plugnz 0.0.22 → 0.0.24

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/plugnz.mjs CHANGED
@@ -6957,8 +6957,17 @@ var require_public_api = __commonJS(function(exports) {
6957
6957
  });
6958
6958
 
6959
6959
  // src/hooks.ts
6960
- import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
6960
+ import { lstatSync as lstatSync8, readFileSync as readFileSync14 } from "node:fs";
6961
6961
  import { isAbsolute as isAbsolute7, join as join19, resolve as resolve10 } from "node:path";
6962
+ function hookEffectGap(required, supported) {
6963
+ for (const effect of HOOK_EFFECTS) {
6964
+ if (required?.[effect] !== true)
6965
+ continue;
6966
+ if (supported?.[effect] !== true)
6967
+ return { effect, status: supported?.[effect] === false ? "unsupported" : "unverified" };
6968
+ }
6969
+ return null;
6970
+ }
6962
6971
  function record(value, label) {
6963
6972
  if (typeof value !== "object" || value === null || Array.isArray(value))
6964
6973
  throw new Error(label + " must be an object");
@@ -6977,8 +6986,9 @@ function text2(value, label, nonblank = true) {
6977
6986
  function validateHookConfig(value) {
6978
6987
  const root = record(value, "Hook configuration");
6979
6988
  keys(root, ["version", "hooks"], "Hook configuration");
6980
- if (root["version"] !== 1)
6981
- throw new Error("Hook configuration version must be 1");
6989
+ const version = root["version"];
6990
+ if (version !== 1 && version !== 2)
6991
+ throw new Error("Hook configuration version must be 1 or 2");
6982
6992
  const sourceHooks = record(root["hooks"], "hooks");
6983
6993
  keys(sourceHooks, HOOK_EVENTS, "hooks");
6984
6994
  const hooks = {};
@@ -6991,7 +7001,22 @@ function validateHookConfig(value) {
6991
7001
  hooks[event] = handlers.map((value, index) => {
6992
7002
  const label = event + "[" + index + "]";
6993
7003
  const handler = record(value, label);
6994
- keys(handler, ["command", "tools", "timeoutMs"], label);
7004
+ keys(handler, version === 1 ? ["command", "tools", "timeoutMs"] : ["command", "tools", "timeoutMs", "requires"], label);
7005
+ let requires;
7006
+ if (version === 2) {
7007
+ const effects = handler["requires"] === undefined ? {} : record(handler["requires"], label + ".requires");
7008
+ keys(effects, HOOK_EFFECTS, label + ".requires");
7009
+ for (const effect of HOOK_EFFECTS) {
7010
+ if (effects[effect] !== undefined && typeof effects[effect] !== "boolean")
7011
+ throw new Error(label + ".requires." + effect + " must be boolean");
7012
+ }
7013
+ requires = { ...effects };
7014
+ if (requires.continue === true && event !== "turn.stop")
7015
+ throw new Error(label + ": continue is only available at turn.stop");
7016
+ if (event === "turn.stop" && requires.context === true !== (requires.continue === true)) {
7017
+ throw new Error(label + ": turn.stop requires context:true and continue:true together");
7018
+ }
7019
+ }
6995
7020
  const command = handler["command"];
6996
7021
  if (!Array.isArray(command) || command.length === 0)
6997
7022
  throw new Error(label + ".command must be a nonempty argv array");
@@ -7009,15 +7034,25 @@ function validateHookConfig(value) {
7009
7034
  if (timeout !== undefined && (typeof timeout !== "number" || !Number.isInteger(timeout) || timeout < 1 || timeout > MAX_HOOK_TIMEOUT_MS)) {
7010
7035
  throw new Error(label + ".timeoutMs must be an integer from 1 to " + MAX_HOOK_TIMEOUT_MS);
7011
7036
  }
7012
- return { command: argv, ...tools === undefined ? {} : { tools }, ...timeout === undefined ? {} : { timeoutMs: timeout } };
7037
+ return { command: argv, ...tools === undefined ? {} : { tools }, ...timeout === undefined ? {} : { timeoutMs: timeout }, ...requires === undefined ? {} : { requires } };
7013
7038
  });
7014
7039
  }
7015
- return { version: 1, hooks };
7040
+ return { version, hooks };
7016
7041
  }
7017
7042
  function readHookConfig(pluginRoot) {
7018
7043
  const path = join19(pluginRoot, HOOK_CONFIG_FILE);
7019
- if (!existsSync15(path))
7020
- return;
7044
+ let stat;
7045
+ try {
7046
+ stat = lstatSync8(path);
7047
+ } catch (error) {
7048
+ if (error.code === "ENOENT")
7049
+ return;
7050
+ throw error;
7051
+ }
7052
+ if (stat.isSymbolicLink())
7053
+ throw new Error("Hook source symlinks are unsupported: " + path);
7054
+ if (!stat.isFile())
7055
+ throw new Error("Hook manifest must be a regular file: " + path);
7021
7056
  let value;
7022
7057
  try {
7023
7058
  value = JSON.parse(readFileSync14(path, "utf8"));
@@ -7026,9 +7061,10 @@ function readHookConfig(pluginRoot) {
7026
7061
  }
7027
7062
  return validateHookConfig(value);
7028
7063
  }
7029
- var HOOK_EVENTS, HOOK_CONFIG_FILE = "plugnz.hooks.json", DEFAULT_HOOK_TIMEOUT_MS = 1e4, MAX_HOOK_TIMEOUT_MS = 60000;
7064
+ var HOOK_EVENTS, HOOK_CONFIG_FILE = "plugnz.hooks.json", DEFAULT_HOOK_TIMEOUT_MS = 1e4, MAX_HOOK_TIMEOUT_MS = 60000, HOOK_EFFECTS;
7030
7065
  var init_hooks = __esm(() => {
7031
7066
  HOOK_EVENTS = ["session.start", "turn.stop", "tool.before", "tool.after"];
7067
+ HOOK_EFFECTS = ["context", "continue"];
7032
7068
  });
7033
7069
 
7034
7070
  // src/hosts/command-hooks.ts
@@ -7111,7 +7147,7 @@ var init_command_hooks = __esm(() => {
7111
7147
  });
7112
7148
 
7113
7149
  // src/hosts/command-hook-manifest.ts
7114
- import { existsSync as existsSync16, mkdirSync, readFileSync as readFileSync15, rmSync, writeFileSync } from "node:fs";
7150
+ import { existsSync as existsSync15, mkdirSync, readFileSync as readFileSync15, rmSync, writeFileSync } from "node:fs";
7115
7151
  import { dirname as dirname4, join as join20 } from "node:path";
7116
7152
  function manifest(path) {
7117
7153
  let parsed;
@@ -7134,13 +7170,13 @@ function manifest(path) {
7134
7170
  function prepareCommandHookManifest(stagingRoot, relativeNativePath, removeRoot) {
7135
7171
  const rootPath = join20(stagingRoot, "plugin.json");
7136
7172
  const nativePath = join20(stagingRoot, relativeNativePath);
7137
- const root = existsSync16(rootPath) ? manifest(rootPath) : undefined;
7173
+ const root = existsSync15(rootPath) ? manifest(rootPath) : undefined;
7138
7174
  if (root) {
7139
7175
  const unsupported = Object.keys(root).find((key) => !IDENTITY_FIELDS.includes(key));
7140
7176
  if (unsupported)
7141
7177
  throw new Error('Hook build cannot project root plugin.json field "' + unsupported + '"; use an explicit native plugin manifest');
7142
7178
  }
7143
- const native = existsSync16(nativePath) ? manifest(nativePath) : undefined;
7179
+ const native = existsSync15(nativePath) ? manifest(nativePath) : undefined;
7144
7180
  if (!native && !root)
7145
7181
  throw new Error("Hook build requires a plugin identity in plugin.json or " + relativeNativePath);
7146
7182
  if (native) {
@@ -7187,6 +7223,33 @@ var init_claude_code_hooks = __esm(() => {
7187
7223
  hookAdapter = { ...adapter, prepare: prepareHookPlugin };
7188
7224
  });
7189
7225
 
7226
+ // src/compatibility.ts
7227
+ function requireCompatible(profile, capability) {
7228
+ const status = profile.capabilities[capability];
7229
+ if (status !== "supported")
7230
+ throw new CompatibilityError(profile.id, capability, status, profile.evidence);
7231
+ }
7232
+ function compatibilityEvidenceId(evidence) {
7233
+ return typeof evidence === "string" && evidence.trim().length > 0 ? evidence : null;
7234
+ }
7235
+ var CompatibilityError;
7236
+ var init_compatibility = __esm(() => {
7237
+ CompatibilityError = class CompatibilityError extends Error {
7238
+ target;
7239
+ capability;
7240
+ status;
7241
+ evidence;
7242
+ constructor(target, capability, status, evidence, diagnostic) {
7243
+ super(diagnostic ?? `target '${target}' is ${status} for ${capability}; evidence: ${evidence}`);
7244
+ this.target = target;
7245
+ this.capability = capability;
7246
+ this.status = status;
7247
+ this.evidence = evidence;
7248
+ this.name = "CompatibilityError";
7249
+ }
7250
+ };
7251
+ });
7252
+
7190
7253
  // src/hosts/codex-hooks.ts
7191
7254
  function prepareHookPlugin2(stagingRoot) {
7192
7255
  prepareCommandHookManifest(stagingRoot, ".codex-plugin/plugin.json", true);
@@ -7530,13 +7593,13 @@ var init_zcode_cli_hooks = __esm(() => {
7530
7593
 
7531
7594
  // src/hook-build.ts
7532
7595
  import { spawnSync as spawnSync3 } from "node:child_process";
7533
- import { cpSync, existsSync as existsSync18, lstatSync as lstatSync9, mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync3, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
7596
+ import { cpSync, existsSync as existsSync17, lstatSync as lstatSync10, mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync3, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
7534
7597
  import { dirname as dirname6, isAbsolute as isAbsolute8, join as join22, relative as relative4, resolve as resolve11 } from "node:path";
7535
7598
  import { fileURLToPath } from "node:url";
7536
7599
  function hookRuntimeSource() {
7537
7600
  const moduleDir = dirname6(fileURLToPath(import.meta.url));
7538
7601
  const source = join22(moduleDir, "hooks.ts");
7539
- if (existsSync18(source) && process.versions["bun"]) {
7602
+ if (existsSync17(source) && process.versions["bun"]) {
7540
7603
  if (developmentRuntime !== undefined)
7541
7604
  return developmentRuntime;
7542
7605
  const built = spawnSync3(process.execPath, ["build", source, "--target=node", "--format=esm"], {
@@ -7553,14 +7616,14 @@ function hookRuntimeSource() {
7553
7616
  return output;
7554
7617
  }
7555
7618
  for (const path of [join22(moduleDir, RUNTIME_FILE), join22(moduleDir, "..", "dist", RUNTIME_FILE)]) {
7556
- if (existsSync18(path))
7619
+ if (existsSync17(path))
7557
7620
  return readFileSync17(path, "utf8");
7558
7621
  }
7559
7622
  throw new Error("Hook runtime is missing from the distribution; rebuild with bun run build");
7560
7623
  }
7561
7624
  function entryExists2(path) {
7562
7625
  try {
7563
- lstatSync9(path);
7626
+ lstatSync10(path);
7564
7627
  return true;
7565
7628
  } catch (error) {
7566
7629
  if (error.code === "ENOENT")
@@ -7576,7 +7639,7 @@ function artifactPath(root, path) {
7576
7639
  let current = root;
7577
7640
  for (const part of path.split("/").slice(0, -1)) {
7578
7641
  current = join22(current, part);
7579
- if (entryExists2(current) && (lstatSync9(current).isSymbolicLink() || !lstatSync9(current).isDirectory())) {
7642
+ if (entryExists2(current) && (lstatSync10(current).isSymbolicLink() || !lstatSync10(current).isDirectory())) {
7580
7643
  throw new Error("Generated hook artifact parent is not an owned directory: " + current);
7581
7644
  }
7582
7645
  }
@@ -7584,8 +7647,15 @@ function artifactPath(root, path) {
7584
7647
  }
7585
7648
  function emitHooksToDirectory(adapter, configValue, stagingRoot) {
7586
7649
  const config = validateHookConfig(configValue);
7650
+ for (const event of HOOK_EVENTS) {
7651
+ for (const [index, handler] of (config.hooks[event] ?? []).entries()) {
7652
+ const gap = hookEffectGap(handler.requires, adapter.capabilities[event]);
7653
+ if (gap !== null)
7654
+ throw new CompatibilityError(adapter.id, "hooks", gap.status, "docs/hooks.md", `${adapter.id}: ${event}[${index}] requires ${gap.effect}, but that effect is ${gap.status}`);
7655
+ }
7656
+ }
7587
7657
  const root = resolve11(stagingRoot);
7588
- if (!existsSync18(root) || lstatSync9(root).isSymbolicLink() || !lstatSync9(root).isDirectory())
7658
+ if (!existsSync17(root) || lstatSync10(root).isSymbolicLink() || !lstatSync10(root).isDirectory())
7589
7659
  throw new Error("Hook staging root must be a directory");
7590
7660
  adapter.prepare?.(root);
7591
7661
  const artifacts = adapter.emit(config);
@@ -7616,7 +7686,7 @@ function copyAuthoredTree(source, destination, top = true) {
7616
7686
  continue;
7617
7687
  const from = join22(source, name);
7618
7688
  const to = join22(destination, name);
7619
- const stat = lstatSync9(from);
7689
+ const stat = lstatSync10(from);
7620
7690
  if (stat.isSymbolicLink())
7621
7691
  throw new Error("Hook source symlinks are unsupported: " + from);
7622
7692
  if (stat.isDirectory())
@@ -7630,7 +7700,7 @@ function copyAuthoredTree(source, destination, top = true) {
7630
7700
  function prospectivePath(path) {
7631
7701
  const suffix = [];
7632
7702
  let parent = resolve11(path);
7633
- while (!existsSync18(parent)) {
7703
+ while (!existsSync17(parent)) {
7634
7704
  const next = dirname6(parent);
7635
7705
  if (next === parent)
7636
7706
  throw new Error("Cannot resolve output ancestor: " + path);
@@ -7641,7 +7711,7 @@ function prospectivePath(path) {
7641
7711
  }
7642
7712
  function buildHooks(pluginDir, targets, outputDir) {
7643
7713
  const requestedSource = resolve11(pluginDir);
7644
- if (!existsSync18(requestedSource) || lstatSync9(requestedSource).isSymbolicLink() || !lstatSync9(requestedSource).isDirectory()) {
7714
+ if (!existsSync17(requestedSource) || lstatSync10(requestedSource).isSymbolicLink() || !lstatSync10(requestedSource).isDirectory()) {
7645
7715
  throw new Error("Hook source must be a directory: " + requestedSource);
7646
7716
  }
7647
7717
  const source = realpathSync3(requestedSource);
@@ -7664,7 +7734,7 @@ function buildHooks(pluginDir, targets, outputDir) {
7664
7734
  const physicalOutput = prospectivePath(output);
7665
7735
  if (physicalOutput === source || physicalOutput.startsWith(source + "/"))
7666
7736
  throw new Error("Hook output must be outside the plugin source");
7667
- if (entryExists2(output) && (lstatSync9(output).isSymbolicLink() || !lstatSync9(output).isDirectory() || readdirSync10(output).length !== 0)) {
7737
+ if (entryExists2(output) && (lstatSync10(output).isSymbolicLink() || !lstatSync10(output).isDirectory() || readdirSync10(output).length !== 0)) {
7668
7738
  throw new Error("Hook output must be absent or an empty directory: " + output);
7669
7739
  }
7670
7740
  mkdirSync2(dirname6(output), { recursive: true });
@@ -7686,6 +7756,7 @@ function buildHooks(pluginDir, targets, outputDir) {
7686
7756
  var hookAdapters, RUNTIME_FILE = "hook-runtime.mjs", developmentRuntime;
7687
7757
  var init_hook_build = __esm(() => {
7688
7758
  init_hooks();
7759
+ init_compatibility();
7689
7760
  init_claude_code_hooks();
7690
7761
  init_codex_hooks();
7691
7762
  init_omp_hooks();
@@ -7708,6 +7779,7 @@ function runHookCli(args) {
7708
7779
  throw new Error("targets takes no arguments");
7709
7780
  console.log(JSON.stringify({
7710
7781
  version: 1,
7782
+ configVersions: [1, 2],
7711
7783
  targets: hookAdapters.map(({ id, baselineVersion, capabilities }) => ({ id, baselineVersion, capabilities }))
7712
7784
  }, null, 2));
7713
7785
  return 0;
@@ -13085,28 +13157,21 @@ function formatFinding(f) {
13085
13157
  // src/hosts/claude-code-writer.ts
13086
13158
  init_claude_code_hooks();
13087
13159
 
13088
- // src/compatibility.ts
13089
- class CompatibilityError extends Error {
13090
- target;
13091
- capability;
13092
- status;
13093
- evidence;
13094
- constructor(target, capability, status, evidence, diagnostic) {
13095
- super(diagnostic ?? `target '${target}' is ${status} for ${capability}; evidence: ${evidence}`);
13096
- this.target = target;
13097
- this.capability = capability;
13098
- this.status = status;
13099
- this.evidence = evidence;
13100
- this.name = "CompatibilityError";
13101
- }
13102
- }
13103
- function requireCompatible(profile, capability) {
13104
- const status = profile.capabilities[capability];
13105
- if (status !== "supported")
13106
- throw new CompatibilityError(profile.id, capability, status, profile.evidence);
13107
- }
13108
- function compatibilityEvidenceId(evidence) {
13109
- return typeof evidence === "string" && evidence.trim().length > 0 ? evidence : null;
13160
+ // src/capability-evidence.ts
13161
+ init_compatibility();
13162
+
13163
+ // src/installation-verification.ts
13164
+ function installationVerification(report) {
13165
+ return {
13166
+ schemaVersion: 1,
13167
+ operations: report.outcomes.filter((outcome) => outcome.coverage === "desired-pair").map((outcome) => ({
13168
+ operationId: outcome.operationId,
13169
+ compatibility: outcome.reason?.code === "capability.unsupported" ? "unsupported" : outcome.reason?.code === "capability.unverified" ? "unverified" : outcome.result === "succeeded" ? "admitted" : "unknown",
13170
+ registration: report.command.dryRun ? "not-checked" : outcome.result === "succeeded" && outcome.resourceState === "present" && outcome.activationState === "active-conforming" ? "verified" : "unknown",
13171
+ executionApproval: "not-checked",
13172
+ delivery: "not-observed"
13173
+ }))
13174
+ };
13110
13175
  }
13111
13176
 
13112
13177
  // src/error-diagnostic.ts
@@ -13209,7 +13274,7 @@ function parseLifecycleReport(value) {
13209
13274
  if (!isObject2(value)) {
13210
13275
  throw invalid4("lifecycle report must be an object");
13211
13276
  }
13212
- exactFields3(value, ["schemaVersion", "command", "plan", "outcomes", "summary", "recovery", "adoptions"], "lifecycle report");
13277
+ exactFields3(value, ["schemaVersion", "command", "plan", "outcomes", "summary", "recovery", "adoptions", "verification"], "lifecycle report");
13213
13278
  if (value["schemaVersion"] !== LIFECYCLE_REPORT_SCHEMA_VERSION) {
13214
13279
  throw invalid4("lifecycle report schemaVersion must be 1");
13215
13280
  }
@@ -13321,6 +13386,14 @@ function parseLifecycleReport(value) {
13321
13386
  assertAdoptionRecoveryStatus(receipt, modern);
13322
13387
  }
13323
13388
  assertSummary(summary, outcomes, command["dryRun"], receipts, adoptions);
13389
+ if (value["verification"] !== undefined) {
13390
+ if (commandName !== "add" && commandName !== "update")
13391
+ throw invalid4("installation verification only applies to add/update");
13392
+ const expected = installationVerification(value);
13393
+ if (canonicalAdoptionJson(value["verification"]) !== canonicalAdoptionJson(expected)) {
13394
+ throw contradiction("installation verification contradicts its outcomes or claims unobserved approval/delivery");
13395
+ }
13396
+ }
13324
13397
  return value;
13325
13398
  }
13326
13399
  function matchesAdoptionRecovery(record, receipt) {
@@ -13820,7 +13893,7 @@ function isObject2(value) {
13820
13893
 
13821
13894
  // src/semantic-inventory.ts
13822
13895
  init_hooks();
13823
- import { existsSync as existsSync17, lstatSync as lstatSync8, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "node:fs";
13896
+ import { existsSync as existsSync16, lstatSync as lstatSync9, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "node:fs";
13824
13897
  import { dirname as dirname5, join as join21, relative as relative3 } from "node:path";
13825
13898
  var PACKAGE_SEMANTICS = [
13826
13899
  "ordinary-skills",
@@ -13874,7 +13947,14 @@ function inventoryPackageSemantics(plugin) {
13874
13947
  events,
13875
13948
  handlerTypes: ["command"],
13876
13949
  handlerFacets: [],
13877
- groups: events.map((event) => ({ event, matcher: null, matcherKind: "all", handlerTypes: ["command"], handlerFacets: [] }))
13950
+ groups: portableHooks.version === 1 ? events.map((event) => ({ event, matcher: null, matcherKind: "all", handlerTypes: ["command"], handlerFacets: [] })) : events.flatMap((event) => (portableHooks.hooks[event] ?? []).map((handler) => ({
13951
+ event,
13952
+ matcher: null,
13953
+ matcherKind: "all",
13954
+ handlerTypes: ["command"],
13955
+ handlerFacets: [],
13956
+ requiredEffects: handler.requires ?? {}
13957
+ })))
13878
13958
  });
13879
13959
  }
13880
13960
  const resources = files.filter((path) => (["assets/", "references/", "resources/"].some((root) => path.startsWith(root)) || path.startsWith("skills/") && !path.endsWith("/SKILL.md") || path.startsWith("hooks/") || path.startsWith(".claude/hooks/")) && !sidecars.has(path) && !hookInventory.configPaths.has(path));
@@ -14011,7 +14091,7 @@ function inventorySkillPolicy(root, skill) {
14011
14091
  }
14012
14092
  }
14013
14093
  const sidecar = `${dirname5(skill)}/agents/openai.yaml`;
14014
- if (existsSync17(join21(root, sidecar))) {
14094
+ if (existsSync16(join21(root, sidecar))) {
14015
14095
  const parsed = parseYamlObject(readFileSync16(join21(root, sidecar), "utf8"), `Codex invocation sidecar ${sidecar}`);
14016
14096
  const policy = parsed["policy"];
14017
14097
  if (policy !== undefined) {
@@ -14095,7 +14175,7 @@ function readSemanticManifests(root) {
14095
14175
  ".plugin/plugin.json",
14096
14176
  ".claude-plugin/plugin.json",
14097
14177
  ".codex-plugin/plugin.json"
14098
- ].filter((path) => existsSync17(join21(root, path))).map((path) => ({
14178
+ ].filter((path) => existsSync16(join21(root, path))).map((path) => ({
14099
14179
  ...parseJsonObject(join21(root, path), `plugin manifest ${path}`),
14100
14180
  path
14101
14181
  }));
@@ -14183,13 +14263,13 @@ function declaredHookPath(root, declaration) {
14183
14263
  invalid5(`declared hook path must be a canonical file inside the plugin root: ${declaration}`);
14184
14264
  }
14185
14265
  const absolute = join21(root, path);
14186
- if (!existsSync17(absolute))
14266
+ if (!existsSync16(absolute))
14187
14267
  invalid5(`declared hook configuration does not exist: ${declaration}`);
14188
- const stat = lstatSync8(absolute);
14268
+ const stat = lstatSync9(absolute);
14189
14269
  if (stat.isDirectory()) {
14190
14270
  const document = `${path}/hooks.json`;
14191
14271
  const documentPath = join21(root, document);
14192
- if (!existsSync17(documentPath) || !lstatSync8(documentPath).isFile()) {
14272
+ if (!existsSync16(documentPath) || !lstatSync9(documentPath).isFile()) {
14193
14273
  invalid5(`declared hook directory must contain hooks.json: ${declaration}`);
14194
14274
  }
14195
14275
  return { path: document, directory: true };
@@ -14301,7 +14381,7 @@ function walkFiles(root) {
14301
14381
  if (entry === ".git" || entry === "node_modules" || entry === ".plgnz-install.json")
14302
14382
  continue;
14303
14383
  const path = join21(dir, entry);
14304
- const stat = lstatSync8(path);
14384
+ const stat = lstatSync9(path);
14305
14385
  if (stat.isSymbolicLink())
14306
14386
  invalid5(`package semantic inventory refuses symlink: ${portable(relative3(root, path))}`);
14307
14387
  if (stat.isDirectory())
@@ -14324,7 +14404,7 @@ var COMPONENT_ROOT_SPECS = [
14324
14404
  var UNSUPPORTED_COMPONENT_ROOTS = [".codex/commands", ".codex/agents"];
14325
14405
  function inventoryComponentRoots(root) {
14326
14406
  for (const unsupported of UNSUPPORTED_COMPONENT_ROOTS) {
14327
- if (existsSync17(join21(root, unsupported)))
14407
+ if (existsSync16(join21(root, unsupported)))
14328
14408
  invalid5(`unsupported component root: ${unsupported}`);
14329
14409
  }
14330
14410
  const definitions = [];
@@ -14332,9 +14412,9 @@ function inventoryComponentRoots(root) {
14332
14412
  const permissionPaths = new Set;
14333
14413
  for (const spec of COMPONENT_ROOT_SPECS) {
14334
14414
  const directory = join21(root, spec.root);
14335
- if (!existsSync17(directory))
14415
+ if (!existsSync16(directory))
14336
14416
  continue;
14337
- const rootStat = lstatSync8(directory);
14417
+ const rootStat = lstatSync9(directory);
14338
14418
  if (!rootStat.isDirectory())
14339
14419
  invalid5(`component root must be a directory: ${spec.root}`);
14340
14420
  const entries = readdirSync9(directory).sort();
@@ -14344,7 +14424,7 @@ function inventoryComponentRoots(root) {
14344
14424
  for (const entry of entries) {
14345
14425
  const absolute = join21(directory, entry);
14346
14426
  const path = `${spec.root}/${entry}`;
14347
- const stat = lstatSync8(absolute);
14427
+ const stat = lstatSync9(absolute);
14348
14428
  if (!stat.isFile())
14349
14429
  invalid5(`component root entries must be regular files: ${path}`);
14350
14430
  const suffix = Object.keys(spec.dialects).find((candidate) => entry.endsWith(candidate));
@@ -14474,6 +14554,8 @@ var PERMISSION_FIELDS = [
14474
14554
  ];
14475
14555
 
14476
14556
  // src/capability-evidence.ts
14557
+ init_hooks();
14558
+
14477
14559
  class PackageCapabilityError extends CompatibilityError {
14478
14560
  gaps;
14479
14561
  constructor(target, admission) {
@@ -14704,6 +14786,9 @@ function hookDeclarationProblem(declaration, selectedManifest, policy) {
14704
14786
  const unsupportedFacet = group.handlerFacets.find((facet) => policy.unsupportedHandlerFacets.includes(facet));
14705
14787
  if (unsupportedFacet !== undefined)
14706
14788
  return unsupportedHookProblem(hookHandlerFacetProblem(unsupportedFacet));
14789
+ const gap = hookEffectGap(group.requiredEffects, policy.supportedEffects?.[group.event]);
14790
+ if (gap !== null)
14791
+ return { status: gap.status, diagnostic: `event '${group.event}' requires ${gap.effect}, but that effect is ${gap.status}` };
14707
14792
  }
14708
14793
  return null;
14709
14794
  }
@@ -14737,7 +14822,16 @@ function normalizeHookPolicy(input) {
14737
14822
  const matcherlessEvents = uniqueStrings(input.matcherlessEvents, "matcherless hook event").sort();
14738
14823
  const supportedMatcherKinds = uniqueStrings(input.supportedMatcherKinds, "hook matcher kind").sort();
14739
14824
  const unsupportedHandlerFacets = uniqueStrings(input.unsupportedHandlerFacets, "unsupported hook handler facet").sort();
14825
+ let supportedEffects;
14826
+ if (input.supportedEffects !== undefined) {
14827
+ supportedEffects = Object.freeze(Object.fromEntries(Object.entries(input.supportedEffects).sort(([a], [b]) => a.localeCompare(b)).map(([event, effects]) => {
14828
+ if (!supportedEvents.includes(event) || effects === null || typeof effects !== "object" || Array.isArray(effects) || Object.keys(effects).some((key) => !HOOK_EFFECTS.includes(key)) || Object.values(effects).some((value) => typeof value !== "boolean"))
14829
+ throw new Error("Invalid hook effect evidence for " + event);
14830
+ return [event, Object.freeze(Object.fromEntries(HOOK_EFFECTS.filter((effect) => effects[effect] !== undefined).map((effect) => [effect, effects[effect]])))];
14831
+ })));
14832
+ }
14740
14833
  return Object.freeze({
14834
+ ...supportedEffects === undefined ? {} : { supportedEffects },
14741
14835
  manifestPrecedence: Object.freeze(manifestPrecedence),
14742
14836
  supportedForms: Object.freeze(supportedForms),
14743
14837
  supportedEvents: Object.freeze(supportedEvents),
@@ -14788,6 +14882,7 @@ function portableHookProfile(adapter, route, operations) {
14788
14882
  supported.has(semantic) ? "supported" : "unsupported"
14789
14883
  ])),
14790
14884
  hookPolicy: {
14885
+ supportedEffects: Object.fromEntries(HOOK_EVENTS.map((event) => [event, { context: adapter.capabilities[event].context, continue: adapter.capabilities[event].continue }])),
14791
14886
  manifestPrecedence: ["plugin.json", ".plugin/plugin.json", ".claude-plugin/plugin.json", ".codex-plugin/plugin.json", ".zcode-plugin/plugin.json"],
14792
14887
  supportedForms: ["portable-hooks"],
14793
14888
  supportedEvents: HOOK_EVENTS,
@@ -14803,7 +14898,7 @@ function portableHookProfile(adapter, route, operations) {
14803
14898
  // src/hook-install.ts
14804
14899
  init_hook_build();
14805
14900
  init_hooks();
14806
- import { cpSync as cpSync2, existsSync as existsSync19, mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync18, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
14901
+ import { cpSync as cpSync2, existsSync as existsSync18, mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync18, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
14807
14902
  import { join as join23 } from "node:path";
14808
14903
  import { tmpdir } from "node:os";
14809
14904
  function preflightPortableHooks(adapter, source) {
@@ -14820,9 +14915,9 @@ function compilePortableHooksInStage(adapter, stage, options = {}) {
14820
14915
  const config = readHookConfig(stage);
14821
14916
  if (config === undefined)
14822
14917
  return false;
14823
- if (options.retainCanonicalIdentity && existsSync19(join23(stage, "plugin.json"))) {
14918
+ if (options.retainCanonicalIdentity && existsSync18(join23(stage, "plugin.json"))) {
14824
14919
  const identity = join23(stage, ".plugin", "plugin.json");
14825
- if (!existsSync19(identity)) {
14920
+ if (!existsSync18(identity)) {
14826
14921
  mkdirSync3(join23(stage, ".plugin"), { recursive: true });
14827
14922
  cpSync2(join23(stage, "plugin.json"), identity);
14828
14923
  }
@@ -14844,18 +14939,18 @@ function registerProjectedExtension(stage, key, entry) {
14844
14939
  }
14845
14940
 
14846
14941
  // src/hosts/claude-code-writer.ts
14847
- import { cpSync as cpSync5, existsSync as existsSync22, lstatSync as lstatSync12, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync5, readFileSync as readFileSync21, readdirSync as readdirSync13, renameSync as renameSync3, rmSync as rmSync6, statSync as statSync9, writeFileSync as writeFileSync6 } from "node:fs";
14942
+ import { cpSync as cpSync5, existsSync as existsSync21, lstatSync as lstatSync13, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync5, readFileSync as readFileSync21, readdirSync as readdirSync13, renameSync as renameSync3, rmSync as rmSync6, statSync as statSync9, writeFileSync as writeFileSync6 } from "node:fs";
14848
14943
  import { dirname as dirname8, join as join27, relative as relative7, resolve as resolve15 } from "node:path";
14849
14944
  import { tmpdir as tmpdir2 } from "node:os";
14850
14945
 
14851
14946
  // src/conversion.ts
14852
- import { cpSync as cpSync4, existsSync as existsSync21, lstatSync as lstatSync11, mkdirSync as mkdirSync5, mkdtempSync as mkdtempSync4, readFileSync as readFileSync20, readdirSync as readdirSync12, rmSync as rmSync5, statSync as statSync8, writeFileSync as writeFileSync4 } from "node:fs";
14947
+ import { cpSync as cpSync4, existsSync as existsSync20, lstatSync as lstatSync12, mkdirSync as mkdirSync5, mkdtempSync as mkdtempSync4, readFileSync as readFileSync20, readdirSync as readdirSync12, rmSync as rmSync5, statSync as statSync8, writeFileSync as writeFileSync4 } from "node:fs";
14853
14948
  import { basename as basename3, dirname as dirname7, join as join25, resolve as resolve13 } from "node:path";
14854
14949
  import { spawnSync as spawnSync5 } from "node:child_process";
14855
14950
 
14856
14951
  // src/source.ts
14857
14952
  import { spawnSync as spawnSync4 } from "node:child_process";
14858
- import { cpSync as cpSync3, existsSync as existsSync20, lstatSync as lstatSync10, mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync3, readFileSync as readFileSync19, readdirSync as readdirSync11, renameSync as renameSync2, rmSync as rmSync4, statSync as statSync7 } from "node:fs";
14953
+ import { cpSync as cpSync3, existsSync as existsSync19, lstatSync as lstatSync11, mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync3, readFileSync as readFileSync19, readdirSync as readdirSync11, renameSync as renameSync2, rmSync as rmSync4, statSync as statSync7 } from "node:fs";
14859
14954
  import { join as join24, basename as basename2, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve12 } from "node:path";
14860
14955
  function resolveSource(source) {
14861
14956
  const parsed = parseSource(source);
@@ -14870,7 +14965,7 @@ function resolveSource(source) {
14870
14965
  targetDir = freezeRemoteSource(parsed.fetchLocator, sha, parsed.binding.locator);
14871
14966
  } else {
14872
14967
  targetDir = sourceUri;
14873
- if (!existsSync20(targetDir))
14968
+ if (!existsSync19(targetDir))
14874
14969
  throw new Error(`Local source not found: ${targetDir}`);
14875
14970
  targetDir = assertSafeSourceTree(targetDir);
14876
14971
  sourceRoot = targetDir;
@@ -14895,7 +14990,7 @@ function resolveSource(source) {
14895
14990
  const mp1 = join24(targetDir, ".claude-plugin", "marketplace.json");
14896
14991
  const mp2 = join24(targetDir, ".omp-plugin", "marketplace.json");
14897
14992
  const mp3 = join24(targetDir, "marketplace.json");
14898
- const mpPath = existsSync20(mp1) ? mp1 : existsSync20(mp2) ? mp2 : existsSync20(mp3) ? mp3 : null;
14993
+ const mpPath = existsSync19(mp1) ? mp1 : existsSync19(mp2) ? mp2 : existsSync19(mp3) ? mp3 : null;
14899
14994
  if (mpPath !== null) {
14900
14995
  const data = parseMarketplace(mpPath);
14901
14996
  const marketplaceName = typeof data["name"] === "string" ? data["name"] : "local";
@@ -14912,7 +15007,7 @@ function resolveSource(source) {
14912
15007
  const pDir = resolve12(targetDir, entry["source"]);
14913
15008
  if (!isInside(targetDir, pDir))
14914
15009
  throw new Error(`Marketplace plugin source escapes collection root: ${entry["source"]}`);
14915
- if (!existsSync20(pDir) || !statSync7(pDir).isDirectory())
15010
+ if (!existsSync19(pDir) || !statSync7(pDir).isDirectory())
14916
15011
  throw new Error(`Marketplace plugin source is not a directory: ${entry["source"]}`);
14917
15012
  plugins.push(pluginFromDir(pDir, marketplaceName, targetDir, sourceRoot));
14918
15013
  }
@@ -14967,7 +15062,7 @@ function freezeLocalSource(source) {
14967
15062
  if (fingerprintTree(verification) !== fingerprint)
14968
15063
  throw new Error(`Local source changed while it was being frozen: ${source}`);
14969
15064
  const target = join24(snapshots, fingerprint);
14970
- if (existsSync20(target)) {
15065
+ if (existsSync19(target)) {
14971
15066
  if (fingerprintTree(assertSafeSourceTree(target)) !== fingerprint)
14972
15067
  throw new Error(`Cached Source snapshot is corrupt: ${target}`);
14973
15068
  return target;
@@ -14985,7 +15080,7 @@ function copySourceTree(source, destination) {
14985
15080
  continue;
14986
15081
  const from = join24(source, entry);
14987
15082
  const to = join24(destination, entry);
14988
- const stat = lstatSync10(from);
15083
+ const stat = lstatSync11(from);
14989
15084
  if (stat.isSymbolicLink())
14990
15085
  throw new Error(`Symlink resources are not supported: ${from}`);
14991
15086
  if (stat.isDirectory()) {
@@ -15034,9 +15129,9 @@ function parseSource(source) {
15034
15129
  }
15035
15130
  function canonicalLocalArgument(source) {
15036
15131
  const path = resolve12(source);
15037
- if (!existsSync20(path))
15132
+ if (!existsSync19(path))
15038
15133
  return path;
15039
- if (lstatSync10(path).isSymbolicLink())
15134
+ if (lstatSync11(path).isSymbolicLink())
15040
15135
  throw new Error(`Symlink resources are not supported: ${path}`);
15041
15136
  return realpath(path);
15042
15137
  }
@@ -15108,7 +15203,7 @@ function freezeRemoteSource(fetchLocator, revision, displayLocator) {
15108
15203
  rmSync4(join24(candidate, ".git"), { recursive: true, force: true });
15109
15204
  const fingerprint = fingerprintTree(candidate);
15110
15205
  const target = join24(snapshots, fingerprint);
15111
- if (existsSync20(target)) {
15206
+ if (existsSync19(target)) {
15112
15207
  if (fingerprintTree(assertSafeSourceTree(target)) !== fingerprint)
15113
15208
  throw new Error(`Cached Source snapshot is corrupt: ${target}`);
15114
15209
  return target;
@@ -15167,12 +15262,12 @@ function isRecord3(value) {
15167
15262
  return typeof value === "object" && value !== null && !Array.isArray(value);
15168
15263
  }
15169
15264
  function isPluginDir(dir) {
15170
- return manifestPaths(dir).some(existsSync20) || existsSync20(join24(dir, ".mcp.json")) || existsSync20(join24(dir, "mcp.json"));
15265
+ return manifestPaths(dir).some(existsSync19) || existsSync19(join24(dir, ".mcp.json")) || existsSync19(join24(dir, "mcp.json"));
15171
15266
  }
15172
15267
  function readPluginManifest(dir) {
15173
15268
  let selected;
15174
15269
  for (const path of manifestPaths(dir)) {
15175
- if (!existsSync20(path))
15270
+ if (!existsSync19(path))
15176
15271
  continue;
15177
15272
  const current = parsePluginManifest(path);
15178
15273
  if (selected === undefined) {
@@ -15221,7 +15316,7 @@ var UNSUPPORTED_CLAUDE_COMPONENTS = new Set(["agents", "hooks", "mcpServers", "o
15221
15316
  function projectPluginForCodex(sourceDir, destinationDir) {
15222
15317
  const source = resolve13(sourceDir);
15223
15318
  const destination = resolve13(destinationDir);
15224
- if (!existsSync21(source) || !statSync8(source).isDirectory())
15319
+ if (!existsSync20(source) || !statSync8(source).isDirectory())
15225
15320
  throw new Error(`plugin source is not a directory: ${source}`);
15226
15321
  if (destination === source || destination.startsWith(`${source}/`))
15227
15322
  throw new Error("destination must not be inside the plugin source");
@@ -15250,7 +15345,7 @@ function projectPluginForCodex(sourceDir, destinationDir) {
15250
15345
  function projectPluginForOmp(sourceDir, destinationDir, options) {
15251
15346
  const source = resolve13(sourceDir);
15252
15347
  const destination = resolve13(destinationDir);
15253
- if (!existsSync21(source) || !statSync8(source).isDirectory())
15348
+ if (!existsSync20(source) || !statSync8(source).isDirectory())
15254
15349
  throw new Error(`plugin source is not a directory: ${source}`);
15255
15350
  if (destination === source || destination.startsWith(`${source}/`))
15256
15351
  throw new Error("destination must not be inside the plugin source");
@@ -15275,11 +15370,11 @@ function projectPluginForOmp(sourceDir, destinationDir, options) {
15275
15370
  writeOmpCommand(destination, `${options.namespace}:${command.name}`, command.description, command.argumentHint, rewriteOmpCommandReferences(command.body, commandNames, options.namespace), join25(options.activeRoot, ".plgnz", "source", relativeCommandBase(source, command.source)), projected);
15276
15371
  }
15277
15372
  const skills = join25(source, "skills");
15278
- if (existsSync21(skills)) {
15373
+ if (existsSync20(skills)) {
15279
15374
  for (const entry of readdirSync12(skills).sort()) {
15280
15375
  const skillDir = join25(skills, entry);
15281
15376
  const skillFile = join25(skillDir, "SKILL.md");
15282
- if (!statSync8(skillDir).isDirectory() || !existsSync21(skillFile))
15377
+ if (!statSync8(skillDir).isDirectory() || !existsSync20(skillFile))
15283
15378
  continue;
15284
15379
  const parsed = parseManualSkill(skillDir);
15285
15380
  if (parsed.userInvocable === false)
@@ -15348,7 +15443,7 @@ function parseManualSkill(directory) {
15348
15443
  if (hint !== undefined && typeof hint !== "string")
15349
15444
  throw new Error(`argument hint must be text: ${path}`);
15350
15445
  const sidecar = join25(directory, "agents", "openai.yaml");
15351
- const implicit = existsSync21(sidecar) ? readImplicitPolicy(sidecar) : undefined;
15446
+ const implicit = existsSync20(sidecar) ? readImplicitPolicy(sidecar) : undefined;
15352
15447
  if (implicit !== undefined && typeof manual === "boolean" && implicit === manual)
15353
15448
  throw new Error(`conflicting invocation policy for native skill ${name}`);
15354
15449
  return { name, description, ...typeof hint === "string" ? { argumentHint: hint } : {}, ...typeof userInvocable === "boolean" ? { userInvocable } : {}, manual: manual === true || implicit === false, body: match[2] ?? "", metadata };
@@ -15369,7 +15464,7 @@ ${match[2] ?? ""}`);
15369
15464
  function projectPluginForHermes(sourceDir, destinationDir, companionDir) {
15370
15465
  const source = resolve13(sourceDir);
15371
15466
  const destination = resolve13(destinationDir);
15372
- if (!existsSync21(source) || !statSync8(source).isDirectory())
15467
+ if (!existsSync20(source) || !statSync8(source).isDirectory())
15373
15468
  throw new Error(`plugin source is not a directory: ${source}`);
15374
15469
  if (destination === source || destination.startsWith(`${source}/`))
15375
15470
  throw new Error("destination must not be inside the plugin source");
@@ -15490,11 +15585,11 @@ Use skill_view with the exact qualified name when a listed skill matches the tas
15490
15585
  }
15491
15586
  function projectHermesSkills(stage) {
15492
15587
  const root = join25(stage, "skills");
15493
- if (!existsSync21(root))
15588
+ if (!existsSync20(root))
15494
15589
  return [];
15495
15590
  const result = readdirSync12(root).sort().flatMap((entry) => {
15496
15591
  const skill = join25(root, entry, "SKILL.md");
15497
- if (!existsSync21(skill))
15592
+ if (!existsSync20(skill))
15498
15593
  return [];
15499
15594
  const match = readFileSync20(skill, "utf8").match(/^---\r?\n([\s\S]*?)\r?\n---/);
15500
15595
  if (match === null)
@@ -15515,7 +15610,7 @@ function projectHermesSkills(stage) {
15515
15610
  }
15516
15611
  function validateClaudeNativeSemantics(source, commands) {
15517
15612
  const file = join25(source, ".claude-plugin", "plugin.json");
15518
- if (!existsSync21(file))
15613
+ if (!existsSync20(file))
15519
15614
  return;
15520
15615
  const parsed = JSON.parse(readFileSync20(file, "utf8"));
15521
15616
  if (!isRecord4(parsed))
@@ -15527,7 +15622,7 @@ function validateClaudeNativeSemantics(source, commands) {
15527
15622
  if (parsed["skills"] !== undefined && parsed["skills"] !== "./skills" && parsed["skills"] !== "./skills/") {
15528
15623
  throw new Error(`Claude native skills pointer is unsupported for Codex conversion: ${file}`);
15529
15624
  }
15530
- if (parsed["skills"] !== undefined && (!existsSync21(join25(source, "skills")) || !statSync8(join25(source, "skills")).isDirectory())) {
15625
+ if (parsed["skills"] !== undefined && (!existsSync20(join25(source, "skills")) || !statSync8(join25(source, "skills")).isDirectory())) {
15531
15626
  throw new Error(`Claude native skills pointer cannot be preserved for Codex conversion: ${file}`);
15532
15627
  }
15533
15628
  if (parsed["commands"] === undefined)
@@ -15550,10 +15645,10 @@ function assertSafeTree(root) {
15550
15645
  }
15551
15646
  function discoverCommands(source) {
15552
15647
  const claude = join25(source, ".claude", "commands");
15553
- if (existsSync21(claude))
15648
+ if (existsSync20(claude))
15554
15649
  return readCommandDirectory(claude, "markdown");
15555
15650
  const root = join25(source, "commands");
15556
- if (!existsSync21(root))
15651
+ if (!existsSync20(root))
15557
15652
  return [];
15558
15653
  const markdown = readCommandDirectory(root, "markdown");
15559
15654
  return markdown.length > 0 ? markdown : readCommandDirectory(root, "toml");
@@ -15626,7 +15721,7 @@ function commandFrom(path, description, argumentHint, userInvocable, disableMode
15626
15721
  }
15627
15722
  function normalizeCommandSources(root) {
15628
15723
  const dir = join25(root, "commands");
15629
- if (!existsSync21(dir))
15724
+ if (!existsSync20(dir))
15630
15725
  return;
15631
15726
  if (!statSync8(dir).isDirectory())
15632
15727
  throw new Error(`commands path is not a directory: ${dir}`);
@@ -15635,7 +15730,7 @@ function normalizeCommandSources(root) {
15635
15730
  function normalizeCommandTree(dir) {
15636
15731
  const stats = readdirSync12(dir).sort().map((name) => {
15637
15732
  const path = join25(dir, name);
15638
- const stat = lstatSync11(path);
15733
+ const stat = lstatSync12(path);
15639
15734
  if (stat.isSymbolicLink())
15640
15735
  throw new Error(`command source contains symlink: ${path}`);
15641
15736
  return { name, path, isDirectory: stat.isDirectory(), isFile: stat.isFile() };
@@ -15673,7 +15768,7 @@ ${body}` };
15673
15768
  function projectPluginForPi(sourceDir, destinationDir, namespace) {
15674
15769
  const source = resolve13(sourceDir);
15675
15770
  const destination = resolve13(destinationDir);
15676
- if (!existsSync21(source) || !statSync8(source).isDirectory())
15771
+ if (!existsSync20(source) || !statSync8(source).isDirectory())
15677
15772
  throw new Error(`plugin source is not a directory: ${source}`);
15678
15773
  if (destination === source || destination.startsWith(`${source}/`))
15679
15774
  throw new Error("destination must not be inside the plugin source");
@@ -15691,7 +15786,7 @@ function writePiCommandSkill(stage, command, namespace, names) {
15691
15786
  if (command.userInvocable === false)
15692
15787
  throw new Error(`user-invocable: false has no proven Pi skill equivalent: ${command.source}`);
15693
15788
  const skillDir = join25(stage, "skills", command.name);
15694
- if (existsSync21(skillDir))
15789
+ if (existsSync20(skillDir))
15695
15790
  throw new Error(`collision: command ${command.name} would replace an existing skill`);
15696
15791
  const body = command.body.replace(/\$ARGUMENTS\b/gu, "the text after this /skill invocation").replace(/(^|[^A-Za-z0-9_-])\/([a-z0-9][a-z0-9-]*)(?=\s|$|[.,:;!?])/giu, (whole, prefix, name) => names.has(name) ? `${prefix}/skill:${namespace}-${name}` : whole);
15697
15792
  mkdirSync5(skillDir, { recursive: true });
@@ -15718,7 +15813,7 @@ function validateMetadata(metadata, path) {
15718
15813
  }
15719
15814
  function writeCommandSkill(stage, command, namespace, commandNames) {
15720
15815
  const skillDir = join25(stage, "skills", command.name);
15721
- if (existsSync21(skillDir))
15816
+ if (existsSync20(skillDir))
15722
15817
  throw new Error(`collision: command ${command.name} would replace an existing skill`);
15723
15818
  const body = command.body.replace(/\$ARGUMENTS\b/gu, "the invocation tail").replace(/(^|[^A-Za-z0-9_-])\/([a-z0-9][a-z0-9-]*)(?=\s|$|[.,:;!?])/giu, (whole, prefix, name) => commandNames.has(name) ? `${prefix}$${namespace}:${name}` : whole);
15724
15819
  const hint = command.argumentHint === undefined ? "" : `argument-hint: ${yamlString(command.argumentHint)}
@@ -15755,7 +15850,7 @@ function hermesSkillUserOnly(skill, metadata) {
15755
15850
  if (user === false)
15756
15851
  throw new Error(`Hermes cannot preserve user-invocable: false: ${skill}`);
15757
15852
  const sidecar = join25(dirname7(skill), "agents", "openai.yaml");
15758
- const implicit = existsSync21(sidecar) ? readImplicitPolicy(sidecar) : undefined;
15853
+ const implicit = existsSync20(sidecar) ? readImplicitPolicy(sidecar) : undefined;
15759
15854
  if (disable !== undefined && implicit !== undefined && implicit !== !disable)
15760
15855
  throw new Error(`conflicting invocation policy for Hermes skill ${skill}`);
15761
15856
  const userOnly = disable === true || implicit === false;
@@ -15781,14 +15876,14 @@ ${yamlStringify(metadata).trimEnd()}
15781
15876
  }
15782
15877
  function translateNativeSkillPolicies(stage) {
15783
15878
  const skills = join25(stage, "skills");
15784
- if (!existsSync21(skills))
15879
+ if (!existsSync20(skills))
15785
15880
  return;
15786
15881
  for (const entry of readdirSync12(skills)) {
15787
15882
  const skill = join25(skills, entry);
15788
15883
  if (!statSync8(skill).isDirectory())
15789
15884
  continue;
15790
15885
  const file = join25(skill, "SKILL.md");
15791
- if (!existsSync21(file))
15886
+ if (!existsSync20(file))
15792
15887
  continue;
15793
15888
  const source = readFileSync20(file, "utf8");
15794
15889
  const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---/);
@@ -15796,7 +15891,7 @@ function translateNativeSkillPolicies(stage) {
15796
15891
  const manual = metadata["disable-model-invocation"] === true;
15797
15892
  const automatic = metadata["disable-model-invocation"] === false;
15798
15893
  const sidecar = join25(skill, "agents", "openai.yaml");
15799
- if (existsSync21(sidecar)) {
15894
+ if (existsSync20(sidecar)) {
15800
15895
  const policy = readImplicitPolicy(sidecar);
15801
15896
  if (policy !== undefined && (manual && policy !== false || automatic && policy !== true)) {
15802
15897
  throw new Error(`conflicting invocation policy for native skill ${entry}`);
@@ -15824,7 +15919,7 @@ function readImplicitPolicy(path) {
15824
15919
  return policy["allow_implicit_invocation"];
15825
15920
  }
15826
15921
  function writePolicy(path, allowImplicit) {
15827
- const existing = existsSync21(path) ? readFileSync20(path, "utf8").replace(/\s*$/u, "") : "";
15922
+ const existing = existsSync20(path) ? readFileSync20(path, "utf8").replace(/\s*$/u, "") : "";
15828
15923
  const suffix = `policy:
15829
15924
  allow_implicit_invocation: ${allowImplicit}
15830
15925
  `;
@@ -17658,7 +17753,7 @@ var claudeCodeWriter = {
17658
17753
  const marketplacesFile = join27(pluginsDir(), "known_marketplaces.json");
17659
17754
  const snapshotRoot = resolved.snapshotDir ?? resolved.sourceUri;
17660
17755
  const frozenSource = resolved.snapshot !== undefined;
17661
- const wrapper = frozenSource || !existsSync22(join27(snapshotRoot, ".claude-plugin", "marketplace.json")) ? join27(pluginsDir(), "marketplaces", `.plgnz-${marketplace}`) : undefined;
17756
+ const wrapper = frozenSource || !existsSync21(join27(snapshotRoot, ".claude-plugin", "marketplace.json")) ? join27(pluginsDir(), "marketplaces", `.plgnz-${marketplace}`) : undefined;
17662
17757
  for (const path of [slot, registryFile, settingsFile, marketplacesFile])
17663
17758
  assertManagedPath(path);
17664
17759
  const registry = readRegistry(registryFile);
@@ -17669,9 +17764,9 @@ var claudeCodeWriter = {
17669
17764
  const owned = ownedRegistryTarget(registry, id, resolved.sourceUri, slot, version);
17670
17765
  const matchedCatalogMember = legacy === undefined && !alreadyOwned && !hasUserRegistryInstall(registry, id) && matchesNativeCatalogMember(marketplaces, marketplace, plugin, resolved);
17671
17766
  const preserveNativeMarketplace = legacy !== undefined || alreadyOwned || matchedCatalogMember;
17672
- const target = owned ?? (legacy !== undefined && existsSync22(join27(slot, version)) && readOwnership(join27(slot, version)) === null ? join27(slot, `${version}.plgnz`) : join27(slot, version));
17767
+ const target = owned ?? (legacy !== undefined && existsSync21(join27(slot, version)) && readOwnership(join27(slot, version)) === null ? join27(slot, `${version}.plgnz`) : join27(slot, version));
17673
17768
  assertManagedPath(target);
17674
- if (existsSync22(target))
17769
+ if (existsSync21(target))
17675
17770
  assertNoSymlinks2(target);
17676
17771
  const existing = readOwnership(target);
17677
17772
  assertTargetIsReplaceable(target, existing, id, resolved.sourceUri);
@@ -17742,7 +17837,7 @@ var claudeCodeWriter = {
17742
17837
  }
17743
17838
  },
17744
17839
  async pin(plugin, opts) {
17745
- if (plugin.path === undefined || !existsSync22(plugin.path))
17840
+ if (plugin.path === undefined || !existsSync21(plugin.path))
17746
17841
  return { changes: [], refusals: [] };
17747
17842
  return pinPluginMcpFiles(plugin.path, mcpCandidates(), opts);
17748
17843
  },
@@ -17752,7 +17847,7 @@ var claudeCodeWriter = {
17752
17847
  for (const path of [registryFile, settingsFile])
17753
17848
  assertManagedPath(path);
17754
17849
  const settings = readSettings(settingsFile);
17755
- if (!existsSync22(registryFile)) {
17850
+ if (!existsSync21(registryFile)) {
17756
17851
  const enabled = settings["enabledPlugins"];
17757
17852
  if (typeof enabled === "object" && enabled !== null && !Array.isArray(enabled) && enabled[id] === true)
17758
17853
  writeSettings(settingsFile, settingsWithEnabled(settings, id, false));
@@ -17803,7 +17898,7 @@ var claudeCodeWriter = {
17803
17898
  if (readOwnership(copy)?.pluginId === id) {
17804
17899
  rmSync6(copy, { recursive: true, force: true });
17805
17900
  const manifest = join27(path, ".claude-plugin", "marketplace.json");
17806
- if (existsSync22(manifest)) {
17901
+ if (existsSync21(manifest)) {
17807
17902
  const document = JSON.parse(readFileSync21(manifest, "utf8"));
17808
17903
  if (typeof document === "object" && document !== null && !Array.isArray(document)) {
17809
17904
  const current = document;
@@ -17827,14 +17922,14 @@ function stagePlugin(source, stage, fallbackName, fallbackVersion) {
17827
17922
  compilePortableHooksInStage(hookAdapter, stage);
17828
17923
  const root = join27(stage, "plugin.json");
17829
17924
  const canonical = join27(stage, ".plugin", "plugin.json");
17830
- const manifest = existsSync22(canonical) ? canonical : existsSync22(root) ? root : undefined;
17925
+ const manifest = existsSync21(canonical) ? canonical : existsSync21(root) ? root : undefined;
17831
17926
  if (manifest === undefined)
17832
17927
  throw new Error("Claude Code stage has no Agent Plugins manifest");
17833
17928
  const canonicalManifest = parseManifest(manifest, "canonical");
17834
17929
  if (canonicalManifest.name !== fallbackName)
17835
17930
  throw new Error(`Claude Code canonical manifest name ${canonicalManifest.name} does not match selected plugin ${fallbackName}`);
17836
17931
  const native = join27(stage, ".claude-plugin", "plugin.json");
17837
- if (!existsSync22(native)) {
17932
+ if (!existsSync21(native)) {
17838
17933
  mkdirSync6(dirname8(native), { recursive: true });
17839
17934
  writeFileSync6(native, JSON.stringify({ name: canonicalManifest.name, version: canonicalManifest.version ?? fallbackVersion, description: canonicalManifest.description, skills: "./skills/" }));
17840
17935
  }
@@ -17844,7 +17939,7 @@ function stagePlugin(source, stage, fallbackName, fallbackVersion) {
17844
17939
  if (nativeManifest.name !== canonicalManifest.name || canonicalManifest.version !== undefined && nativeManifest.version !== canonicalManifest.version)
17845
17940
  throw new Error("Claude Code native manifest identity does not match the canonical manifest");
17846
17941
  for (const path of [join27(stage, "skills"), join27(stage, "commands"), join27(stage, ".claude", "commands")]) {
17847
- if (existsSync22(path) && !statSync9(path).isDirectory())
17942
+ if (existsSync21(path) && !statSync9(path).isDirectory())
17848
17943
  throw new Error(`Claude Code stage native content path is not a directory: ${path}`);
17849
17944
  }
17850
17945
  if (fallbackName.length === 0)
@@ -17852,10 +17947,10 @@ function stagePlugin(source, stage, fallbackName, fallbackVersion) {
17852
17947
  }
17853
17948
  function projectRootCommandsToNative(stage) {
17854
17949
  const nativeCommands = join27(stage, ".claude", "commands");
17855
- if (existsSync22(nativeCommands))
17950
+ if (existsSync21(nativeCommands))
17856
17951
  return;
17857
17952
  const rootCommands = join27(stage, "commands");
17858
- if (!existsSync22(rootCommands))
17953
+ if (!existsSync21(rootCommands))
17859
17954
  return;
17860
17955
  const entries = readdirSync13(rootCommands).sort();
17861
17956
  const markdown = entries.filter((file) => file.endsWith(".md"));
@@ -17874,7 +17969,7 @@ function projectRootCommandsToNative(stage) {
17874
17969
  }
17875
17970
  function projectNativeCommands(stage, native) {
17876
17971
  const commandsRoot = join27(stage, ".claude", "commands");
17877
- if (!existsSync22(commandsRoot))
17972
+ if (!existsSync21(commandsRoot))
17878
17973
  return;
17879
17974
  const commands = readdirSync13(commandsRoot).filter((file) => file.endsWith(".md")).sort().map((file) => `./.claude/commands/${file}`);
17880
17975
  if (commands.length === 0)
@@ -17909,7 +18004,7 @@ function parseManifest(file, kind) {
17909
18004
  return { name: manifest["name"], ...typeof manifest["version"] === "string" ? { version: manifest["version"] } : {}, ...typeof manifest["description"] === "string" ? { description: manifest["description"] } : {} };
17910
18005
  }
17911
18006
  function readRegistry(file) {
17912
- if (!existsSync22(file))
18007
+ if (!existsSync21(file))
17913
18008
  return { version: 2, plugins: {} };
17914
18009
  let value;
17915
18010
  try {
@@ -17925,7 +18020,7 @@ function readRegistry(file) {
17925
18020
  return { version: typeof root["version"] === "number" ? root["version"] : 2, plugins: root["plugins"] };
17926
18021
  }
17927
18022
  function readSettings(file) {
17928
- if (!existsSync22(file))
18023
+ if (!existsSync21(file))
17929
18024
  return {};
17930
18025
  let value;
17931
18026
  try {
@@ -17941,7 +18036,7 @@ function readSettings(file) {
17941
18036
  return settings;
17942
18037
  }
17943
18038
  function readMarketplaces(file) {
17944
- if (!existsSync22(file))
18039
+ if (!existsSync21(file))
17945
18040
  return {};
17946
18041
  let value;
17947
18042
  try {
@@ -17972,14 +18067,14 @@ function assertLifecycleMarketplaceEnvelope(version) {
17972
18067
  function marketplacesWithLocalSource(marketplaces, name, sourcePath, sourceIdentity, plugin, forceWrapper) {
17973
18068
  const manifest = join27(sourcePath, ".claude-plugin", "marketplace.json");
17974
18069
  const catalog = validateMarketplaceRegistration(marketplaces, name, sourcePath, sourceIdentity, plugin, forceWrapper);
17975
- if (forceWrapper || !existsSync22(manifest)) {
18070
+ if (forceWrapper || !existsSync21(manifest)) {
17976
18071
  const marker = join27(catalog, OWNERSHIP);
17977
18072
  const copy = join27(catalog, "plugins", plugin.name);
17978
18073
  rmSync6(copy, { recursive: true, force: true });
17979
18074
  cpSync5(plugin.dir, copy, { recursive: true });
17980
18075
  writeFileSync6(join27(copy, OWNERSHIP), JSON.stringify({ source: sourceIdentity, pluginId: `${plugin.name}@${name}`, fingerprint: plugin.contentFingerprint ?? "" }));
17981
18076
  mkdirSync6(join27(catalog, ".claude-plugin"), { recursive: true });
17982
- const current = existsSync22(join27(catalog, ".claude-plugin", "marketplace.json")) ? JSON.parse(readFileSync21(join27(catalog, ".claude-plugin", "marketplace.json"), "utf8")) : {};
18077
+ const current = existsSync21(join27(catalog, ".claude-plugin", "marketplace.json")) ? JSON.parse(readFileSync21(join27(catalog, ".claude-plugin", "marketplace.json"), "utf8")) : {};
17983
18078
  const plugins = Array.isArray(current.plugins) ? current.plugins.filter((entry) => !(typeof entry === "object" && entry !== null && entry["name"] === plugin.name)) : [];
17984
18079
  plugins.push({ name: plugin.name, source: `./plugins/${plugin.name}` });
17985
18080
  writeFileSync6(join27(catalog, ".claude-plugin", "marketplace.json"), JSON.stringify({ name, owner: { name: "plgnz" }, plugins }));
@@ -17999,17 +18094,17 @@ function validateMarketplaceRegistration(marketplaces, name, sourcePath, sourceI
17999
18094
  if (!sourcePath.startsWith("/"))
18000
18095
  throw new Error(`Claude Code marketplace registration for remote source ${name} is unverified`);
18001
18096
  const manifest = join27(sourcePath, ".claude-plugin", "marketplace.json");
18002
- const catalog = !forceWrapper && existsSync22(manifest) ? sourcePath : join27(pluginsDir(), "marketplaces", `.plgnz-${name}`);
18003
- if (!existsSync22(manifest) && existsSync22(catalog)) {
18097
+ const catalog = !forceWrapper && existsSync21(manifest) ? sourcePath : join27(pluginsDir(), "marketplaces", `.plgnz-${name}`);
18098
+ if (!existsSync21(manifest) && existsSync21(catalog)) {
18004
18099
  assertNoSymlinks2(catalog);
18005
18100
  const wrapper = readOwnership(catalog);
18006
18101
  if (wrapper?.pluginId !== `marketplace@${name}` || wrapper.source !== "plgnz-wrapper")
18007
18102
  throw new Error(`Claude Code marketplace wrapper ${catalog} is foreign; refusing to replace it`);
18008
18103
  const copy = join27(catalog, "plugins", plugin.name);
18009
- if (existsSync22(copy) && readOwnership(copy)?.source !== sourceIdentity)
18104
+ if (existsSync21(copy) && readOwnership(copy)?.source !== sourceIdentity)
18010
18105
  throw new Error(`Claude Code marketplace wrapper plugin ${copy} is foreign; refusing to replace it`);
18011
18106
  }
18012
- if (existsSync22(join27(catalog, ".claude-plugin", "marketplace.json"))) {
18107
+ if (existsSync21(join27(catalog, ".claude-plugin", "marketplace.json"))) {
18013
18108
  let document;
18014
18109
  try {
18015
18110
  document = JSON.parse(readFileSync21(join27(catalog, ".claude-plugin", "marketplace.json"), "utf8"));
@@ -18041,7 +18136,7 @@ function restoreMetadata(registryFile, registry, settingsFile, settings, marketp
18041
18136
  }
18042
18137
  }
18043
18138
  function snapshotDirectory(directory) {
18044
- if (!existsSync22(directory))
18139
+ if (!existsSync21(directory))
18045
18140
  return;
18046
18141
  assertNoSymlinks2(directory);
18047
18142
  const snapshot = mkdtempSync5(join27(tmpdir2(), "plgnz-claude-wrapper-"));
@@ -18053,7 +18148,7 @@ function restoreDirectory(directory, snapshot) {
18053
18148
  return;
18054
18149
  rmSync6(directory, { recursive: true, force: true });
18055
18150
  const previous = snapshot === undefined ? undefined : join27(snapshot, "previous");
18056
- if (previous !== undefined && existsSync22(previous)) {
18151
+ if (previous !== undefined && existsSync21(previous)) {
18057
18152
  mkdirSync6(dirname8(directory), { recursive: true });
18058
18153
  renameSync3(previous, directory);
18059
18154
  }
@@ -18117,7 +18212,7 @@ function assertNoForeignRegistryEntry(registry, id, target, source, adoptedLegac
18117
18212
  if (typeof row !== "object" || row === null || row["scope"] !== "user")
18118
18213
  continue;
18119
18214
  const path = row["installPath"];
18120
- if (typeof path !== "string" || path === target || !existsSync22(path))
18215
+ if (typeof path !== "string" || path === target || !existsSync21(path))
18121
18216
  continue;
18122
18217
  if (path === adoptedLegacy)
18123
18218
  continue;
@@ -18135,7 +18230,7 @@ function validateLegacyUserInstall(registry, id, slot, plugin) {
18135
18230
  throw new Error(`claude-code user install ${id} is ambiguous; refusing adoption`);
18136
18231
  const row = users[0];
18137
18232
  const path = row["installPath"];
18138
- if (typeof path !== "string" || dirname8(path) !== slot || !existsSync22(path))
18233
+ if (typeof path !== "string" || dirname8(path) !== slot || !existsSync21(path))
18139
18234
  throw new Error(`claude-code user install ${id} is outside its native cache slot; refusing adoption`);
18140
18235
  assertNoSymlinks2(path);
18141
18236
  if (readOwnership(path) !== null)
@@ -18153,7 +18248,7 @@ function ownedRegistryTarget(registry, id, source, slot, version) {
18153
18248
  if (users.length !== 1)
18154
18249
  return;
18155
18250
  const path = users[0]["installPath"];
18156
- if (typeof path !== "string" || dirname8(path) !== slot || path !== join27(slot, `${version}.plgnz`) || !existsSync22(path))
18251
+ if (typeof path !== "string" || dirname8(path) !== slot || path !== join27(slot, `${version}.plgnz`) || !existsSync21(path))
18157
18252
  return;
18158
18253
  const ownership = readOwnership(path);
18159
18254
  return ownership?.pluginId === id && ownership.source === source ? path : undefined;
@@ -18164,7 +18259,7 @@ function hasAdoptedRegistryInstall(registry, id, source, slot) {
18164
18259
  if (users.length !== 1)
18165
18260
  return false;
18166
18261
  const path = users[0]["installPath"];
18167
- if (typeof path !== "string" || dirname8(path) !== slot || !existsSync22(path))
18262
+ if (typeof path !== "string" || dirname8(path) !== slot || !existsSync21(path))
18168
18263
  return false;
18169
18264
  const ownership = readOwnership(path);
18170
18265
  return ownership?.pluginId === id && ownership.source === source && ownership.adopted === true;
@@ -18188,7 +18283,7 @@ function matchesNativeCatalogMember(marketplaces, name, plugin, resolved) {
18188
18283
  if (!containedPath(resolved.sourceUri, plugin.sourceDir ?? plugin.dir))
18189
18284
  return false;
18190
18285
  const manifest = join27(catalog, ".claude-plugin", "marketplace.json");
18191
- if (!existsSync22(manifest))
18286
+ if (!existsSync21(manifest))
18192
18287
  return false;
18193
18288
  assertCatalogPath(catalog, manifest);
18194
18289
  let document;
@@ -18212,7 +18307,7 @@ function matchesNativeCatalogMember(marketplaces, name, plugin, resolved) {
18212
18307
  if (!containedPath(catalog, nativeDir) || nativeDir === resolve15(catalog))
18213
18308
  return false;
18214
18309
  assertCatalogPath(catalog, nativeDir);
18215
- if (!existsSync22(nativeDir) || !lstatSync12(nativeDir).isDirectory())
18310
+ if (!existsSync21(nativeDir) || !lstatSync13(nativeDir).isDirectory())
18216
18311
  return false;
18217
18312
  const stages = mkdtempSync5(join27(tmpdir2(), "plgnz-claude-catalog-proof-"));
18218
18313
  try {
@@ -18239,7 +18334,7 @@ function assertCatalogPath(root, path) {
18239
18334
  for (const part of ["", ...relative7(current, target).split("/").filter(Boolean)]) {
18240
18335
  if (part !== "")
18241
18336
  current = join27(current, part);
18242
- const stat = lstatSync12(current);
18337
+ const stat = lstatSync13(current);
18243
18338
  if (stat.isSymbolicLink())
18244
18339
  throw new Error(`Claude Code native catalog path contains symlink: ${current}`);
18245
18340
  if (current !== target && !stat.isDirectory())
@@ -18247,7 +18342,7 @@ function assertCatalogPath(root, path) {
18247
18342
  }
18248
18343
  }
18249
18344
  function assertTargetIsReplaceable(target, ownership, id, source) {
18250
- if (existsSync22(target) && ownership === null)
18345
+ if (existsSync21(target) && ownership === null)
18251
18346
  throw new Error(`claude-code cache slot ${target} is unowned; refusing to replace it`);
18252
18347
  if (ownership !== null && (ownership.pluginId !== id || ownership.source !== source))
18253
18348
  throw new Error(`claude-code cache slot ${target} has a different owned source identity; refusing to replace it`);
@@ -18264,7 +18359,7 @@ function assertManagedPath(path) {
18264
18359
  current = join27(current, part);
18265
18360
  let stat;
18266
18361
  try {
18267
- stat = lstatSync12(current);
18362
+ stat = lstatSync13(current);
18268
18363
  } catch (error) {
18269
18364
  if (error.code === "ENOENT")
18270
18365
  return;
@@ -18284,7 +18379,7 @@ function cleanupPriorOwnedPaths(registry, id, active, source) {
18284
18379
  if (typeof row !== "object" || row === null)
18285
18380
  continue;
18286
18381
  const path = row["installPath"];
18287
- if (typeof path !== "string" || path === active || !existsSync22(path))
18382
+ if (typeof path !== "string" || path === active || !existsSync21(path))
18288
18383
  continue;
18289
18384
  const ownership = readOwnership(path);
18290
18385
  if (ownership?.pluginId === id && ownership.source === source)
@@ -18293,7 +18388,7 @@ function cleanupPriorOwnedPaths(registry, id, active, source) {
18293
18388
  }
18294
18389
  function readOwnership(dir) {
18295
18390
  const file = join27(dir, OWNERSHIP);
18296
- if (!existsSync22(file))
18391
+ if (!existsSync21(file))
18297
18392
  return null;
18298
18393
  try {
18299
18394
  const parsed = JSON.parse(readFileSync21(file, "utf8"));
@@ -18318,7 +18413,7 @@ function readOwnership(dir) {
18318
18413
  }
18319
18414
  }
18320
18415
  function activate(stage, target, slot) {
18321
- if (!existsSync22(target)) {
18416
+ if (!existsSync21(target)) {
18322
18417
  renameSync3(stage, target);
18323
18418
  return { commit: () => {}, rollback: () => rmSync6(target, { recursive: true, force: true }) };
18324
18419
  }
@@ -18339,13 +18434,13 @@ function moveAside(path, parent = dirname8(path)) {
18339
18434
  const backup = join27(backupRoot, "previous");
18340
18435
  renameSync3(path, backup);
18341
18436
  return { commit: () => rmSync6(backupRoot, { recursive: true, force: true }), rollback: () => {
18342
- if (existsSync22(backup))
18437
+ if (existsSync21(backup))
18343
18438
  renameSync3(backup, path);
18344
18439
  rmSync6(backupRoot, { recursive: true, force: true });
18345
18440
  } };
18346
18441
  }
18347
18442
  function sameTree(left, right) {
18348
- if (!existsSync22(right))
18443
+ if (!existsSync21(right))
18349
18444
  return false;
18350
18445
  const listing = (root) => {
18351
18446
  const out = [];
@@ -18373,11 +18468,11 @@ function bytesKey(path) {
18373
18468
  return hash.digest("hex");
18374
18469
  }
18375
18470
  function assertNoSymlinks2(dir) {
18376
- if (lstatSync12(dir).isSymbolicLink())
18471
+ if (lstatSync13(dir).isSymbolicLink())
18377
18472
  throw new Error(`Claude Code cache contains symlink: ${dir}`);
18378
18473
  for (const entry of readdirSync13(dir)) {
18379
18474
  const path = join27(dir, entry);
18380
- const stat = lstatSync12(path);
18475
+ const stat = lstatSync13(path);
18381
18476
  if (stat.isSymbolicLink())
18382
18477
  throw new Error(`Claude Code cache contains symlink: ${path}`);
18383
18478
  if (stat.isDirectory())
@@ -18538,7 +18633,7 @@ function claudeCodeLifecycleDefinition(contracts) {
18538
18633
  retire: async (prepared) => {
18539
18634
  retireLifecycleCatalog(prepared.handle.nativeId, prepared.handle.scopeId);
18540
18635
  const installPath = recordedInstallPath(prepared.handle.nativeId);
18541
- const existed = installPath !== undefined && existsSync22(installPath);
18636
+ const existed = installPath !== undefined && existsSync21(installPath);
18542
18637
  if (installPath !== undefined)
18543
18638
  rmSync6(installPath, { recursive: true, force: true });
18544
18639
  dropUserRow(prepared.handle.nativeId);
@@ -18693,7 +18788,7 @@ function observeClaudeInstallations(target, version) {
18693
18788
  if (typeof recordedPath !== "string")
18694
18789
  continue;
18695
18790
  const installPath = resolve15(recordedPath);
18696
- if (!existsSync22(installPath))
18791
+ if (!existsSync21(installPath))
18697
18792
  continue;
18698
18793
  const marker = readOwnership(installPath);
18699
18794
  const digest = fingerprintTree(installPath);
@@ -18770,7 +18865,7 @@ function activationIdentity(activation) {
18770
18865
  function claudeReadback(identity, absentRoute, version) {
18771
18866
  assertLifecycleMarketplaceEnvelope(version);
18772
18867
  const installPath = recordedInstallPath(identity.nativeId);
18773
- const present = installPath !== undefined && existsSync22(installPath);
18868
+ const present = installPath !== undefined && existsSync21(installPath);
18774
18869
  const retention = {
18775
18870
  pluginData: retained(resolve15(join27(pluginsDir(), "plugin-data", identity.nativeId))),
18776
18871
  inactiveMetadata: retained(resolve15(join27(pluginsDir(), "inactive-metadata", identity.nativeId)))
@@ -18804,7 +18899,7 @@ function claudeReadback(identity, absentRoute, version) {
18804
18899
  }
18805
18900
  function installedRoute(installPath) {
18806
18901
  const file = join27(installPath, ".plgnz-lifecycle.json");
18807
- if (!existsSync22(file))
18902
+ if (!existsSync21(file))
18808
18903
  return "managed";
18809
18904
  try {
18810
18905
  const parsed = JSON.parse(readFileSync21(file, "utf8"));
@@ -18817,7 +18912,7 @@ function installedRoute(installPath) {
18817
18912
  }
18818
18913
  function observedOwnedRoute(installPath) {
18819
18914
  const file = join27(installPath, ".plgnz-lifecycle.json");
18820
- if (!existsSync22(file))
18915
+ if (!existsSync21(file))
18821
18916
  return;
18822
18917
  const value = JSON.parse(readFileSync21(file, "utf8"));
18823
18918
  if (typeof value !== "object" || value === null || Array.isArray(value))
@@ -18828,7 +18923,7 @@ function observedOwnedRoute(installPath) {
18828
18923
  return route;
18829
18924
  }
18830
18925
  function retained(path) {
18831
- if (!existsSync22(path))
18926
+ if (!existsSync21(path))
18832
18927
  return { state: "absent", fingerprint: null };
18833
18928
  return { state: "present", fingerprint: fingerprintTree(path) };
18834
18929
  }
@@ -18875,14 +18970,14 @@ function registeredLifecycleCatalogMember(nativeId) {
18875
18970
  if (!isRecord6(entry) || !isRecord6(entry["source"]) || entry["source"]["source"] !== "directory" || typeof entry["source"]["path"] !== "string" || entry["installLocation"] !== entry["source"]["path"])
18876
18971
  return null;
18877
18972
  const root = entry["source"]["path"];
18878
- if (!root.startsWith("/") || resolve15(root) !== root || !existsSync22(root))
18973
+ if (!root.startsWith("/") || resolve15(root) !== root || !existsSync21(root))
18879
18974
  return null;
18880
18975
  assertCatalogPath(root, join27(root, ".claude-plugin", "marketplace.json"));
18881
18976
  const selected = catalogEntries(lifecycleCatalogDocument(root, market)).filter((item) => isCatalogMember(item, nativeId));
18882
18977
  if (selected.length !== 1 || !isRecord6(selected[0]) || typeof selected[0]["source"] !== "string" || !selected[0]["source"].startsWith("./"))
18883
18978
  return null;
18884
18979
  const member = resolve15(root, selected[0]["source"]);
18885
- if (!containedPath(root, member) || root === member || !existsSync22(member))
18980
+ if (!containedPath(root, member) || root === member || !existsSync21(member))
18886
18981
  return null;
18887
18982
  assertCatalogPath(root, member);
18888
18983
  assertNoSymlinks2(member);
@@ -18896,7 +18991,7 @@ function matchingForeignLifecycleCatalog(nativeId, scopeId, target, packageRoot,
18896
18991
  return null;
18897
18992
  if (!foreignLifecycleEntryEquivalent(catalog.entry))
18898
18993
  return null;
18899
- if (!existsSync22(join27(catalog.member, ".claude-plugin", "plugin.json")))
18994
+ if (!existsSync21(join27(catalog.member, ".claude-plugin", "plugin.json")))
18900
18995
  return null;
18901
18996
  const proof = mkdtempSync5(join27(tmpdir2(), "plgnz-claude-native-member-"));
18902
18997
  try {
@@ -18913,7 +19008,7 @@ function matchingForeignLifecycleCatalog(nativeId, scopeId, target, packageRoot,
18913
19008
  }
18914
19009
  function lifecycleCatalogDocument(root, market) {
18915
19010
  const file = join27(root, ".claude-plugin", "marketplace.json");
18916
- if (!existsSync22(file))
19011
+ if (!existsSync21(file))
18917
19012
  return null;
18918
19013
  const parsed = JSON.parse(readFileSync21(file, "utf8"));
18919
19014
  if (!isRecord6(parsed) || parsed["name"] !== market || !Array.isArray(parsed["plugins"]))
@@ -18961,7 +19056,7 @@ function validateLifecycleCatalog(nativeId, scopeId) {
18961
19056
  assertManagedPath(join27(root, ".claude-plugin", "marketplace.json"));
18962
19057
  assertManagedPath(join27(root, OWNERSHIP));
18963
19058
  assertManagedPath(copy);
18964
- if (existsSync22(root)) {
19059
+ if (existsSync21(root)) {
18965
19060
  const owner = readOwnership(root);
18966
19061
  if (owner?.source !== "plgnz-wrapper" || owner.pluginId !== `marketplace@${market}`)
18967
19062
  throw new Error(`Claude Code marketplace wrapper ${root} is foreign; refusing to replace it`);
@@ -18970,7 +19065,7 @@ function validateLifecycleCatalog(nativeId, scopeId) {
18970
19065
  const selected = catalogEntries(document).filter((entry) => isCatalogMember(entry, nativeId));
18971
19066
  if (selected.length > 1 || selected.some((entry) => !isRecord6(entry) || entry["source"] !== `./plugins/${nativeId.slice(0, nativeId.indexOf("@"))}`))
18972
19067
  throw new Error(`Claude Code marketplace member ${nativeId} is foreign or ambiguous; refusing to replace it`);
18973
- if (existsSync22(copy)) {
19068
+ if (existsSync21(copy)) {
18974
19069
  assertNoSymlinks2(copy);
18975
19070
  const owner = readOwnership(copy);
18976
19071
  if (owner?.pluginId !== nativeId || owner.scopeId !== scopeId)
@@ -19016,7 +19111,7 @@ function lifecycleCatalogConforms(nativeId, installPath, target) {
19016
19111
  if (registered !== null && registered.root !== lifecycleCatalogRoot(nativeId)) {
19017
19112
  if (owner?.scopeId === undefined)
19018
19113
  return false;
19019
- const manifest = existsSync22(join27(installPath, ".plugin", "plugin.json")) ? join27(installPath, ".plugin", "plugin.json") : join27(installPath, "plugin.json");
19114
+ const manifest = existsSync21(join27(installPath, ".plugin", "plugin.json")) ? join27(installPath, ".plugin", "plugin.json") : join27(installPath, "plugin.json");
19020
19115
  return matchingForeignLifecycleCatalog(nativeId, owner.scopeId, target, installPath, parseManifest(manifest, "canonical").version ?? "") !== null;
19021
19116
  }
19022
19117
  const known = readMarketplaces(join27(pluginsDir(), "known_marketplaces.json"))[market];
@@ -19026,7 +19121,7 @@ function lifecycleCatalogConforms(nativeId, installPath, target) {
19026
19121
  if (entries.length !== 1 || catalogEntryFingerprint(entries[0]) !== catalogEntryFingerprint(ownedLifecycleCatalogEntry(nativeId)))
19027
19122
  return false;
19028
19123
  const copy = lifecycleCatalogCopy(nativeId);
19029
- if (!existsSync22(copy))
19124
+ if (!existsSync21(copy))
19030
19125
  return false;
19031
19126
  assertManagedPath(copy);
19032
19127
  assertNoSymlinks2(copy);
@@ -19035,13 +19130,13 @@ function lifecycleCatalogConforms(nativeId, installPath, target) {
19035
19130
  }
19036
19131
  function lifecycleContentRoots(nativeId, installPath, digest) {
19037
19132
  const copy = registeredLifecycleCatalogMember(nativeId)?.member ?? lifecycleCatalogCopy(nativeId);
19038
- return [{ label: "plugin", path: installPath, fingerprint: digest }, ...existsSync22(copy) ? [{ label: "catalog-plugin", path: copy, fingerprint: fingerprintTree(copy) }] : [], ...lifecycleCatalogEntryObservation(nativeId)];
19133
+ return [{ label: "plugin", path: installPath, fingerprint: digest }, ...existsSync21(copy) ? [{ label: "catalog-plugin", path: copy, fingerprint: fingerprintTree(copy) }] : [], ...lifecycleCatalogEntryObservation(nativeId)];
19039
19134
  }
19040
19135
  function retireLifecycleCatalog(nativeId, scopeId) {
19041
19136
  validateLifecycleCatalogRetirement(nativeId, scopeId);
19042
19137
  const root = lifecycleCatalogRoot(nativeId);
19043
19138
  const copy = lifecycleCatalogCopy(nativeId);
19044
- if (!existsSync22(root))
19139
+ if (!existsSync21(root))
19045
19140
  return;
19046
19141
  assertManagedPath(root);
19047
19142
  const market = marketplaceName(nativeId);
@@ -19049,7 +19144,7 @@ function retireLifecycleCatalog(nativeId, scopeId) {
19049
19144
  if (owner?.source !== "plgnz-wrapper" || owner.pluginId !== `marketplace@${market}`)
19050
19145
  return;
19051
19146
  const document = lifecycleCatalogDocument(root, market);
19052
- if (existsSync22(copy)) {
19147
+ if (existsSync21(copy)) {
19053
19148
  const member = readOwnership(copy);
19054
19149
  if (member?.pluginId !== nativeId || member.scopeId !== scopeId)
19055
19150
  throw new Error(`Claude Code catalog retirement cannot prove ownership: ${copy}`);
@@ -19071,17 +19166,17 @@ function retireLifecycleCatalog(nativeId, scopeId) {
19071
19166
  }
19072
19167
  }
19073
19168
  function emptyOwnedCatalogContainer(root) {
19074
- if (!existsSync22(root))
19169
+ if (!existsSync21(root))
19075
19170
  return true;
19076
19171
  if (readdirSync13(root).some((name) => ![OWNERSHIP, ".claude-plugin", "plugins"].includes(name)))
19077
19172
  return false;
19078
- if (existsSync22(join27(root, ".claude-plugin")) && readdirSync13(join27(root, ".claude-plugin")).some((name) => name !== "marketplace.json"))
19173
+ if (existsSync21(join27(root, ".claude-plugin")) && readdirSync13(join27(root, ".claude-plugin")).some((name) => name !== "marketplace.json"))
19079
19174
  return false;
19080
- return !existsSync22(join27(root, "plugins")) || readdirSync13(join27(root, "plugins")).length === 0;
19175
+ return !existsSync21(join27(root, "plugins")) || readdirSync13(join27(root, "plugins")).length === 0;
19081
19176
  }
19082
19177
  function validateLifecycleCatalogRetirement(nativeId, scopeId) {
19083
19178
  const root = lifecycleCatalogRoot(nativeId);
19084
- if (!existsSync22(root))
19179
+ if (!existsSync21(root))
19085
19180
  return;
19086
19181
  assertManagedPath(root);
19087
19182
  assertManagedPath(join27(root, OWNERSHIP));
@@ -19098,7 +19193,7 @@ function validateLifecycleCatalogRetirement(nativeId, scopeId) {
19098
19193
  const selected = catalogEntries(lifecycleCatalogDocument(root, marketplaceName(nativeId))).filter((entry) => isCatalogMember(entry, nativeId));
19099
19194
  if (selected.length > 1 || selected.some((entry) => !isRecord6(entry) || entry["source"] !== `./plugins/${nativeId.slice(0, nativeId.indexOf("@"))}`))
19100
19195
  throw new Error(`Claude Code catalog retirement found a foreign or ambiguous member: ${nativeId}`);
19101
- if (existsSync22(copy)) {
19196
+ if (existsSync21(copy)) {
19102
19197
  assertNoSymlinks2(copy);
19103
19198
  const member = readOwnership(copy);
19104
19199
  if (member?.pluginId !== nativeId || member.scopeId !== scopeId)
@@ -19109,9 +19204,9 @@ function captureLifecycleCatalog(reference, nativeId) {
19109
19204
  const root = lifecycleCatalogRoot(nativeId);
19110
19205
  const market = marketplaceName(nativeId);
19111
19206
  const document = lifecycleCatalogDocument(root, market);
19112
- writeFileSync6(join27(reference, "catalog.json"), JSON.stringify({ document, selected: catalogEntries(document).filter((entry) => isCatalogMember(entry, nativeId)), marker: existsSync22(join27(root, OWNERSHIP)) ? readFileSync21(join27(root, OWNERSHIP), "utf8") : null }));
19207
+ writeFileSync6(join27(reference, "catalog.json"), JSON.stringify({ document, selected: catalogEntries(document).filter((entry) => isCatalogMember(entry, nativeId)), marker: existsSync21(join27(root, OWNERSHIP)) ? readFileSync21(join27(root, OWNERSHIP), "utf8") : null }));
19113
19208
  const copy = lifecycleCatalogCopy(nativeId);
19114
- if (existsSync22(copy)) {
19209
+ if (existsSync21(copy)) {
19115
19210
  assertNoSymlinks2(copy);
19116
19211
  cpSync5(copy, join27(reference, "catalog-plugin"), { recursive: true });
19117
19212
  }
@@ -19120,7 +19215,7 @@ function restoreLifecycleCatalog(reference, nativeId, scopeId) {
19120
19215
  const saved = JSON.parse(readFileSync21(join27(reference, "catalog.json"), "utf8"));
19121
19216
  const root = lifecycleCatalogRoot(nativeId);
19122
19217
  assertManagedPath(root);
19123
- if (existsSync22(root)) {
19218
+ if (existsSync21(root)) {
19124
19219
  assertManagedPath(join27(root, OWNERSHIP));
19125
19220
  const owner = readOwnership(root);
19126
19221
  if (owner?.source !== "plgnz-wrapper" || owner.pluginId !== `marketplace@${marketplaceName(nativeId)}`)
@@ -19132,14 +19227,14 @@ function restoreLifecycleCatalog(reference, nativeId, scopeId) {
19132
19227
  const siblings = catalogEntries(current).filter((entry) => !isCatalogMember(entry, nativeId));
19133
19228
  const copy = lifecycleCatalogCopy(nativeId);
19134
19229
  assertManagedPath(copy);
19135
- if (existsSync22(copy)) {
19230
+ if (existsSync21(copy)) {
19136
19231
  assertNoSymlinks2(copy);
19137
19232
  const owner = readOwnership(copy);
19138
19233
  if (owner?.pluginId !== nativeId || owner.scopeId !== scopeId)
19139
19234
  throw new Error(`Claude Code rollback refuses a foreign catalog member: ${copy}`);
19140
19235
  }
19141
19236
  rmSync6(copy, { recursive: true, force: true });
19142
- if (existsSync22(join27(reference, "catalog-plugin"))) {
19237
+ if (existsSync21(join27(reference, "catalog-plugin"))) {
19143
19238
  mkdirSync6(dirname8(copy), { recursive: true });
19144
19239
  cpSync5(join27(reference, "catalog-plugin"), copy, { recursive: true });
19145
19240
  }
@@ -19182,7 +19277,7 @@ function captureRollback(attemptId, operationId, nativeId) {
19182
19277
  writeFileSync6(join27(reference, "known-marketplace.json"), JSON.stringify({ marketplace: marketplace ?? null, entry: knownEntry }));
19183
19278
  captureLifecycleCatalog(reference, nativeId);
19184
19279
  const installPath = recordedInstallPath(nativeId);
19185
- if (installPath !== undefined && existsSync22(installPath)) {
19280
+ if (installPath !== undefined && existsSync21(installPath)) {
19186
19281
  cpSync5(installPath, join27(reference, "install"), { recursive: true });
19187
19282
  writeFileSync6(join27(reference, "install-path.txt"), installPath);
19188
19283
  }
@@ -19204,7 +19299,7 @@ function mutateInstall(handle, stagingRoot) {
19204
19299
  }
19205
19300
  const beforeCatalog = lifecycleSelectedMutationState(handle.nativeId);
19206
19301
  const installPath = cacheSlot(handle.nativeId, slotVersion(handle.packageVersion, handle.sourceRevision));
19207
- const before = existsSync22(installPath) ? fingerprintTree(installPath) : null;
19302
+ const before = existsSync21(installPath) ? fingerprintTree(installPath) : null;
19208
19303
  rmSync6(installPath, { recursive: true, force: true });
19209
19304
  mkdirSync6(dirname8(installPath), { recursive: true });
19210
19305
  cpSync5(stagingRoot, installPath, { recursive: true });
@@ -19239,7 +19334,7 @@ function lifecycleSelectedMutationState(nativeId) {
19239
19334
  const member = registeredLifecycleCatalogMember(nativeId)?.member ?? lifecycleCatalogCopy(nativeId);
19240
19335
  return catalogEntryFingerprint({
19241
19336
  catalogEntry: lifecycleCatalogEntryObservation(nativeId),
19242
- member: existsSync22(member) ? fingerprintTree(member) : null,
19337
+ member: existsSync21(member) ? fingerprintTree(member) : null,
19243
19338
  registration: known[market] ?? null,
19244
19339
  extraRegistration: isRecord6(extra) ? extra[market] ?? null : null,
19245
19340
  installedRows: readRegistry(join27(pluginsDir(), "installed_plugins.json")).plugins[nativeId] ?? null,
@@ -19271,15 +19366,15 @@ function restoreRollback(handle) {
19271
19366
  const registryFile = join27(pluginsDir(), "installed_plugins.json");
19272
19367
  const appliedSlot = cacheSlot(handle.nativeId, slotVersion(handle.packageVersion, handle.sourceRevision));
19273
19368
  const savedPath = join27(reference, "install-path.txt");
19274
- const previousSlot = existsSync22(savedPath) ? readFileSync21(savedPath, "utf8") : undefined;
19275
- if (previousSlot !== undefined && resolve15(previousSlot) !== appliedSlot && !existsSync22(appliedSlot)) {
19369
+ const previousSlot = existsSync21(savedPath) ? readFileSync21(savedPath, "utf8") : undefined;
19370
+ if (previousSlot !== undefined && resolve15(previousSlot) !== appliedSlot && !existsSync21(appliedSlot)) {
19276
19371
  throw new Error(`claude-code rollback cannot remove the updated cache slot: ${appliedSlot}`);
19277
19372
  }
19278
19373
  const beforeEntry = JSON.stringify(readRegistry(registryFile).plugins[handle.nativeId] ?? null);
19279
19374
  const beforeEnabled = JSON.stringify(enabledPlugins()[handle.nativeId] ?? null);
19280
- const beforeMarkets = existsSync22(join27(pluginsDir(), "known_marketplaces.json")) ? readFileSync21(join27(pluginsDir(), "known_marketplaces.json"), "utf8") : "";
19281
- const beforeApplied = existsSync22(appliedSlot) ? fingerprintTree(appliedSlot) : null;
19282
- const beforePrevious = previousSlot !== undefined && existsSync22(previousSlot) ? fingerprintTree(previousSlot) : null;
19375
+ const beforeMarkets = existsSync21(join27(pluginsDir(), "known_marketplaces.json")) ? readFileSync21(join27(pluginsDir(), "known_marketplaces.json"), "utf8") : "";
19376
+ const beforeApplied = existsSync21(appliedSlot) ? fingerprintTree(appliedSlot) : null;
19377
+ const beforePrevious = previousSlot !== undefined && existsSync21(previousSlot) ? fingerprintTree(previousSlot) : null;
19283
19378
  restoreLifecycleCatalog(reference, handle.nativeId, handle.scopeId);
19284
19379
  restorePluginSlice(handle.nativeId, reference);
19285
19380
  if (previousSlot !== undefined && resolve15(previousSlot) !== appliedSlot)
@@ -19287,15 +19382,15 @@ function restoreRollback(handle) {
19287
19382
  const installPath = previousSlot ?? recordedInstallPath(handle.nativeId) ?? appliedSlot;
19288
19383
  const backup = join27(reference, "install");
19289
19384
  rmSync6(installPath, { recursive: true, force: true });
19290
- if (existsSync22(backup)) {
19385
+ if (existsSync21(backup)) {
19291
19386
  mkdirSync6(dirname8(installPath), { recursive: true });
19292
19387
  cpSync5(backup, installPath, { recursive: true });
19293
19388
  }
19294
19389
  const afterEntry = JSON.stringify(readRegistry(registryFile).plugins[handle.nativeId] ?? null);
19295
19390
  const afterEnabled = JSON.stringify(enabledPlugins()[handle.nativeId] ?? null);
19296
- const afterMarkets = existsSync22(join27(pluginsDir(), "known_marketplaces.json")) ? readFileSync21(join27(pluginsDir(), "known_marketplaces.json"), "utf8") : "";
19297
- const afterApplied = existsSync22(appliedSlot) ? fingerprintTree(appliedSlot) : null;
19298
- const afterPrevious = previousSlot !== undefined && existsSync22(previousSlot) ? fingerprintTree(previousSlot) : null;
19391
+ const afterMarkets = existsSync21(join27(pluginsDir(), "known_marketplaces.json")) ? readFileSync21(join27(pluginsDir(), "known_marketplaces.json"), "utf8") : "";
19392
+ const afterApplied = existsSync21(appliedSlot) ? fingerprintTree(appliedSlot) : null;
19393
+ const afterPrevious = previousSlot !== undefined && existsSync21(previousSlot) ? fingerprintTree(previousSlot) : null;
19299
19394
  return {
19300
19395
  receiptId: `claude-rollback-${handle.operationId}`,
19301
19396
  changed: beforeEntry !== afterEntry || beforeEnabled !== afterEnabled || beforeMarkets !== afterMarkets || beforeApplied !== afterApplied || beforePrevious !== afterPrevious
@@ -19343,13 +19438,13 @@ function restoreKnownMarketplace(reference) {
19343
19438
  if (typeof saved.marketplace !== "string")
19344
19439
  return;
19345
19440
  const file = join27(pluginsDir(), "known_marketplaces.json");
19346
- const hadFile = existsSync22(file);
19441
+ const hadFile = existsSync21(file);
19347
19442
  const current = hadFile ? readMarketplaces(file) : {};
19348
19443
  if (saved.entry === null) {
19349
19444
  if (!hadFile || !Object.hasOwn(current, saved.marketplace))
19350
19445
  return;
19351
19446
  const root = lifecycleCatalogRoot(`rollback@${saved.marketplace}`);
19352
- if (existsSync22(root) && (catalogEntries(lifecycleCatalogDocument(root, saved.marketplace)).length > 0 || !emptyOwnedCatalogContainer(root)))
19447
+ if (existsSync21(root) && (catalogEntries(lifecycleCatalogDocument(root, saved.marketplace)).length > 0 || !emptyOwnedCatalogContainer(root)))
19353
19448
  return;
19354
19449
  const next = { ...current };
19355
19450
  delete next[saved.marketplace];
@@ -19405,7 +19500,7 @@ function hasForeignMarketplaceSibling(nativeId, marketplace) {
19405
19500
  if (!isRecord6(registration) || !isRecord6(registration["source"]) || registration["source"]["source"] !== "directory" || typeof registration["source"]["path"] !== "string")
19406
19501
  return false;
19407
19502
  const root = registration["source"]["path"];
19408
- if (!root.startsWith("/") || !existsSync22(root))
19503
+ if (!root.startsWith("/") || !existsSync21(root))
19409
19504
  return false;
19410
19505
  const document = lifecycleCatalogDocument(root, marketplace);
19411
19506
  return catalogEntries(document).some((entry) => {
@@ -19414,14 +19509,14 @@ function hasForeignMarketplaceSibling(nativeId, marketplace) {
19414
19509
  if (!isRecord6(entry) || typeof entry["name"] !== "string" || typeof entry["source"] !== "string" || !entry["source"].startsWith("./"))
19415
19510
  return true;
19416
19511
  const member = resolve15(root, entry["source"]);
19417
- if (!containedPath(root, member) || member === root || !existsSync22(member))
19512
+ if (!containedPath(root, member) || member === root || !existsSync21(member))
19418
19513
  return true;
19419
19514
  assertCatalogPath(root, member);
19420
19515
  return readOwnership(member)?.pluginId !== `${entry["name"]}@${marketplace}`;
19421
19516
  });
19422
19517
  }
19423
19518
  function plgnzOwnedInstall(id, installPath) {
19424
- if (typeof installPath !== "string" || !existsSync22(installPath))
19519
+ if (typeof installPath !== "string" || !existsSync21(installPath))
19425
19520
  return false;
19426
19521
  return readOwnership(installPath)?.pluginId === id;
19427
19522
  }
@@ -19451,19 +19546,19 @@ function disableMarketplaceAutoUpdate(nativeId) {
19451
19546
 
19452
19547
  // src/hosts/codex-writer.ts
19453
19548
  init_codex_hooks();
19454
- import { chmodSync, cpSync as cpSync6, existsSync as existsSync23, lstatSync as lstatSync14, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync6, readFileSync as readFileSync23, readdirSync as readdirSync14, renameSync as renameSync4, rmSync as rmSync7, statSync as statSync10, writeFileSync as writeFileSync7 } from "node:fs";
19549
+ import { chmodSync, cpSync as cpSync6, existsSync as existsSync22, lstatSync as lstatSync15, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync6, readFileSync as readFileSync23, readdirSync as readdirSync14, renameSync as renameSync4, rmSync as rmSync7, statSync as statSync10, writeFileSync as writeFileSync7 } from "node:fs";
19455
19550
  import { dirname as dirname9, join as join29, resolve as resolve16 } from "node:path";
19456
19551
  import { tmpdir as tmpdir3 } from "node:os";
19457
19552
 
19458
19553
  // src/hosts/codex-marketplace-proof.ts
19459
- import { lstatSync as lstatSync13, readFileSync as readFileSync22 } from "node:fs";
19554
+ import { lstatSync as lstatSync14, readFileSync as readFileSync22 } from "node:fs";
19460
19555
  import { join as join28 } from "node:path";
19461
19556
  var codexMarketplaceMetadataFile = ".codex-marketplace-install.json";
19462
19557
  function codexMarketplaceSourceFingerprint(checkout, expected) {
19463
19558
  try {
19464
19559
  let stat;
19465
19560
  try {
19466
- stat = lstatSync13(join28(checkout, codexMarketplaceMetadataFile));
19561
+ stat = lstatSync14(join28(checkout, codexMarketplaceMetadataFile));
19467
19562
  } catch (error) {
19468
19563
  if (error.code === "ENOENT")
19469
19564
  return fingerprintSourceTree(checkout);
@@ -19509,13 +19604,13 @@ var codexWriter = {
19509
19604
  validateStage(stage);
19510
19605
  writeFileSync7(join29(stage, OWNERSHIP2), JSON.stringify({ source: resolved.sourceUri, pluginId: id, fingerprint: plugin.contentFingerprint ?? "" }));
19511
19606
  assertManagedPath2(codexHome(), slot);
19512
- if (existsSync23(slot)) {
19607
+ if (existsSync22(slot)) {
19513
19608
  assertNoSymlinks3(slot);
19514
19609
  assertNoWinningForeignVersion(slot, version, id, resolved.sourceUri);
19515
19610
  const marker = readOwnership2(targetDir);
19516
19611
  if (marker !== null && (marker.source !== resolved.sourceUri || marker.pluginId !== id))
19517
19612
  throw new Error(`codex cache slot ${targetDir} has a different owned source identity; refusing to replace it`);
19518
- if (existsSync23(targetDir) && marker === null && !sameTree2(stage, targetDir)) {
19613
+ if (existsSync22(targetDir) && marker === null && !sameTree2(stage, targetDir)) {
19519
19614
  if (!opts.adoptExisting)
19520
19615
  throw new Error(`codex cache slot ${targetDir} is unowned and differs from the staged representation; pass --adopt-existing to take ownership explicitly`);
19521
19616
  validateCachedIdentity(targetDir, plugin.name, version);
@@ -19541,8 +19636,8 @@ var codexWriter = {
19541
19636
  ensureNativeManifest(stage, plugin.name, version);
19542
19637
  validateStage(stage);
19543
19638
  writeFileSync7(join29(stage, OWNERSHIP2), JSON.stringify({ source: resolved.sourceUri, pluginId: id, fingerprint: plugin.contentFingerprint ?? "" }));
19544
- const identicalUnowned = existsSync23(targetDir) && marker === null && sameTree2(stage, targetDir);
19545
- if (existsSync23(targetDir) && marker === null && !identicalUnowned) {
19639
+ const identicalUnowned = existsSync22(targetDir) && marker === null && sameTree2(stage, targetDir);
19640
+ if (existsSync22(targetDir) && marker === null && !identicalUnowned) {
19546
19641
  if (!opts?.adoptExisting)
19547
19642
  throw new Error(`codex cache slot ${targetDir} is unowned and differs from the staged representation; pass --adopt-existing to take ownership explicitly`);
19548
19643
  validateCachedIdentity(targetDir, plugin.name, version);
@@ -19579,7 +19674,7 @@ var codexWriter = {
19579
19674
  }
19580
19675
  },
19581
19676
  async pin(plugin, opts) {
19582
- if (plugin.path === undefined || !existsSync23(plugin.path))
19677
+ if (plugin.path === undefined || !existsSync22(plugin.path))
19583
19678
  return { changes: [], refusals: [] };
19584
19679
  return pinPluginMcpFiles(plugin.path, mcpCandidates2(), opts);
19585
19680
  },
@@ -19590,7 +19685,7 @@ var codexWriter = {
19590
19685
  const owned = [];
19591
19686
  if (at !== -1) {
19592
19687
  const slot = join29(codexHome(), "plugins", "cache", id.slice(at + 1), id.slice(0, at));
19593
- if (existsSync23(slot)) {
19688
+ if (existsSync22(slot)) {
19594
19689
  assertNoSymlinks3(slot);
19595
19690
  for (const version of readdirSync14(slot)) {
19596
19691
  const candidate = join29(slot, version);
@@ -19601,7 +19696,7 @@ var codexWriter = {
19601
19696
  }
19602
19697
  }
19603
19698
  }
19604
- if (existsSync23(configPath)) {
19699
+ if (existsSync22(configPath)) {
19605
19700
  const toml = readFileSync23(configPath, "utf8");
19606
19701
  const header = `[plugins."${id}"]`;
19607
19702
  const idx = toml.indexOf(header);
@@ -19610,7 +19705,7 @@ var codexWriter = {
19610
19705
  [`, idx + header.length);
19611
19706
  const end = nextTable === -1 ? toml.length : nextTable;
19612
19707
  const block = toml.slice(idx, end);
19613
- const withoutEnabled = block.replace(/^enabled\s*=\s*(true|false)\s*\n?/mu, "");
19708
+ const withoutEnabled = block.replace(enabledAssignment("true|false", true), "");
19614
19709
  const remaining = withoutEnabled.slice(header.length).trim();
19615
19710
  const replacement = remaining === "" ? "" : `${withoutEnabled.trimEnd()}
19616
19711
  enabled = false
@@ -19622,8 +19717,12 @@ enabled = false
19622
19717
  rmSync7(candidate, { recursive: true, force: true });
19623
19718
  }
19624
19719
  };
19720
+ var ENABLED_ASSIGNMENT_TAIL = String.raw`[ \t]*(?:#.*)?`;
19721
+ function enabledAssignment(value, consumeNewline = false) {
19722
+ return new RegExp(`^enabled\\s*=\\s*(?:${value})${ENABLED_ASSIGNMENT_TAIL}$${consumeNewline ? "\\n?" : ""}`, "mu");
19723
+ }
19625
19724
  function enable(configPath, id) {
19626
- let toml = existsSync23(configPath) ? readFileSync23(configPath, "utf8") : "";
19725
+ let toml = existsSync22(configPath) ? readFileSync23(configPath, "utf8") : "";
19627
19726
  parseConfigToml(toml, configPath);
19628
19727
  let newToml = toml;
19629
19728
  const header = `[plugins."${id}"]`;
@@ -19633,7 +19732,7 @@ function enable(configPath, id) {
19633
19732
  [`, idx + header.length);
19634
19733
  const blockEnd = nextTable !== -1 ? nextTable : toml.length;
19635
19734
  const block = toml.slice(idx, blockEnd);
19636
- const enabled = /^([ \t]*enabled[ \t]*=[ \t]*)(true|false)([ \t]*(?:#.*)?)$/gmu;
19735
+ const enabled = new RegExp(`^([ \\t]*enabled[ \\t]*=[ \\t]*)(true|false)(${ENABLED_ASSIGNMENT_TAIL})$`, "gmu");
19637
19736
  const matches = [...block.matchAll(enabled)];
19638
19737
  if (matches.length > 1)
19639
19738
  throw new Error(`duplicate enabled keys in Codex plugin config: ${id}`);
@@ -19667,7 +19766,7 @@ function parseConfigToml(text, path) {
19667
19766
  }
19668
19767
  }
19669
19768
  function isEnabled(configPath, id) {
19670
- if (!existsSync23(configPath))
19769
+ if (!existsSync22(configPath))
19671
19770
  return false;
19672
19771
  const toml = readFileSync23(configPath, "utf8");
19673
19772
  const header = `[plugins."${id}"]`;
@@ -19677,10 +19776,10 @@ function isEnabled(configPath, id) {
19677
19776
  const nextTable = toml.indexOf(`
19678
19777
  [`, idx + header.length);
19679
19778
  const block = toml.slice(idx, nextTable === -1 ? toml.length : nextTable);
19680
- return !/^enabled\s*=\s*false\s*$/mu.test(block);
19779
+ return !enabledAssignment("false").test(block);
19681
19780
  }
19682
19781
  function readConfigSnapshot(path) {
19683
- if (!existsSync23(path))
19782
+ if (!existsSync22(path))
19684
19783
  return { existed: false };
19685
19784
  const read = readFileSync23;
19686
19785
  return { existed: true, bytes: read(path) };
@@ -19701,7 +19800,7 @@ function validVersionSegment(value) {
19701
19800
  }
19702
19801
  function readOwnership2(dir) {
19703
19802
  const file = join29(dir, OWNERSHIP2);
19704
- if (!existsSync23(file))
19803
+ if (!existsSync22(file))
19705
19804
  return null;
19706
19805
  try {
19707
19806
  const value = JSON.parse(readFileSync23(file, "utf8"));
@@ -19725,12 +19824,12 @@ function validateStage(stage) {
19725
19824
  if (readPluginManifest(stage) === undefined)
19726
19825
  throw new Error("Codex stage has no Agent Plugins manifest");
19727
19826
  const skills = join29(stage, "skills");
19728
- if (existsSync23(skills) && !statSync10(skills).isDirectory())
19827
+ if (existsSync22(skills) && !statSync10(skills).isDirectory())
19729
19828
  throw new Error("Codex stage skills path is not a directory");
19730
19829
  }
19731
19830
  function validateCachedIdentity(target, expectedName, expectedVersion) {
19732
19831
  const candidates = [join29(target, ".codex-plugin", "plugin.json"), join29(target, "plugin.json"), join29(target, ".plugin", "plugin.json")];
19733
- const manifest = candidates.find(existsSync23);
19832
+ const manifest = candidates.find(existsSync22);
19734
19833
  if (manifest === undefined)
19735
19834
  throw new Error(`unowned Codex cache slot has no manifest: ${target}`);
19736
19835
  const value = JSON.parse(readFileSync23(manifest, "utf8"));
@@ -19740,7 +19839,7 @@ function validateCachedIdentity(target, expectedName, expectedVersion) {
19740
19839
  if (record["name"] === expectedName && record["version"] === expectedVersion)
19741
19840
  return;
19742
19841
  if (manifest === candidates[0] && record["name"] === expectedName && nativeBuildVariant(expectedVersion, record["version"])) {
19743
- const canonical = candidates.slice(1).find(existsSync23);
19842
+ const canonical = candidates.slice(1).find(existsSync22);
19744
19843
  if (canonical !== undefined) {
19745
19844
  const canonicalValue = JSON.parse(readFileSync23(canonical, "utf8"));
19746
19845
  if (typeof canonicalValue === "object" && canonicalValue !== null && !Array.isArray(canonicalValue)) {
@@ -19765,7 +19864,7 @@ function ensureNativeManifest(stage, fallbackName, fallbackVersion) {
19765
19864
  throw new Error("Codex stage has no Agent Plugins manifest");
19766
19865
  for (const path of ["plugin.json", ".plugin/plugin.json", ".claude-plugin/plugin.json"]) {
19767
19866
  const file = join29(stage, path);
19768
- if (existsSync23(file) && JSON.parse(readFileSync23(file, "utf8")).mcpServers !== undefined) {
19867
+ if (existsSync22(file) && JSON.parse(readFileSync23(file, "utf8")).mcpServers !== undefined) {
19769
19868
  throw new Error("Codex inline manifest MCP projection is unverified; use mcp.json or .mcp.json");
19770
19869
  }
19771
19870
  }
@@ -19773,7 +19872,7 @@ function ensureNativeManifest(stage, fallbackName, fallbackVersion) {
19773
19872
  const version = sourceManifest.version ?? fallbackVersion;
19774
19873
  const description = sourceManifest.description ?? `Plugin ${name}`;
19775
19874
  let overlay = {};
19776
- if (existsSync23(native)) {
19875
+ if (existsSync22(native)) {
19777
19876
  const value = JSON.parse(readFileSync23(native, "utf8"));
19778
19877
  if (typeof value !== "object" || value === null || Array.isArray(value))
19779
19878
  throw new Error("Codex native plugin manifest must be an object");
@@ -19787,10 +19886,10 @@ function ensureNativeManifest(stage, fallbackName, fallbackVersion) {
19787
19886
  }
19788
19887
  }
19789
19888
  const pointer = overlay["mcpServers"];
19790
- if (pointer !== undefined && (typeof pointer !== "string" || !pointer.startsWith("./") || pointer.includes("\\") || pointer.split("/").includes("..") || !existsSync23(join29(stage, pointer)))) {
19889
+ if (pointer !== undefined && (typeof pointer !== "string" || !pointer.startsWith("./") || pointer.includes("\\") || pointer.split("/").includes("..") || !existsSync22(join29(stage, pointer)))) {
19791
19890
  throw new Error("Codex native MCP pointer must name an existing plugin-local file");
19792
19891
  }
19793
- const mcpFiles = ["mcp.json", ".mcp.json", ...typeof pointer === "string" ? [pointer] : []].map((path) => join29(stage, path)).filter(existsSync23);
19892
+ const mcpFiles = ["mcp.json", ".mcp.json", ...typeof pointer === "string" ? [pointer] : []].map((path) => join29(stage, path)).filter(existsSync22);
19794
19893
  const declarations = mcpFiles.map((file) => {
19795
19894
  const value = JSON.parse(readFileSync23(file, "utf8"));
19796
19895
  if (value === null || typeof value !== "object" || Array.isArray(value) || !("mcpServers" in value) || value.mcpServers === null || typeof value.mcpServers !== "object" || Array.isArray(value.mcpServers)) {
@@ -19807,7 +19906,7 @@ function ensureNativeManifest(stage, fallbackName, fallbackVersion) {
19807
19906
  version,
19808
19907
  description,
19809
19908
  skills: overlay["skills"] ?? "./skills/",
19810
- ...overlay["mcpServers"] === undefined && existsSync23(join29(stage, "mcp.json")) && !existsSync23(join29(stage, ".mcp.json")) ? { mcpServers: "./mcp.json" } : {}
19909
+ ...overlay["mcpServers"] === undefined && existsSync22(join29(stage, "mcp.json")) && !existsSync22(join29(stage, ".mcp.json")) ? { mcpServers: "./mcp.json" } : {}
19811
19910
  }));
19812
19911
  }
19813
19912
  function mcpDeclarationIdentity(value) {
@@ -19825,9 +19924,9 @@ function assertManagedPath2(root, target) {
19825
19924
  for (const part of ["", ...suffix.split("/").filter(Boolean)]) {
19826
19925
  if (part !== "")
19827
19926
  current = join29(current, part);
19828
- if (!existsSync23(current))
19927
+ if (!existsSync22(current))
19829
19928
  continue;
19830
- const stat = lstatSync14(current);
19929
+ const stat = lstatSync15(current);
19831
19930
  if (stat.isSymbolicLink())
19832
19931
  throw new Error(`Codex managed path component is a symlink: ${current}`);
19833
19932
  if (!stat.isDirectory())
@@ -19836,16 +19935,16 @@ function assertManagedPath2(root, target) {
19836
19935
  }
19837
19936
  function assertManagedConfigPath(root, path) {
19838
19937
  assertManagedPath2(root, dirname9(path));
19839
- if (!existsSync23(path))
19938
+ if (!existsSync22(path))
19840
19939
  return;
19841
- const stat = lstatSync14(path);
19940
+ const stat = lstatSync15(path);
19842
19941
  if (stat.isSymbolicLink())
19843
19942
  throw new Error(`Codex managed config is a symlink: ${path}`);
19844
19943
  if (!stat.isFile())
19845
19944
  throw new Error(`Codex managed config is not a file: ${path}`);
19846
19945
  }
19847
19946
  function activate2(stage, target, slot) {
19848
- if (!existsSync23(target)) {
19947
+ if (!existsSync22(target)) {
19849
19948
  renameSync4(stage, target);
19850
19949
  return { commit: () => {}, rollback: () => rmSync7(target, { recursive: true, force: true }) };
19851
19950
  }
@@ -19920,7 +20019,7 @@ function assertNoSymlinks3(dir) {
19920
20019
  const walk = (current) => {
19921
20020
  for (const entry of readdirSync14(current)) {
19922
20021
  const path = join29(current, entry);
19923
- const stat = lstatSync14(path);
20022
+ const stat = lstatSync15(path);
19924
20023
  if (stat.isSymbolicLink())
19925
20024
  throw new Error(`Codex managed slot contains symlink: ${path}`);
19926
20025
  if (stat.isDirectory())
@@ -20049,10 +20148,10 @@ function revalidateCodexTarget(handle) {
20049
20148
  for (const root of handle.expected.contentRoots)
20050
20149
  assertRequestedCacheOwnership(root.path, handle.prior.contentRoots);
20051
20150
  }
20052
- if (existsSync23(join29(bundle, "marketplace.json"))) {
20151
+ if (existsSync22(join29(bundle, "marketplace.json"))) {
20053
20152
  const metadata = JSON.parse(readFileSync23(join29(bundle, "marketplace.json"), "utf8"));
20054
20153
  const checkout = marketplaceCheckout(metadata.marketplace);
20055
- const actual = existsSync23(checkout) ? fingerprintTree(checkout) : null;
20154
+ const actual = existsSync22(checkout) ? fingerprintTree(checkout) : null;
20056
20155
  if (actual !== metadata.fingerprint)
20057
20156
  throw new Error("Codex marketplace checkout changed after rollback capture");
20058
20157
  }
@@ -20249,13 +20348,13 @@ async function retireCodex(prepared) {
20249
20348
  }
20250
20349
  function restampNativeUpgrade(prepared) {
20251
20350
  const markerPath = join29(prepared.stagingRoot, OWNERSHIP2);
20252
- if (!existsSync23(markerPath))
20351
+ if (!existsSync22(markerPath))
20253
20352
  return;
20254
20353
  const marker = readFileSync23(markerPath, "utf8");
20255
20354
  const version = pluginVersion(prepared.stagingRoot);
20256
20355
  if (validVersionSegment(version)) {
20257
20356
  const destination = cacheDestination(prepared.handle.nativeId, version);
20258
- if (existsSync23(destination) && statSync10(destination).isDirectory()) {
20357
+ if (existsSync22(destination) && statSync10(destination).isDirectory()) {
20259
20358
  assertManagedPath2(codexHome(), destination);
20260
20359
  writeFileSync7(join29(destination, OWNERSHIP2), marker);
20261
20360
  }
@@ -20264,7 +20363,7 @@ function restampNativeUpgrade(prepared) {
20264
20363
  if (nativeId === prepared.handle.nativeId)
20265
20364
  continue;
20266
20365
  const path = codex.listInstalled().find((plugin) => plugin.id === nativeId)?.path;
20267
- if (path === undefined || !existsSync23(path))
20366
+ if (path === undefined || !existsSync22(path))
20268
20367
  continue;
20269
20368
  const existing = readOwnership2(path);
20270
20369
  if (existing?.pluginId === nativeId)
@@ -20283,7 +20382,7 @@ function restampNativeUpgrade(prepared) {
20283
20382
  function priorInstallMarker(prepared, nativeId) {
20284
20383
  const bundle = rollbackBundle(prepared.handle.attemptId, prepared.handle.operationId);
20285
20384
  const manifestPath = join29(bundle, "manifest.json");
20286
- if (!existsSync23(manifestPath))
20385
+ if (!existsSync22(manifestPath))
20287
20386
  return null;
20288
20387
  const manifest = parseRollbackManifest(readFileSync23(manifestPath, "utf8"));
20289
20388
  const install = manifest.installs.find((item) => item.nativeId === nativeId);
@@ -20320,11 +20419,11 @@ function readCodexInstall(handle) {
20320
20419
  function cleanupCodexStage(reference) {
20321
20420
  releasePriorSourceRepair(reference);
20322
20421
  const stage = resolve16(join29(codexHome(), ".plgnz-lifecycle", `${reference.attemptId}:${reference.operationId}`));
20323
- if (existsSync23(stage))
20422
+ if (existsSync22(stage))
20324
20423
  rmSync7(stage, { recursive: true, force: true });
20325
20424
  const rollback = rollbackBundle(reference.attemptId, reference.operationId);
20326
20425
  assertManagedPath2(codexHome(), rollback);
20327
- if (existsSync23(rollback))
20426
+ if (existsSync22(rollback))
20328
20427
  rmSync7(rollback, { recursive: true, force: true });
20329
20428
  return { cleanupId: `cleanup:${reference.attemptId}:${reference.operationId}`, completed: true };
20330
20429
  }
@@ -20384,7 +20483,7 @@ function pluginDataRoots(nativeId) {
20384
20483
  ];
20385
20484
  }
20386
20485
  function retainedTree(paths) {
20387
- const present = paths.filter((path) => existsSync23(path));
20486
+ const present = paths.filter((path) => existsSync22(path));
20388
20487
  const [only, ...rest] = present;
20389
20488
  if (only === undefined)
20390
20489
  return { state: "absent", fingerprint: null };
@@ -20425,7 +20524,7 @@ function cacheDestination(nativeId, version) {
20425
20524
  }
20426
20525
  function cacheFingerprint(nativeId) {
20427
20526
  const path = codex.listInstalled().find((plugin) => plugin.id === nativeId)?.path;
20428
- if (path === undefined || !existsSync23(path))
20527
+ if (path === undefined || !existsSync22(path))
20429
20528
  return null;
20430
20529
  try {
20431
20530
  return fingerprintTree(path);
@@ -20476,7 +20575,7 @@ function codexRollbackReference(attemptId, operationId) {
20476
20575
  const reference = `codex:${attemptId}:${operationId}`;
20477
20576
  const bundle = rollbackBundle(attemptId, operationId);
20478
20577
  const capture = join29(bundle, "native-cache.json");
20479
- if (!existsSync23(capture))
20578
+ if (!existsSync22(capture))
20480
20579
  return reference;
20481
20580
  const digest = new CryptoHasher("sha256").update(readFileSync23(capture, "utf8")).update("\x00").update(readFileSync23(join29(bundle, "manifest.json"), "utf8")).digest("hex");
20482
20581
  return `${reference}:native-cache-sha256:${digest}`;
@@ -20488,14 +20587,14 @@ function nativeCacheFingerprint(root, ignoreOwnership = false) {
20488
20587
  const hash = new CryptoHasher("sha256");
20489
20588
  const read = readFileSync23;
20490
20589
  const walk = (path, relative) => {
20491
- const stat = lstatSync14(path);
20590
+ const stat = lstatSync15(path);
20492
20591
  if (stat.isSymbolicLink() || !stat.isDirectory() && !stat.isFile())
20493
20592
  throw new Error(`Codex native cache contains an unsafe resource: ${path}`);
20494
20593
  hash.update(`${stat.isDirectory() ? "d" : "f"}\x00${relative}\x00${stat.mode & 4095}\x00`);
20495
20594
  if (stat.isDirectory()) {
20496
20595
  for (const entry of readdirSync14(path).sort()) {
20497
20596
  if (ignoreOwnership && relative === "" && entry === OWNERSHIP2) {
20498
- const marker = lstatSync14(join29(path, entry));
20597
+ const marker = lstatSync15(join29(path, entry));
20499
20598
  if (marker.isSymbolicLink() || !marker.isFile())
20500
20599
  throw new Error("Codex attempted cache ownership marker is unsafe");
20501
20600
  continue;
@@ -20525,7 +20624,7 @@ function nativeSlotIsOwned(installation, source) {
20525
20624
  const activeProof = nativeCacheFingerprint(active.path);
20526
20625
  return readdirSync14(slot).every((version) => {
20527
20626
  const path = join29(slot, version);
20528
- const stat = lstatSync14(path);
20627
+ const stat = lstatSync15(path);
20529
20628
  if (stat.isSymbolicLink())
20530
20629
  throw new Error("Codex native cache slot is redirected");
20531
20630
  if (!validVersionSegment(version) || !stat.isDirectory())
@@ -20574,7 +20673,7 @@ function captureNativeCacheSnapshots(projection) {
20574
20673
  }
20575
20674
  function readNativeCacheSnapshots(handle) {
20576
20675
  const file = join29(rollbackBundle(handle.attemptId, handle.operationId), "native-cache.json");
20577
- if (!existsSync23(file))
20676
+ if (!existsSync22(file))
20578
20677
  throw new Error("Codex complete native cache rollback capture is missing");
20579
20678
  if (handle.rollbackReference !== codexRollbackReference(handle.attemptId, handle.operationId))
20580
20679
  throw new Error("Codex complete native cache authority differs from its sealed rollback reference");
@@ -20615,7 +20714,7 @@ function saveCodexRollback(attemptId, operationId, nativeIds) {
20615
20714
  assertManagedPath2(codexHome(), bundle);
20616
20715
  rmSync7(bundle, { recursive: true, force: true });
20617
20716
  mkdirSync7(bundle, { recursive: true });
20618
- const toml = existsSync23(configFile()) ? readFileSync23(configFile(), "utf8") : "";
20717
+ const toml = existsSync22(configFile()) ? readFileSync23(configFile(), "utf8") : "";
20619
20718
  const tables = nativeIds.map((nativeId) => ({ nativeId, block: extractPluginTable(toml, nativeId) }));
20620
20719
  const installs = nativeIds.map((nativeId, index) => {
20621
20720
  const slot = pluginSlot(nativeId);
@@ -20632,7 +20731,7 @@ function saveCodexRollback(attemptId, operationId, nativeIds) {
20632
20731
  function restoreCodexRollback(handle) {
20633
20732
  const bundle = rollbackBundle(handle.attemptId, handle.operationId);
20634
20733
  const manifestPath = join29(bundle, "manifest.json");
20635
- if (!existsSync23(manifestPath))
20734
+ if (!existsSync22(manifestPath))
20636
20735
  throw new Error(`codex lifecycle rollback bundle is missing: ${handle.operationId}`);
20637
20736
  const manifest = parseRollbackManifest(readFileSync23(manifestPath, "utf8"));
20638
20737
  assertMarketplaceRollbackCurrent(handle);
@@ -20669,7 +20768,7 @@ function marketplaceCheckout(marketplace) {
20669
20768
  return path;
20670
20769
  }
20671
20770
  function assertNativeRollbackSurfaces(handle, manifest, bundle) {
20672
- const config = existsSync23(configFile()) ? readFileSync23(configFile(), "utf8") : "";
20771
+ const config = existsSync22(configFile()) ? readFileSync23(configFile(), "utf8") : "";
20673
20772
  for (const table of manifest.tables) {
20674
20773
  if (extractPluginTable(config, table.nativeId) !== table.block)
20675
20774
  throw new Error("Codex affected plugin config changed outside the captured native attempt; refusing rollback before any restore write");
@@ -20684,14 +20783,14 @@ function assertNativeRollbackSurfaces(handle, manifest, bundle) {
20684
20783
  const currentFingerprint = nativeCacheFingerprint(slot.path);
20685
20784
  if (currentFingerprint === slot.fingerprint)
20686
20785
  return { ...slot, currentFingerprint };
20687
- const projected = projections.find((path) => existsSync23(path) && readOwnership2(path)?.pluginId === slot.nativeId);
20786
+ const projected = projections.find((path) => existsSync22(path) && readOwnership2(path)?.pluginId === slot.nativeId);
20688
20787
  let containsCandidate = false;
20689
20788
  for (const version of readdirSync14(slot.path)) {
20690
20789
  const path = join29(slot.path, version);
20691
- if (!validVersionSegment(version) || !lstatSync14(path).isDirectory())
20790
+ if (!validVersionSegment(version) || !lstatSync15(path).isDirectory())
20692
20791
  throw new Error("Codex complete cache contains an unproven resource; refusing rollback before any restore write");
20693
20792
  const priorVersion = join29(saved, version);
20694
- if (existsSync23(priorVersion) && nativeCacheFingerprint(path) === nativeCacheFingerprint(priorVersion))
20793
+ if (existsSync22(priorVersion) && nativeCacheFingerprint(path) === nativeCacheFingerprint(priorVersion))
20695
20794
  continue;
20696
20795
  if (projected === undefined || version !== pluginVersion(projected) || (readOwnership2(path) === null ? nativeCacheFingerprint(path, true) !== nativeCacheFingerprint(projected, true) : nativeCacheFingerprint(path) !== nativeCacheFingerprint(projected))) {
20697
20796
  throw new Error("Codex complete cache changed outside the captured native attempt; refusing rollback before any restore write");
@@ -20710,7 +20809,7 @@ function captureMarketplaceRollback(projection) {
20710
20809
  throw new Error("native Codex mutation has no bounded marketplace");
20711
20810
  const checkout = marketplaceCheckout(marketplace);
20712
20811
  const bundle = rollbackBundle(projection.attemptId, projection.operationId);
20713
- const fingerprint = existsSync23(checkout) ? fingerprintTree(checkout) : null;
20812
+ const fingerprint = existsSync22(checkout) ? fingerprintTree(checkout) : null;
20714
20813
  if (fingerprint !== null) {
20715
20814
  const snapshot = join29(bundle, "marketplace");
20716
20815
  cpSync6(checkout, snapshot, { recursive: true });
@@ -20721,13 +20820,13 @@ function captureMarketplaceRollback(projection) {
20721
20820
  }
20722
20821
  function captureAttemptedMarketplace(handle) {
20723
20822
  const metadata = join29(rollbackBundle(handle.attemptId, handle.operationId), "marketplace.json");
20724
- if (!existsSync23(metadata))
20823
+ if (!existsSync22(metadata))
20725
20824
  return;
20726
20825
  const marketplace = marketplaceOf(handle.nativeId);
20727
20826
  if (marketplace === null || handle.sourceLocator === null)
20728
20827
  return;
20729
20828
  const checkout = marketplaceCheckout(marketplace);
20730
- if (!existsSync23(checkout))
20829
+ if (!existsSync22(checkout))
20731
20830
  return;
20732
20831
  const capture = JSON.parse(readFileSync23(metadata, "utf8"));
20733
20832
  if (typeof capture["sourceFingerprint"] !== "string" || !/^[0-9a-f]{64}$/u.test(capture["sourceFingerprint"]))
@@ -20742,14 +20841,14 @@ function captureAttemptedMarketplace(handle) {
20742
20841
  }
20743
20842
  function assertMarketplaceRollbackCurrent(handle) {
20744
20843
  const metadata = join29(rollbackBundle(handle.attemptId, handle.operationId), "marketplace.json");
20745
- if (!existsSync23(metadata))
20844
+ if (!existsSync22(metadata))
20746
20845
  return;
20747
20846
  const row = JSON.parse(readFileSync23(metadata, "utf8"));
20748
20847
  const marketplace = marketplaceOf(handle.nativeId);
20749
20848
  if (marketplace === null || row["marketplace"] !== marketplace || row["fingerprint"] !== null && (typeof row["fingerprint"] !== "string" || !/^[0-9a-f]{64}$/u.test(row["fingerprint"])) || row["attemptedFingerprint"] !== undefined && (typeof row["attemptedFingerprint"] !== "string" || !/^[0-9a-f]{64}$/u.test(row["attemptedFingerprint"])))
20750
20849
  throw new Error("invalid Codex marketplace rollback capture");
20751
20850
  const checkout = marketplaceCheckout(marketplace);
20752
- const current = existsSync23(checkout) ? fingerprintTree(checkout) : null;
20851
+ const current = existsSync22(checkout) ? fingerprintTree(checkout) : null;
20753
20852
  if (current !== row["fingerprint"] && current !== row["attemptedFingerprint"]) {
20754
20853
  throw new Error("Codex marketplace checkout changed outside the captured native attempt; refusing rollback before any restore write");
20755
20854
  }
@@ -20760,7 +20859,7 @@ function assertMarketplaceRollbackCurrent(handle) {
20760
20859
  function restoreMarketplaceRollback(handle) {
20761
20860
  const bundle = rollbackBundle(handle.attemptId, handle.operationId);
20762
20861
  const metadata = join29(bundle, "marketplace.json");
20763
- if (!existsSync23(metadata))
20862
+ if (!existsSync22(metadata))
20764
20863
  return;
20765
20864
  const capture = JSON.parse(readFileSync23(metadata, "utf8"));
20766
20865
  if (typeof capture !== "object" || capture === null || Array.isArray(capture))
@@ -20771,7 +20870,7 @@ function restoreMarketplaceRollback(handle) {
20771
20870
  throw new Error("invalid Codex marketplace rollback identity");
20772
20871
  const checkout = marketplaceCheckout(marketplace);
20773
20872
  if (row["fingerprint"] === null) {
20774
- if (existsSync23(checkout))
20873
+ if (existsSync22(checkout))
20775
20874
  rmSync7(checkout, { recursive: true });
20776
20875
  return;
20777
20876
  }
@@ -20803,18 +20902,18 @@ function pluginSlot(nativeId) {
20803
20902
  return join29(codexHome(), "plugins", "cache", marketplace, name);
20804
20903
  }
20805
20904
  function slotVersions(slot) {
20806
- if (!existsSync23(slot))
20905
+ if (!existsSync22(slot))
20807
20906
  return [];
20808
20907
  return readdirSync14(slot).filter((version) => {
20809
20908
  try {
20810
- return lstatSync14(join29(slot, version)).isDirectory();
20909
+ return lstatSync15(join29(slot, version)).isDirectory();
20811
20910
  } catch {
20812
20911
  return false;
20813
20912
  }
20814
20913
  }).sort();
20815
20914
  }
20816
20915
  function removeUnsnapshotVersions(slot, versions) {
20817
- if (slot === null || !existsSync23(slot))
20916
+ if (slot === null || !existsSync22(slot))
20818
20917
  return;
20819
20918
  assertManagedPath2(codexHome(), slot);
20820
20919
  const kept = new Set(versions);
@@ -20827,10 +20926,10 @@ function removeUnsnapshotVersions(slot, versions) {
20827
20926
  }
20828
20927
  }
20829
20928
  function rollbackSurface(nativeIds) {
20830
- const config = existsSync23(configFile()) ? readFileSync23(configFile(), "utf8") : "absent";
20929
+ const config = existsSync22(configFile()) ? readFileSync23(configFile(), "utf8") : "absent";
20831
20930
  const slots = nativeIds.map((nativeId) => {
20832
20931
  const slot = pluginSlot(nativeId);
20833
- if (slot === null || !existsSync23(slot))
20932
+ if (slot === null || !existsSync22(slot))
20834
20933
  return `${nativeId}:`;
20835
20934
  return `${nativeId}:${slotVersions(slot).map((version) => {
20836
20935
  const path = join29(slot, version);
@@ -20860,7 +20959,7 @@ function extractPluginTable(toml, id) {
20860
20959
  }
20861
20960
  function restorePluginTables(tables) {
20862
20961
  const configPath = configFile();
20863
- const current = existsSync23(configPath) ? readFileSync23(configPath, "utf8") : "";
20962
+ const current = existsSync22(configPath) ? readFileSync23(configPath, "utf8") : "";
20864
20963
  let next = current;
20865
20964
  for (const table of tables)
20866
20965
  next = applyPluginTable(next, table.nativeId, table.block);
@@ -20998,7 +21097,7 @@ function nativeProjection2(request) {
20998
21097
  }
20999
21098
  if (request.pins.length > 0)
21000
21099
  return { kind: "requires-managed", reasonId: "pins-present" };
21001
- if (existsSync23(join29(request.snapshot.snapshotRoot, codexMarketplaceMetadataFile))) {
21100
+ if (existsSync22(join29(request.snapshot.snapshotRoot, codexMarketplaceMetadataFile))) {
21002
21101
  return { kind: "requires-managed", reasonId: "native-reserved-source-metadata" };
21003
21102
  }
21004
21103
  const marketplace = marketplaceOf(request.snapshot.nativeId);
@@ -21024,16 +21123,16 @@ function nativeProjection2(request) {
21024
21123
  }
21025
21124
  function assertRequestedCacheOwnership(destination, observedRoots) {
21026
21125
  assertManagedPath2(codexHome(), destination);
21027
- if (existsSync23(destination) && !observedRoots.some((root) => root.path === destination)) {
21126
+ if (existsSync22(destination) && !observedRoots.some((root) => root.path === destination)) {
21028
21127
  throw new Error("Codex inactive requested version has no captured active ownership; refusing to replace it");
21029
21128
  }
21030
21129
  const slot = dirname9(destination);
21031
- if (!existsSync23(slot))
21130
+ if (!existsSync22(slot))
21032
21131
  return;
21033
21132
  const requested = destination.slice(slot.length + 1);
21034
21133
  for (const version of readdirSync14(slot)) {
21035
21134
  const path = join29(slot, version);
21036
- if (lstatSync14(path).isDirectory() && wins(version, requested) && !observedRoots.some((root) => root.path === path)) {
21135
+ if (lstatSync15(path).isDirectory() && wins(version, requested) && !observedRoots.some((root) => root.path === path)) {
21037
21136
  throw new Error(`Codex inactive cache version ${version} has no captured retirement authority and would remain active over ${requested}`);
21038
21137
  }
21039
21138
  }
@@ -21083,7 +21182,7 @@ function marketplaceOf(nativeId) {
21083
21182
  return nativeId.slice(at + 1);
21084
21183
  }
21085
21184
  function readConfigDocument() {
21086
- if (!existsSync23(configFile()))
21185
+ if (!existsSync22(configFile()))
21087
21186
  return null;
21088
21187
  try {
21089
21188
  const parsed = parse(readFileSync23(configFile(), "utf8"));
@@ -21121,7 +21220,7 @@ function comparePrerelease2(left, right) {
21121
21220
  }
21122
21221
 
21123
21222
  // src/hosts/kimi-writer.ts
21124
- import { cpSync as cpSync7, existsSync as existsSync24, lstatSync as lstatSync15, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync7, readFileSync as readFileSync24, readdirSync as readdirSync15, realpathSync as realpathSync4, renameSync as renameSync5, rmSync as rmSync8, statSync as statSync11, writeFileSync as writeFileSync8 } from "node:fs";
21223
+ import { cpSync as cpSync7, existsSync as existsSync23, lstatSync as lstatSync16, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync7, readFileSync as readFileSync24, readdirSync as readdirSync15, realpathSync as realpathSync4, renameSync as renameSync5, rmSync as rmSync8, statSync as statSync11, writeFileSync as writeFileSync8 } from "node:fs";
21125
21224
  import { dirname as dirname10, isAbsolute as isAbsolute11, join as join30, resolve as resolve17 } from "node:path";
21126
21225
  import { tmpdir as tmpdir4 } from "node:os";
21127
21226
  var MARKER4 = ".plgnz-install.json";
@@ -21137,7 +21236,7 @@ var samePhysicalKimiNativeIdentity = (plugin, prior, observation) => {
21137
21236
  const managed = managedPluginPath(plugin.name);
21138
21237
  const registryFile = join30(pluginsDir2(), "installed.json");
21139
21238
  assertKimiManaged(plugin.name, managed, registryFile);
21140
- if (!existsSync24(managed))
21239
+ if (!existsSync23(managed))
21141
21240
  return null;
21142
21241
  const rows = readRegistry2(registryFile).plugins.filter((row) => row.id === plugin.name || sameRoot(row.root, managed));
21143
21242
  if (rows.length !== 1 || rows[0].id !== plugin.name || rows[0].enabled !== true || !sameRoot(rows[0].root, managed))
@@ -21188,8 +21287,8 @@ var kimiWriter = {
21188
21287
  const differentSource = marker !== null && !lifecycleLocalSource && marker.source !== resolved.sourceUri;
21189
21288
  if (marker !== null && (differentSource || !markerHasExpectedIdentity))
21190
21289
  throw new Error(`Kimi plugin ${id} belongs to another source; refusing to replace it`);
21191
- const same = existsSync24(target) && sameTree3(stage, target);
21192
- if (existsSync24(target) && marker === null && !same) {
21290
+ const same = existsSync23(target) && sameTree3(stage, target);
21291
+ if (existsSync23(target) && marker === null && !same) {
21193
21292
  if (!opts?.adoptExisting)
21194
21293
  throw new Error(`Kimi managed plugin ${id} is unowned and differs from the staged representation; pass --adopt-existing to take ownership explicitly`);
21195
21294
  validateNativeIdentity(target, id);
@@ -21207,13 +21306,13 @@ var kimiWriter = {
21207
21306
  }
21208
21307
  if (unchanged)
21209
21308
  return "unchanged";
21210
- const registryBefore = existsSync24(registryFile) ? readFileSync24(registryFile, "utf8") : undefined;
21309
+ const registryBefore = existsSync23(registryFile) ? readFileSync24(registryFile, "utf8") : undefined;
21211
21310
  const backup = moveAside2(target, managedRoot);
21212
21311
  try {
21213
21312
  await nativeInstall(stage, kimiRootPath(), resolveKimiBinary());
21214
21313
  const after = readRegistry2(registryFile);
21215
21314
  const row = after.plugins.find((candidate) => candidate.id === id);
21216
- if (row === undefined || row.enabled !== true || !sameRoot(row.root, target) || !existsSync24(target) || !sameTree3(stage, target)) {
21315
+ if (row === undefined || row.enabled !== true || !sameRoot(row.root, target) || !existsSync23(target) || !sameTree3(stage, target)) {
21217
21316
  throw new Error(`Kimi native install did not produce enabled managed plugin ${id}`);
21218
21317
  }
21219
21318
  } catch (error) {
@@ -21228,7 +21327,7 @@ var kimiWriter = {
21228
21327
  }
21229
21328
  },
21230
21329
  async pin(plugin, opts) {
21231
- if (plugin.path === undefined || !existsSync24(plugin.path))
21330
+ if (plugin.path === undefined || !existsSync23(plugin.path))
21232
21331
  return { changes: [], refusals: [] };
21233
21332
  return pinPluginMcpFiles(plugin.path, mcpCandidates3(), opts);
21234
21333
  },
@@ -21272,7 +21371,7 @@ function sameRoot(value, target) {
21272
21371
  }
21273
21372
  }
21274
21373
  function readRegistry2(path) {
21275
- if (!existsSync24(path))
21374
+ if (!existsSync23(path))
21276
21375
  return { version: 1, plugins: [] };
21277
21376
  let raw;
21278
21377
  try {
@@ -21292,18 +21391,18 @@ function restore(path, value) {
21292
21391
  }
21293
21392
  function restoreRegistryRow(registryFile, id, reference) {
21294
21393
  const rowFile = join30(reference, "registry.row.json");
21295
- const priorRow = existsSync24(rowFile) ? parseJson(rowFile, "Kimi registry row") : undefined;
21394
+ const priorRow = existsSync23(rowFile) ? parseJson(rowFile, "Kimi registry row") : undefined;
21296
21395
  if (priorRow !== undefined && priorRow.id !== id)
21297
21396
  throw new Error(`Kimi rollback row is not ${id}`);
21298
- const live = existsSync24(registryFile) ? readRegistry2(registryFile) : { version: 1, plugins: [] };
21397
+ const live = existsSync23(registryFile) ? readRegistry2(registryFile) : { version: 1, plugins: [] };
21299
21398
  const plugins = live.plugins.filter((row) => row.id !== id);
21300
21399
  if (priorRow !== undefined)
21301
21400
  plugins.push(priorRow);
21302
- if (plugins.length === 0 && existsSync24(join30(reference, "registry.absent"))) {
21401
+ if (plugins.length === 0 && existsSync23(join30(reference, "registry.absent"))) {
21303
21402
  rmSync8(registryFile, { force: true });
21304
21403
  return;
21305
21404
  }
21306
- if (!existsSync24(registryFile) && plugins.length === 0)
21405
+ if (!existsSync23(registryFile) && plugins.length === 0)
21307
21406
  return;
21308
21407
  writeFileSync8(registryFile, JSON.stringify({ version: 1, plugins }));
21309
21408
  }
@@ -21324,13 +21423,13 @@ function projectStagedKimi(stage, expectedName) {
21324
21423
  if (manifest[key] !== undefined)
21325
21424
  throw new Error(`Kimi root manifest ${key} is unsupported without an explicit native declaration`);
21326
21425
  const skills = join30(stage, "skills");
21327
- if (existsSync24(skills) && !statSync11(skills).isDirectory())
21426
+ if (existsSync23(skills) && !statSync11(skills).isDirectory())
21328
21427
  throw new Error(`Kimi skills path is not a directory: ${skills}`);
21329
- if (existsSync24(skills))
21428
+ if (existsSync23(skills))
21330
21429
  assertKimiSkillPolicies(skills);
21331
21430
  const native = join30(stage, "kimi.plugin.json");
21332
21431
  let supplied = {};
21333
- if (existsSync24(native)) {
21432
+ if (existsSync23(native)) {
21334
21433
  supplied = parseJson(native, "Kimi native manifest");
21335
21434
  if (supplied.name !== undefined && supplied.name !== expectedName)
21336
21435
  throw new Error(`Kimi native manifest name conflicts with ${expectedName}`);
@@ -21348,7 +21447,7 @@ function projectStagedKimi(stage, expectedName) {
21348
21447
  }
21349
21448
  const commands = prepareCommands(stage, typeof supplied.commands === "string" ? supplied.commands : undefined);
21350
21449
  const mcpServers = collectMcpServers(stage, manifest, supplied);
21351
- const nativeManifest = { name: expectedName, ...typeof manifest.version === "string" ? { version: manifest.version } : {}, ...typeof manifest.description === "string" ? { description: manifest.description } : {}, ...existsSync24(skills) ? { skills: "./skills/" } : {}, ...commands !== undefined ? { commands } : {}, ...mcpServers !== undefined ? { mcpServers } : {} };
21450
+ const nativeManifest = { name: expectedName, ...typeof manifest.version === "string" ? { version: manifest.version } : {}, ...typeof manifest.description === "string" ? { description: manifest.description } : {}, ...existsSync23(skills) ? { skills: "./skills/" } : {}, ...commands !== undefined ? { commands } : {}, ...mcpServers !== undefined ? { mcpServers } : {} };
21352
21451
  writeFileSync8(native, JSON.stringify(nativeManifest, null, 2));
21353
21452
  assertNoSymlinks4(stage);
21354
21453
  }
@@ -21371,12 +21470,12 @@ function collectMcpServers(stage, manifest, supplied) {
21371
21470
  };
21372
21471
  add("native manifest", supplied.mcpServers);
21373
21472
  const legacyNative = join30(stage, ".kimi-plugin", "plugin.json");
21374
- if (existsSync24(legacyNative))
21473
+ if (existsSync23(legacyNative))
21375
21474
  add(".kimi-plugin/plugin.json", parseJson(legacyNative, ".kimi-plugin/plugin.json").mcpServers);
21376
21475
  add("root plugin manifest", manifest.mcpServers);
21377
21476
  for (const file of [".mcp.json", "mcp.json"]) {
21378
21477
  const path = join30(stage, file);
21379
- if (!existsSync24(path))
21478
+ if (!existsSync23(path))
21380
21479
  continue;
21381
21480
  add(file, parseJson(path, file).mcpServers);
21382
21481
  }
@@ -21384,14 +21483,14 @@ function collectMcpServers(stage, manifest, supplied) {
21384
21483
  }
21385
21484
  function prepareCommands(stage, supplied) {
21386
21485
  const commands = join30(stage, "commands");
21387
- if (existsSync24(commands) && !statSync11(commands).isDirectory())
21486
+ if (existsSync23(commands) && !statSync11(commands).isDirectory())
21388
21487
  throw new Error(`Kimi commands path is not a directory: ${commands}`);
21389
21488
  const claude = join30(stage, ".claude", "commands");
21390
- const selected = supplied === undefined ? existsSync24(claude) ? "./.claude/commands/" : existsSync24(commands) ? "./commands/" : undefined : supplied.endsWith("/") ? supplied : `${supplied}/`;
21489
+ const selected = supplied === undefined ? existsSync23(claude) ? "./.claude/commands/" : existsSync23(commands) ? "./commands/" : undefined : supplied.endsWith("/") ? supplied : `${supplied}/`;
21391
21490
  if (selected === undefined)
21392
21491
  return;
21393
21492
  const dir = selected.startsWith("./.claude/") ? claude : commands;
21394
- if (!existsSync24(dir))
21493
+ if (!existsSync23(dir))
21395
21494
  throw new Error(`Kimi native commands pointer has no directory: ${selected}`);
21396
21495
  assertMarkdownCommandTree(dir);
21397
21496
  if (!containsMarkdown(dir))
@@ -21401,7 +21500,7 @@ function prepareCommands(stage, supplied) {
21401
21500
  function assertKimiSkillPolicies(dir) {
21402
21501
  for (const name of readdirSync15(dir)) {
21403
21502
  const path = join30(dir, name);
21404
- const stat = lstatSync15(path);
21503
+ const stat = lstatSync16(path);
21405
21504
  if (stat.isDirectory())
21406
21505
  assertKimiSkillPolicies(path);
21407
21506
  else if (stat.isFile() && name === "SKILL.md") {
@@ -21434,7 +21533,7 @@ function openingFrontmatter2(raw, path) {
21434
21533
  function assertMarkdownCommandTree(dir) {
21435
21534
  for (const name of readdirSync15(dir)) {
21436
21535
  const path = join30(dir, name);
21437
- const stat = lstatSync15(path);
21536
+ const stat = lstatSync16(path);
21438
21537
  if (stat.isSymbolicLink())
21439
21538
  throw new Error(`Kimi command source contains symlink: ${path}`);
21440
21539
  if (stat.isDirectory())
@@ -21465,7 +21564,7 @@ function containsMarkdown(dir) {
21465
21564
  });
21466
21565
  }
21467
21566
  function readSourceManifest(stage) {
21468
- const file = [join30(stage, "plugin.json"), join30(stage, ".plugin", "plugin.json")].find(existsSync24);
21567
+ const file = [join30(stage, "plugin.json"), join30(stage, ".plugin", "plugin.json")].find(existsSync23);
21469
21568
  if (file === undefined)
21470
21569
  throw new Error("Kimi stage has no Agent Plugins manifest");
21471
21570
  return parseJson(file, "Agent Plugins manifest");
@@ -21482,7 +21581,7 @@ function parseJson(path, label) {
21482
21581
  }
21483
21582
  function validateNativeIdentity(target, id) {
21484
21583
  const file = join30(target, "kimi.plugin.json");
21485
- if (!existsSync24(file) || parseJson(file, "Kimi native manifest").name !== id)
21584
+ if (!existsSync23(file) || parseJson(file, "Kimi native manifest").name !== id)
21486
21585
  throw new Error(`unowned Kimi managed plugin has no matching native manifest: ${target}`);
21487
21586
  }
21488
21587
  function readOwnership3(target) {
@@ -21514,7 +21613,7 @@ function rewriteOwnership(target, ownership) {
21514
21613
  }
21515
21614
  }
21516
21615
  function sameTree3(left, right) {
21517
- if (!existsSync24(right))
21616
+ if (!existsSync23(right))
21518
21617
  return false;
21519
21618
  const readBytes = readFileSync24;
21520
21619
  const list = (root) => {
@@ -21525,7 +21624,7 @@ function sameTree3(left, right) {
21525
21624
  continue;
21526
21625
  const path = join30(dir, name);
21527
21626
  const rel = prefix ? `${prefix}/${name}` : name;
21528
- const stat = lstatSync15(path);
21627
+ const stat = lstatSync16(path);
21529
21628
  if (stat.isSymbolicLink())
21530
21629
  throw new Error(`Kimi plugin contains symlink: ${path}`);
21531
21630
  if (stat.isDirectory())
@@ -21543,14 +21642,14 @@ function sameTree3(left, right) {
21543
21642
  }
21544
21643
  function assertNoSymlinks4(root) {
21545
21644
  const walk = (dir) => {
21546
- const stat = lstatSync15(dir);
21645
+ const stat = lstatSync16(dir);
21547
21646
  if (stat.isSymbolicLink())
21548
21647
  throw new Error(`Kimi plugin contains symlink: ${dir}`);
21549
21648
  if (!stat.isDirectory())
21550
21649
  throw new Error(`Kimi plugin path is not a directory: ${dir}`);
21551
21650
  for (const name of readdirSync15(dir)) {
21552
21651
  const path = join30(dir, name);
21553
- const child = lstatSync15(path);
21652
+ const child = lstatSync16(path);
21554
21653
  if (child.isSymbolicLink())
21555
21654
  throw new Error(`Kimi plugin contains symlink: ${path}`);
21556
21655
  if (child.isDirectory())
@@ -21562,7 +21661,7 @@ function assertNoSymlinks4(root) {
21562
21661
  walk(root);
21563
21662
  }
21564
21663
  function moveAside2(target, root) {
21565
- if (!existsSync24(target))
21664
+ if (!existsSync23(target))
21566
21665
  return { commit: () => {}, rollback: () => {} };
21567
21666
  mkdirSync8(root, { recursive: true });
21568
21667
  const dir = mkdtempSync7(join30(root, ".plgnz-kimi-backup-"));
@@ -21575,7 +21674,7 @@ function moveAside2(target, root) {
21575
21674
  }
21576
21675
  function lstatIfPresent(path) {
21577
21676
  try {
21578
- return lstatSync15(path);
21677
+ return lstatSync16(path);
21579
21678
  } catch (error) {
21580
21679
  if (error.code === "ENOENT")
21581
21680
  return;
@@ -21591,7 +21690,7 @@ function assertManagedPath3(root, target) {
21591
21690
  for (const part of selected.slice(base.length).split("/").filter(Boolean)) {
21592
21691
  if (lstatIfPresent(current) === undefined)
21593
21692
  break;
21594
- const stat = lstatSync15(current);
21693
+ const stat = lstatSync16(current);
21595
21694
  if (stat.isSymbolicLink())
21596
21695
  throw new Error(`Kimi managed path component is a symlink: ${current}`);
21597
21696
  if (!stat.isDirectory())
@@ -21632,7 +21731,7 @@ function currentKimiVersion(exitCode, version) {
21632
21731
  }
21633
21732
  function resolveKimiBinary() {
21634
21733
  const binary = kimiBinaryPath();
21635
- if (!existsSync24(binary))
21734
+ if (!existsSync23(binary))
21636
21735
  throw new Error(`current Kimi Code binary not found: ${binary}`);
21637
21736
  const probed = readKimiBinaryVersion(binary);
21638
21737
  if (currentKimiVersion(probed.exitCode, probed.version) === undefined)
@@ -21842,11 +21941,11 @@ var kimiLifecycle = {
21842
21941
  const managed = managedPluginPath(projection.packageName);
21843
21942
  const registryFile = join30(pluginsDir2(), "installed.json");
21844
21943
  assertKimiManaged(projection.packageName, managed, registryFile);
21845
- if (existsSync24(managed))
21944
+ if (existsSync23(managed))
21846
21945
  cpSync7(managed, join30(rollbackReference, "managed"), { recursive: true });
21847
- const priorRow = existsSync24(registryFile) ? readRegistry2(registryFile).plugins.find((row) => row.id === projection.packageName) : undefined;
21946
+ const priorRow = existsSync23(registryFile) ? readRegistry2(registryFile).plugins.find((row) => row.id === projection.packageName) : undefined;
21848
21947
  if (priorRow === undefined) {
21849
- if (!existsSync24(registryFile))
21948
+ if (!existsSync23(registryFile))
21850
21949
  writeFileSync8(join30(rollbackReference, "registry.absent"), "");
21851
21950
  } else
21852
21951
  writeFileSync8(join30(rollbackReference, "registry.row.json"), JSON.stringify(priorRow));
@@ -21874,10 +21973,10 @@ var kimiLifecycle = {
21874
21973
  const managed = managedPluginPath(id);
21875
21974
  const registryFile = join30(pluginsDir2(), "installed.json");
21876
21975
  assertKimiManaged(id, managed, registryFile);
21877
- const priorRow = existsSync24(registryFile) ? readRegistry2(registryFile).plugins.find((row) => row.id === id) : undefined;
21878
- const marker = existsSync24(managed) ? readOwnership3(managed) : null;
21976
+ const priorRow = existsSync23(registryFile) ? readRegistry2(registryFile).plugins.find((row) => row.id === id) : undefined;
21977
+ const marker = existsSync23(managed) ? readOwnership3(managed) : null;
21879
21978
  const legacyMarker = marker !== null && !marker.pluginId.includes("@") && prepared.handle.nativeId.startsWith(`${marker.pluginId}@`);
21880
- if (existsSync24(managed) && priorRow?.enabled === true && sameRoot(priorRow.root, managed) && sameTree3(prepared.stagingRoot, managed)) {
21979
+ if (existsSync23(managed) && priorRow?.enabled === true && sameRoot(priorRow.root, managed) && sameTree3(prepared.stagingRoot, managed)) {
21881
21980
  if (legacyMarker) {
21882
21981
  rewriteOwnership(managed, {
21883
21982
  ...marker,
@@ -21888,12 +21987,12 @@ var kimiLifecycle = {
21888
21987
  }
21889
21988
  return { receiptId: `kimi-apply:${prepared.handle.attemptId}:${prepared.handle.operationId}`, changed: false };
21890
21989
  }
21891
- const registryBefore = existsSync24(registryFile) ? readFileSync24(registryFile, "utf8") : undefined;
21990
+ const registryBefore = existsSync23(registryFile) ? readFileSync24(registryFile, "utf8") : undefined;
21892
21991
  const backup = moveAside2(managed, dirname10(managed));
21893
21992
  try {
21894
21993
  await nativeInstall(prepared.stagingRoot, kimiRootPath(), resolveKimiBinary());
21895
21994
  const row = readRegistry2(registryFile).plugins.find((candidate) => candidate.id === id);
21896
- if (row === undefined || row.enabled !== true || !sameRoot(row.root, managed) || !existsSync24(managed) || !sameTree3(prepared.stagingRoot, managed)) {
21995
+ if (row === undefined || row.enabled !== true || !sameRoot(row.root, managed) || !existsSync23(managed) || !sameTree3(prepared.stagingRoot, managed)) {
21897
21996
  throw new Error(`Kimi native install did not produce enabled managed plugin ${id}`);
21898
21997
  }
21899
21998
  backup.commit();
@@ -21916,7 +22015,7 @@ var kimiLifecycle = {
21916
22015
  const reference = handle.rollbackReference;
21917
22016
  rmSync8(managed, { recursive: true, force: true });
21918
22017
  const backup = join30(reference, "managed");
21919
- if (existsSync24(backup))
22018
+ if (existsSync23(backup))
21920
22019
  cpSync7(backup, managed, { recursive: true });
21921
22020
  restoreRegistryRow(registryFile, id, reference);
21922
22021
  return { receiptId: `kimi-rollback:${handle.attemptId}:${handle.operationId}`, changed: true };
@@ -21924,7 +22023,7 @@ var kimiLifecycle = {
21924
22023
  cleanup: async (reference) => {
21925
22024
  const root = join30(pluginsDir2(), ".plgnz-kimi-lifecycle");
21926
22025
  rmSync8(join30(root, safeSegment(reference.attemptId)), { recursive: true, force: true });
21927
- if (existsSync24(root) && readdirSync15(root).length === 0)
22026
+ if (existsSync23(root) && readdirSync15(root).length === 0)
21928
22027
  rmSync8(root, { recursive: true, force: true });
21929
22028
  return { cleanupId: `kimi-cleanup:${reference.attemptId}:${reference.operationId}`, completed: true };
21930
22029
  }
@@ -21948,8 +22047,8 @@ function assertKimiManaged(packageName, managed, registryFile) {
21948
22047
  function kimiReadback(handle) {
21949
22048
  const managed = managedPluginPath(handle.packageName);
21950
22049
  const registryFile = join30(pluginsDir2(), "installed.json");
21951
- const row = existsSync24(registryFile) ? readRegistry2(registryFile).plugins.find((candidate) => candidate.id === handle.packageName) : undefined;
21952
- const present = row !== undefined && existsSync24(managed) && sameRoot(row.root, managed);
22050
+ const row = existsSync23(registryFile) ? readRegistry2(registryFile).plugins.find((candidate) => candidate.id === handle.packageName) : undefined;
22051
+ const present = row !== undefined && existsSync23(managed) && sameRoot(row.root, managed);
21953
22052
  const enabled = present && row?.enabled === true;
21954
22053
  const digest = present ? fingerprintTree(managed) : null;
21955
22054
  return {
@@ -21970,7 +22069,7 @@ function kimiReadback(handle) {
21970
22069
  }
21971
22070
  function probeKimiBinary() {
21972
22071
  const binary = kimiBinaryPath();
21973
- if (!existsSync24(binary))
22072
+ if (!existsSync23(binary))
21974
22073
  return { kind: "unknown" };
21975
22074
  const probed = readKimiBinaryVersion(binary);
21976
22075
  const version = currentKimiVersion(probed.exitCode, probed.version);
@@ -22113,12 +22212,12 @@ function unexposed(phase) {
22113
22212
  }
22114
22213
 
22115
22214
  // src/hosts/cursor-writer.ts
22116
- import { accessSync as accessSync5, constants as constants5, cpSync as cpSync8, existsSync as existsSync25, lstatSync as lstatSync17, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync8, readFileSync as readFileSync26, readdirSync as readdirSync17, renameSync as renameSync6, rmSync as rmSync9, statSync as statSync12, writeFileSync as writeFileSync9 } from "node:fs";
22215
+ import { accessSync as accessSync5, constants as constants5, cpSync as cpSync8, existsSync as existsSync24, lstatSync as lstatSync18, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync8, readFileSync as readFileSync26, readdirSync as readdirSync17, renameSync as renameSync6, rmSync as rmSync9, statSync as statSync12, writeFileSync as writeFileSync9 } from "node:fs";
22117
22216
  import { delimiter as delimiter4, join as join32, resolve as resolve19 } from "node:path";
22118
22217
  import { tmpdir as tmpdir5 } from "node:os";
22119
22218
 
22120
22219
  // src/hosts/cursor-adoption.ts
22121
- import { accessSync as accessSync4, constants as constants4, lstatSync as lstatSync16, readFileSync as readFileSync25, readdirSync as readdirSync16 } from "node:fs";
22220
+ import { accessSync as accessSync4, constants as constants4, lstatSync as lstatSync17, readFileSync as readFileSync25, readdirSync as readdirSync16 } from "node:fs";
22122
22221
  import { dirname as dirname11, join as join31, resolve as resolve18 } from "node:path";
22123
22222
  var MARKER5 = ".plgnz-install.json";
22124
22223
  function proveCursorLegacyAdoption(request) {
@@ -22279,7 +22378,7 @@ function readTree(root) {
22279
22378
  const tree = new Map;
22280
22379
  const walk = (dir, prefix) => {
22281
22380
  for (const name of readdirSync16(dir).sort()) {
22282
- const path = join31(dir, name), relative = prefix === "" ? name : `${prefix}/${name}`, stat = lstatSync16(path);
22381
+ const path = join31(dir, name), relative = prefix === "" ? name : `${prefix}/${name}`, stat = lstatSync17(path);
22283
22382
  if (stat.isSymbolicLink())
22284
22383
  fail3(`symlink resource: ${relative}`);
22285
22384
  if (stat.isDirectory()) {
@@ -22297,7 +22396,7 @@ function readTree(root) {
22297
22396
  function safeAncestors(root, allowMissing) {
22298
22397
  for (let path = resolve18(root);; path = dirname11(path)) {
22299
22398
  if (!allowMissing || present(path)) {
22300
- const stat = lstatSync16(path);
22399
+ const stat = lstatSync17(path);
22301
22400
  if (stat.isSymbolicLink() || !stat.isDirectory())
22302
22401
  fail3(`unsafe directory: ${path}`);
22303
22402
  }
@@ -22349,7 +22448,7 @@ function parseManifest2(entry) {
22349
22448
  }
22350
22449
  function present(path) {
22351
22450
  try {
22352
- lstatSync16(path);
22451
+ lstatSync17(path);
22353
22452
  return true;
22354
22453
  } catch (error) {
22355
22454
  if (error.code === "ENOENT")
@@ -22410,8 +22509,8 @@ var cursorWriter = {
22410
22509
  if (marker !== null && (differentSource || !matchesOwnership(marker.pluginId, id, ownershipId))) {
22411
22510
  throw new Error(`Cursor local plugin ${id} belongs to another source; refusing to replace it`);
22412
22511
  }
22413
- const identicalUnowned = existsSync25(target) && marker === null && sameTree4(stage, target);
22414
- if (existsSync25(target) && marker === null && !identicalUnowned) {
22512
+ const identicalUnowned = existsSync24(target) && marker === null && sameTree4(stage, target);
22513
+ if (existsSync24(target) && marker === null && !identicalUnowned) {
22415
22514
  if (!opts?.adoptExisting)
22416
22515
  throw new Error(`Cursor local plugin ${id} is unowned and differs from the staged representation; pass --adopt-existing to take ownership explicitly`);
22417
22516
  validateExistingIdentity(target, id, sourceVersion(plugin.dir));
@@ -22430,7 +22529,7 @@ var cursorWriter = {
22430
22529
  }
22431
22530
  },
22432
22531
  async pin(plugin, opts) {
22433
- if (plugin.path === undefined || !existsSync25(plugin.path))
22532
+ if (plugin.path === undefined || !existsSync24(plugin.path))
22434
22533
  return { changes: [], refusals: [] };
22435
22534
  return pinPluginMcpFiles(plugin.path, mcpCandidates4(), opts);
22436
22535
  },
@@ -22464,7 +22563,7 @@ function projectCommandsToSkills(stage) {
22464
22563
  throw new Error(`Cursor command projection collision: ${command.name}`);
22465
22564
  seen.add(command.name);
22466
22565
  const target = join32(stage, "skills", command.name, "SKILL.md");
22467
- if (existsSync25(target))
22566
+ if (existsSync24(target))
22468
22567
  throw new Error(`Cursor command collides with an existing skill: ${command.name}`);
22469
22568
  mkdirSync9(join32(stage, "skills", command.name), { recursive: true });
22470
22569
  const body = command.body.endsWith(`
@@ -22482,13 +22581,13 @@ ${body}`);
22482
22581
  }
22483
22582
  }
22484
22583
  function hasCommands(root) {
22485
- return existsSync25(join32(root, "commands")) || existsSync25(join32(root, ".claude", "commands"));
22584
+ return existsSync24(join32(root, "commands")) || existsSync24(join32(root, ".claude", "commands"));
22486
22585
  }
22487
22586
  function ensureCursorManifest(stage, expectedName) {
22488
22587
  const cursorManifest = join32(stage, ".cursor-plugin", "plugin.json");
22489
- if (existsSync25(cursorManifest))
22588
+ if (existsSync24(cursorManifest))
22490
22589
  return;
22491
- const source = manifestCandidates(stage).find(existsSync25);
22590
+ const source = manifestCandidates(stage).find(existsSync24);
22492
22591
  if (source === undefined)
22493
22592
  throw new Error("Cursor stage has no Agent Plugins manifest");
22494
22593
  mkdirSync9(join32(stage, ".cursor-plugin"), { recursive: true });
@@ -22501,7 +22600,7 @@ function validateStage2(stage, expectedName) {
22501
22600
  const native = parseManifest3(join32(stage, ".cursor-plugin", "plugin.json"));
22502
22601
  if (native.name !== expectedName)
22503
22602
  throw new Error(`Cursor manifest identity does not match ${expectedName}`);
22504
- const canonicalPath = manifestCandidates(stage).find(existsSync25);
22603
+ const canonicalPath = manifestCandidates(stage).find(existsSync24);
22505
22604
  if (canonicalPath !== undefined) {
22506
22605
  const canonical = parseManifest3(canonicalPath);
22507
22606
  if (native.name !== canonical.name || canonical.version !== undefined && native.version !== canonical.version) {
@@ -22509,14 +22608,14 @@ function validateStage2(stage, expectedName) {
22509
22608
  }
22510
22609
  }
22511
22610
  const skills = join32(stage, "skills");
22512
- if (existsSync25(skills) && !statSync12(skills).isDirectory())
22611
+ if (existsSync24(skills) && !statSync12(skills).isDirectory())
22513
22612
  throw new Error("Cursor stage skills path is not a directory");
22514
22613
  }
22515
22614
  function manifestCandidates(root) {
22516
22615
  return [join32(root, ".claude-plugin", "plugin.json"), join32(root, "plugin.json"), join32(root, ".plugin", "plugin.json")];
22517
22616
  }
22518
22617
  function sourceVersion(root) {
22519
- const manifest = [join32(root, ".cursor-plugin", "plugin.json"), ...manifestCandidates(root)].find(existsSync25);
22618
+ const manifest = [join32(root, ".cursor-plugin", "plugin.json"), ...manifestCandidates(root)].find(existsSync24);
22520
22619
  return manifest === undefined ? undefined : parseManifest3(manifest).version;
22521
22620
  }
22522
22621
  function parseManifest3(path) {
@@ -22537,7 +22636,7 @@ function parseManifest3(path) {
22537
22636
  }
22538
22637
  function validateExistingIdentity(target, expectedName, expectedVersion) {
22539
22638
  const manifest = join32(target, ".cursor-plugin", "plugin.json");
22540
- if (!existsSync25(manifest))
22639
+ if (!existsSync24(manifest))
22541
22640
  throw new Error(`unowned Cursor local plugin has no native manifest: ${target}`);
22542
22641
  const parsed = parseManifest3(manifest);
22543
22642
  if (parsed.name !== expectedName || parsed.version !== expectedVersion)
@@ -22545,7 +22644,7 @@ function validateExistingIdentity(target, expectedName, expectedVersion) {
22545
22644
  }
22546
22645
  function readOwnership4(target) {
22547
22646
  const marker = join32(target, OWNERSHIP3);
22548
- if (!existsSync25(marker))
22647
+ if (!existsSync24(marker))
22549
22648
  return null;
22550
22649
  try {
22551
22650
  const value = JSON.parse(readFileSync26(marker, "utf8"));
@@ -22589,7 +22688,7 @@ function ownsNativeDirectory(markerId, nativeId) {
22589
22688
  return markerId.startsWith(prefix) && validIdentity2(markerId.slice(prefix.length));
22590
22689
  }
22591
22690
  function activate3(stage, target, root) {
22592
- if (!existsSync25(target)) {
22691
+ if (!existsSync24(target)) {
22593
22692
  renameSync6(stage, target);
22594
22693
  return { commit: () => {} };
22595
22694
  }
@@ -22606,7 +22705,7 @@ function activate3(stage, target, root) {
22606
22705
  return { commit: () => rmSync9(backupRoot, { recursive: true, force: true }) };
22607
22706
  }
22608
22707
  function sameTree4(left, right) {
22609
- if (!existsSync25(right))
22708
+ if (!existsSync24(right))
22610
22709
  return false;
22611
22710
  const entries = (root) => {
22612
22711
  const out = [];
@@ -22616,7 +22715,7 @@ function sameTree4(left, right) {
22616
22715
  continue;
22617
22716
  const path = join32(dir, name);
22618
22717
  const relative = prefix === "" ? name : `${prefix}/${name}`;
22619
- const stat = lstatSync17(path);
22718
+ const stat = lstatSync18(path);
22620
22719
  if (stat.isSymbolicLink())
22621
22720
  throw new Error(`Cursor managed plugin contains symlink: ${path}`);
22622
22721
  if (stat.isDirectory())
@@ -22643,15 +22742,15 @@ function assertManagedDirectory(root, target) {
22643
22742
  throw new Error(`Cursor managed path escapes its store: ${target}`);
22644
22743
  let current = resolvedRoot;
22645
22744
  for (const part of resolvedTarget.slice(resolvedRoot.length).split("/").filter(Boolean)) {
22646
- if (existsSync25(current))
22745
+ if (existsSync24(current))
22647
22746
  assertDirectoryNotLink(current);
22648
22747
  current = join32(current, part);
22649
22748
  }
22650
- if (existsSync25(current))
22749
+ if (existsSync24(current))
22651
22750
  assertDirectoryNotLink(current);
22652
22751
  }
22653
22752
  function assertDirectoryNotLink(path) {
22654
- const stat = lstatSync17(path);
22753
+ const stat = lstatSync18(path);
22655
22754
  if (stat.isSymbolicLink())
22656
22755
  throw new Error(`Cursor managed path component is a symlink: ${path}`);
22657
22756
  if (!stat.isDirectory())
@@ -22659,14 +22758,14 @@ function assertDirectoryNotLink(path) {
22659
22758
  }
22660
22759
  function assertNoSymlinks5(root) {
22661
22760
  const walk = (dir) => {
22662
- const stat = lstatSync17(dir);
22761
+ const stat = lstatSync18(dir);
22663
22762
  if (stat.isSymbolicLink())
22664
22763
  throw new Error(`Cursor plugin source contains symlink: ${dir}`);
22665
22764
  if (!stat.isDirectory())
22666
22765
  throw new Error(`Cursor plugin source is not a directory: ${dir}`);
22667
22766
  for (const name of readdirSync17(dir)) {
22668
22767
  const path = join32(dir, name);
22669
- const entry = lstatSync17(path);
22768
+ const entry = lstatSync18(path);
22670
22769
  if (entry.isSymbolicLink())
22671
22770
  throw new Error(`Cursor plugin source contains symlink: ${path}`);
22672
22771
  if (entry.isDirectory())
@@ -22866,7 +22965,7 @@ var cursorLifecycleDefinition = {
22866
22965
  const handle = prepared.handle;
22867
22966
  const target = managedPluginDir(handle.target.instance, handle.nativeId);
22868
22967
  refuseForeignScope(target, handle.scopeId, handle.nativeId);
22869
- if (existsSync25(target) && fingerprintTree(target) === fingerprintTree(prepared.stagingRoot)) {
22968
+ if (existsSync24(target) && fingerprintTree(target) === fingerprintTree(prepared.stagingRoot)) {
22870
22969
  return { receiptId: receipt("apply", handle), changed: false };
22871
22970
  }
22872
22971
  const root = localDir(handle.target.instance);
@@ -22887,7 +22986,7 @@ var cursorLifecycleDefinition = {
22887
22986
  async retire(prepared) {
22888
22987
  const handle = prepared.handle;
22889
22988
  const target = managedPluginDir(handle.target.instance, handle.nativeId);
22890
- if (!existsSync25(target))
22989
+ if (!existsSync24(target))
22891
22990
  return { receiptId: receipt("retire", handle), changed: false };
22892
22991
  refuseForeignScope(target, handle.scopeId, handle.nativeId);
22893
22992
  rmSync9(target, { recursive: true, force: true });
@@ -22909,15 +23008,15 @@ var cursorLifecycleDefinition = {
22909
23008
  const root = localDir(handle.target.instance);
22910
23009
  const target = managedPluginDir(handle.target.instance, handle.nativeId);
22911
23010
  const backup = join32(handle.rollbackReference, "active");
22912
- const restore = prior.presence === "present" && existsSync25(backup);
23011
+ const restore = prior.presence === "present" && existsSync24(backup);
22913
23012
  if (!restore) {
22914
- if (prior.presence === "present" || !existsSync25(target))
23013
+ if (prior.presence === "present" || !existsSync24(target))
22915
23014
  return { receiptId: receipt("rollback", handle), changed: false };
22916
23015
  refuseForeignScope(target, handle.scopeId, handle.nativeId);
22917
23016
  rmSync9(target, { recursive: true, force: true });
22918
23017
  return { receiptId: receipt("rollback", handle), changed: true };
22919
23018
  }
22920
- if (existsSync25(target)) {
23019
+ if (existsSync24(target)) {
22921
23020
  refuseForeignScope(target, handle.scopeId, handle.nativeId);
22922
23021
  if (fingerprintTree(target) === fingerprintTree(backup))
22923
23022
  return { receiptId: receipt("rollback", handle), changed: false };
@@ -22969,7 +23068,7 @@ function probeCursorVersion() {
22969
23068
  function locateCursorProbeBinary() {
22970
23069
  const override = process.env["OPEN_PLUGIN_CURSOR_BIN"];
22971
23070
  if (override !== undefined) {
22972
- if (override.length === 0 || !existsSync25(override))
23071
+ if (override.length === 0 || !existsSync24(override))
22973
23072
  return { kind: "refused" };
22974
23073
  return { kind: "path", path: override };
22975
23074
  }
@@ -23012,7 +23111,7 @@ function decodeStdout(bytes) {
23012
23111
  }
23013
23112
  function inventoryLocalStore(target) {
23014
23113
  const root = localDir(target.instance);
23015
- if (!existsSync25(root))
23114
+ if (!existsSync24(root))
23016
23115
  return { target, installations: [] };
23017
23116
  const installations = [];
23018
23117
  for (const entry of readdirSync17(root)) {
@@ -23033,7 +23132,7 @@ function inventoryLocalStore(target) {
23033
23132
  }
23034
23133
  function readLocalInstallation(entry, dir) {
23035
23134
  const manifestPath = join32(dir, ".cursor-plugin", "plugin.json");
23036
- if (!existsSync25(manifestPath))
23135
+ if (!existsSync24(manifestPath))
23037
23136
  return;
23038
23137
  let manifest;
23039
23138
  let marker = null;
@@ -23135,7 +23234,7 @@ function applyRecordedPins(stage, pins) {
23135
23234
  for (const pin of pins) {
23136
23235
  let found = false;
23137
23236
  for (const file of [join32(stage, ".mcp.json"), join32(stage, "mcp.json")]) {
23138
- if (!existsSync25(file))
23237
+ if (!existsSync24(file))
23139
23238
  continue;
23140
23239
  const parsed = JSON.parse(readFileSync26(file, "utf8"));
23141
23240
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
@@ -23164,7 +23263,7 @@ function projectReadback(identity) {
23164
23263
  inactiveMetadata: retainedResource(instance, identity.nativeId, "metadata")
23165
23264
  };
23166
23265
  const dir = join32(localDir(instance), identity.nativeId);
23167
- if (!existsSync25(dir)) {
23266
+ if (!existsSync24(dir)) {
23168
23267
  return {
23169
23268
  adapterId: identity.adapterId,
23170
23269
  target: identity.target,
@@ -23200,9 +23299,9 @@ function projectReadback(identity) {
23200
23299
  }
23201
23300
  function retainedResource(instance, nativeId, kind) {
23202
23301
  const dir = retentionDir(instance, nativeId, kind);
23203
- if (!existsSync25(dir))
23302
+ if (!existsSync24(dir))
23204
23303
  return { state: "absent", fingerprint: null };
23205
- const stat = lstatSync17(dir);
23304
+ const stat = lstatSync18(dir);
23206
23305
  if (stat.isSymbolicLink() || !stat.isDirectory())
23207
23306
  throw new Error(`Cursor retained ${kind} is not a directory: ${dir}`);
23208
23307
  return { state: "present", fingerprint: fingerprintTree(dir) };
@@ -23220,7 +23319,7 @@ function captureRollback2(instance, attemptId, operationId, nativeId, prior) {
23220
23319
  rmSync9(reference, { recursive: true, force: true });
23221
23320
  mkdirSync9(reference, { recursive: true });
23222
23321
  const active = join32(localDir(instance), nativeId);
23223
- if (existsSync25(active))
23322
+ if (existsSync24(active))
23224
23323
  cpSync8(active, join32(reference, "active"), { recursive: true });
23225
23324
  writeFileSync9(join32(reference, "prior.json"), `${JSON.stringify(prior)}
23226
23325
  `);
@@ -23253,7 +23352,7 @@ function absentRoute(action, route) {
23253
23352
  }
23254
23353
  }
23255
23354
  function refuseForeignScope(target, scopeId, nativeId) {
23256
- if (!existsSync25(target))
23355
+ if (!existsSync24(target))
23257
23356
  return;
23258
23357
  const marker = readOwnership4(target);
23259
23358
  if (marker === null || !ownsNativeDirectory(marker.pluginId, nativeId)) {
@@ -23282,7 +23381,7 @@ function receipt(kind, handle) {
23282
23381
 
23283
23382
  // src/hosts/omp-writer.ts
23284
23383
  init_omp_hooks();
23285
- import { cpSync as cpSync9, existsSync as existsSync26, lstatSync as lstatSync18, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync9, readFileSync as readFileSync27, readdirSync as readdirSync18, readlinkSync as readlinkSync2, renameSync as renameSync7, rmSync as rmSync10, symlinkSync, writeFileSync as writeFileSync10 } from "node:fs";
23384
+ import { cpSync as cpSync9, existsSync as existsSync25, lstatSync as lstatSync19, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync9, readFileSync as readFileSync27, readdirSync as readdirSync18, readlinkSync as readlinkSync2, renameSync as renameSync7, rmSync as rmSync10, symlinkSync, writeFileSync as writeFileSync10 } from "node:fs";
23286
23385
  import { dirname as dirname12, join as join33, resolve as resolve20 } from "node:path";
23287
23386
  import { tmpdir as tmpdir6 } from "node:os";
23288
23387
  var MARKER6 = ".plgnz-install.json";
@@ -23378,7 +23477,7 @@ var ompWriter = {
23378
23477
  }
23379
23478
  },
23380
23479
  async pin(plugin, opts) {
23381
- if (plugin.path === undefined || !existsSync26(plugin.path))
23480
+ if (plugin.path === undefined || !existsSync25(plugin.path))
23382
23481
  return { changes: [], refusals: [] };
23383
23482
  return pinPluginMcpFiles(plugin.path, mcpCandidates5(), opts);
23384
23483
  },
@@ -23472,7 +23571,7 @@ function registryInstallPaths(registry) {
23472
23571
  }
23473
23572
  function findOwned(id) {
23474
23573
  const root = join33(pluginsDir3(), MANAGED);
23475
- if (!existsSync26(root))
23574
+ if (!existsSync25(root))
23476
23575
  return null;
23477
23576
  for (const name of readdirSync18(root)) {
23478
23577
  const path = join33(root, name);
@@ -23490,7 +23589,7 @@ function assertOwnedLink(path, target, owned) {
23490
23589
  }
23491
23590
  function lstatExists(path) {
23492
23591
  try {
23493
- lstatSync18(path);
23592
+ lstatSync19(path);
23494
23593
  return true;
23495
23594
  } catch {
23496
23595
  return false;
@@ -23498,7 +23597,7 @@ function lstatExists(path) {
23498
23597
  }
23499
23598
  function linkPointsTo(path, target) {
23500
23599
  try {
23501
- return lstatSync18(path).isSymbolicLink() && resolve20(dirname12(path), readlinkSync2(path)) === resolve20(target);
23600
+ return lstatSync19(path).isSymbolicLink() && resolve20(dirname12(path), readlinkSync2(path)) === resolve20(target);
23502
23601
  } catch {
23503
23602
  return false;
23504
23603
  }
@@ -23538,7 +23637,7 @@ function mkdirSafe(path) {
23538
23637
  const parentBoundary = dirname12(boundary);
23539
23638
  for (let current = target;; current = dirname12(current)) {
23540
23639
  if (lstatExists(current)) {
23541
- const stat = lstatSync18(current);
23640
+ const stat = lstatSync19(current);
23542
23641
  if (stat.isSymbolicLink() || !stat.isDirectory())
23543
23642
  throw new Error(`OMP managed path is unsafe: ${current}`);
23544
23643
  }
@@ -23548,7 +23647,7 @@ function mkdirSafe(path) {
23548
23647
  mkdirSync10(path, { recursive: true });
23549
23648
  let current = target;
23550
23649
  while (true) {
23551
- const stat = lstatSync18(current);
23650
+ const stat = lstatSync19(current);
23552
23651
  if (stat.isSymbolicLink() || !stat.isDirectory())
23553
23652
  throw new Error(`OMP managed path is unsafe: ${current}`);
23554
23653
  if (current === boundary)
@@ -23564,7 +23663,7 @@ function assertExistingDirectoryTree(boundaryPath, targetPath, label) {
23564
23663
  for (let current = target;; current = dirname12(current)) {
23565
23664
  if (!lstatExists(current))
23566
23665
  throw new Error(`${label} has no safe native copy`);
23567
- const stat = lstatSync18(current);
23666
+ const stat = lstatSync19(current);
23568
23667
  if (stat.isSymbolicLink() || !stat.isDirectory())
23569
23668
  throw new Error(`${label} contains a symlink or non-directory component: ${current}`);
23570
23669
  if (current === boundary)
@@ -23572,7 +23671,7 @@ function assertExistingDirectoryTree(boundaryPath, targetPath, label) {
23572
23671
  }
23573
23672
  }
23574
23673
  function sameTree5(left, right) {
23575
- if (!existsSync26(right))
23674
+ if (!existsSync25(right))
23576
23675
  return false;
23577
23676
  const bytes = readFileSync27;
23578
23677
  const list = (root) => {
@@ -23583,7 +23682,7 @@ function sameTree5(left, right) {
23583
23682
  continue;
23584
23683
  const path = join33(dir, name);
23585
23684
  const rel = prefix ? `${prefix}/${name}` : name;
23586
- const stat = lstatSync18(path);
23685
+ const stat = lstatSync19(path);
23587
23686
  if (stat.isSymbolicLink())
23588
23687
  throw new Error(`OMP managed plugin contains symlink: ${path}`);
23589
23688
  if (stat.isDirectory())
@@ -23601,7 +23700,7 @@ function sameTree5(left, right) {
23601
23700
  }
23602
23701
  function ownership2(path) {
23603
23702
  const marker = join33(path, MARKER6);
23604
- if (!existsSync26(marker))
23703
+ if (!existsSync25(marker))
23605
23704
  return null;
23606
23705
  const value = readDoc(marker, {}, "ownership marker");
23607
23706
  if (typeof value.source !== "string" || typeof value.pluginId !== "string" || typeof value.fingerprint !== "string" || typeof value.packageName !== "string")
@@ -23620,7 +23719,7 @@ function ownership2(path) {
23620
23719
  };
23621
23720
  }
23622
23721
  function readDoc(path, fallback, label) {
23623
- if (!existsSync26(path))
23722
+ if (!existsSync25(path))
23624
23723
  return fallback;
23625
23724
  try {
23626
23725
  const value = JSON.parse(readFileSync27(path, "utf8"));
@@ -23650,7 +23749,7 @@ function writeDoc(path, value) {
23650
23749
  writeFileSync10(path, JSON.stringify(value, null, 2));
23651
23750
  }
23652
23751
  function snapshot(path) {
23653
- return existsSync26(path) ? readFileSync27(path, "utf8") : undefined;
23752
+ return existsSync25(path) ? readFileSync27(path, "utf8") : undefined;
23654
23753
  }
23655
23754
  function restore2(path, value) {
23656
23755
  if (value === undefined)
@@ -23872,7 +23971,7 @@ async function observeInventory(target) {
23872
23971
  return { target, installations: omp.listInstalled().map((plugin) => installationOf(plugin)) };
23873
23972
  }
23874
23973
  function installationOf(plugin) {
23875
- const path = plugin.path !== undefined && existsSync26(plugin.path) ? resolve20(plugin.path) : undefined;
23974
+ const path = plugin.path !== undefined && existsSync25(plugin.path) ? resolve20(plugin.path) : undefined;
23876
23975
  if (path === undefined) {
23877
23976
  return {
23878
23977
  nativeId: plugin.id,
@@ -23913,7 +24012,7 @@ function sourceOf2(owner) {
23913
24012
  }
23914
24013
  function observeReadback(identity) {
23915
24014
  const target = managedPackageDir(identity.nativeId);
23916
- const present = existsSync26(target) && linkPointsTo(managedLink(identity.nativeId), target);
24015
+ const present = existsSync25(target) && linkPointsTo(managedLink(identity.nativeId), target);
23917
24016
  const retention = retentionOf(identity.nativeId);
23918
24017
  if (!present) {
23919
24018
  return {
@@ -23957,17 +24056,17 @@ function retentionOf(nativeId) {
23957
24056
  };
23958
24057
  }
23959
24058
  function resourceObservation(path) {
23960
- if (!existsSync26(path))
24059
+ if (!existsSync25(path))
23961
24060
  return { state: "absent", fingerprint: null };
23962
24061
  return { state: "present", fingerprint: fingerprintTree(path) };
23963
24062
  }
23964
24063
  function lockMetadataObservation(nativeId) {
23965
- if (!existsSync26(lockPath()))
24064
+ if (!existsSync25(lockPath()))
23966
24065
  return { state: "absent", fingerprint: null };
23967
24066
  return { state: "present", fingerprint: sha256(canonical3(metadataView(readDoc(lockPath(), {}, "lockfile"), npmName(nativeId)))) };
23968
24067
  }
23969
24068
  function plannedLockMetadata(nativeId, version) {
23970
- const lock = existsSync26(lockPath()) ? readDoc(lockPath(), {}, "lockfile") : { plugins: {}, settings: {} };
24069
+ const lock = existsSync25(lockPath()) ? readDoc(lockPath(), {}, "lockfile") : { plugins: {}, settings: {} };
23971
24070
  const plugins = isDoc(lock.plugins) ? lock.plugins : {};
23972
24071
  const npm = npmName(nativeId);
23973
24072
  const next = { ...lock, plugins: { ...plugins, [npm]: activatedEntry(entry(plugins[npm]), version) } };
@@ -24005,7 +24104,7 @@ function captureRollback3(nativeId, attemptId, operationId) {
24005
24104
  mkdirSafe(preparationDir2(attemptId, operationId));
24006
24105
  mkdirSync10(reference, { recursive: true });
24007
24106
  const target = managedPackageDir(nativeId);
24008
- if (existsSync26(target))
24107
+ if (existsSync25(target))
24009
24108
  cpSync9(target, join33(reference, "package"), { recursive: true });
24010
24109
  writeFileSync10(join33(reference, "state.json"), JSON.stringify({ lock: captureLockRow(nativeId), link: currentLinkTarget(managedLink(nativeId)) }));
24011
24110
  return resolve20(reference);
@@ -24015,7 +24114,7 @@ function restoreRollback2(nativeId, reference) {
24015
24114
  const target = managedPackageDir(nativeId);
24016
24115
  rmSync10(target, { recursive: true, force: true });
24017
24116
  const backup = join33(reference, "package");
24018
- if (existsSync26(backup)) {
24117
+ if (existsSync25(backup)) {
24019
24118
  mkdirSafe(dirname12(target));
24020
24119
  cpSync9(backup, target, { recursive: true });
24021
24120
  }
@@ -24029,7 +24128,7 @@ function restoreRollback2(nativeId, reference) {
24029
24128
  }
24030
24129
  function captureLockRow(nativeId) {
24031
24130
  const packageName = npmName(nativeId);
24032
- if (!existsSync26(lockPath()))
24131
+ if (!existsSync25(lockPath()))
24033
24132
  return { packageName, present: false, row: null };
24034
24133
  const lock = readDoc(lockPath(), {}, "lockfile");
24035
24134
  const plugins = isDoc(lock.plugins) ? lock.plugins : {};
@@ -24039,7 +24138,7 @@ function captureLockRow(nativeId) {
24039
24138
  }
24040
24139
  function restoreLockRow(saved) {
24041
24140
  const file = lockPath();
24042
- if (!existsSync26(file)) {
24141
+ if (!existsSync25(file)) {
24043
24142
  if (!saved.present)
24044
24143
  return;
24045
24144
  writeDoc(file, { plugins: { [saved.packageName]: saved.row } });
@@ -24055,7 +24154,7 @@ function restoreLockRow(saved) {
24055
24154
  }
24056
24155
  function currentLinkTarget(path) {
24057
24156
  try {
24058
- return lstatSync18(path).isSymbolicLink() ? resolve20(dirname12(path), readlinkSync2(path)) : null;
24157
+ return lstatSync19(path).isSymbolicLink() ? resolve20(dirname12(path), readlinkSync2(path)) : null;
24059
24158
  } catch {
24060
24159
  return null;
24061
24160
  }
@@ -24097,7 +24196,7 @@ async function applyManaged(handle, stagingRoot) {
24097
24196
  }
24098
24197
  function activationAlreadyCurrent(nativeId, stage, version) {
24099
24198
  const target = managedPackageDir(nativeId);
24100
- if (!existsSync26(target) || !existsSync26(stage) || fingerprintTree(stage) !== fingerprintTree(target) || !linkPointsTo(managedLink(nativeId), target))
24199
+ if (!existsSync25(target) || !existsSync25(stage) || fingerprintTree(stage) !== fingerprintTree(target) || !linkPointsTo(managedLink(nativeId), target))
24101
24200
  return false;
24102
24201
  const lock = readDoc(lockPath(), { plugins: {}, settings: {} }, "lockfile");
24103
24202
  const plugins = object8(lock.plugins, "lockfile plugins");
@@ -24158,9 +24257,10 @@ function captureRecorded(activation, route, attemptId, operationId, affectedOper
24158
24257
  // src/native-hook-writer.ts
24159
24258
  init_hooks();
24160
24259
  init_hook_build();
24161
- import { chmodSync as chmodSync2, cpSync as cpSync10, existsSync as existsSync27, lstatSync as lstatSync19, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync10, renameSync as renameSync8, rmSync as rmSync11, writeFileSync as writeFileSync11 } from "node:fs";
24260
+ import { chmodSync as chmodSync2, cpSync as cpSync10, existsSync as existsSync26, lstatSync as lstatSync20, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync10, renameSync as renameSync8, rmSync as rmSync11, writeFileSync as writeFileSync11 } from "node:fs";
24162
24261
  import { dirname as dirname13, join as join34 } from "node:path";
24163
24262
  import { tmpdir as tmpdir7 } from "node:os";
24263
+ init_compatibility();
24164
24264
  function probeHookHostVersion(command, override) {
24165
24265
  const binary = process.env[override] ?? which(command);
24166
24266
  if (!binary)
@@ -24182,8 +24282,8 @@ function createNativeHookWriter(options) {
24182
24282
  if (reader.listInstalled().some((item) => item.id === id && item.path !== target)) {
24183
24283
  throw new Error("Native hook identity already belongs to a historical standalone install; remove that owned install before retrying: " + id);
24184
24284
  }
24185
- const owner = existsSync27(target) ? readHookOwner(target) : null;
24186
- if (existsSync27(target) && (owner === null || owner.pluginId !== id || owner.source !== source)) {
24285
+ const owner = existsSync26(target) ? readHookOwner(target) : null;
24286
+ if (existsSync26(target) && (owner === null || owner.pluginId !== id || owner.source !== source)) {
24187
24287
  throw new Error("Native hook package is not owned for this source: " + target);
24188
24288
  }
24189
24289
  const raw = registrationText(registration);
@@ -24207,7 +24307,7 @@ function createNativeHookWriter(options) {
24207
24307
  }, [profile]);
24208
24308
  if (admission.status === "refused")
24209
24309
  throw new PackageCapabilityError(store.id, admission);
24210
- if (existsSync27(join34(plugin.dir, NATIVE_HOOK_MARKER)))
24310
+ if (existsSync26(join34(plugin.dir, NATIVE_HOOK_MARKER)))
24211
24311
  throw new Error("Source contains reserved native hook ownership metadata");
24212
24312
  preflightPortableHooks(adapter, plugin.dir);
24213
24313
  checkTarget(idFor(plugin), resolved.sourceUri);
@@ -24232,7 +24332,7 @@ function createNativeHookWriter(options) {
24232
24332
  fingerprint: plugin.contentFingerprint ?? fingerprintTree(plugin.dir)
24233
24333
  }) + `
24234
24334
  `);
24235
- const unchanged = existsSync27(target) && fingerprintTree(target) === fingerprintTree(compiled) && registrationEnabled(registration);
24335
+ const unchanged = existsSync26(target) && fingerprintTree(target) === fingerprintTree(compiled) && registrationEnabled(registration);
24236
24336
  if (opts?.dryRun) {
24237
24337
  console.log("[" + store.id + "] would register native hooks: " + target);
24238
24338
  return unchanged ? "unchanged" : undefined;
@@ -24249,7 +24349,7 @@ function createNativeHookWriter(options) {
24249
24349
  const expectedFingerprint = fingerprintTree(stage);
24250
24350
  let activated = false, moved = false, committed = false;
24251
24351
  try {
24252
- if (existsSync27(target)) {
24352
+ if (existsSync26(target)) {
24253
24353
  renameSync8(target, backup);
24254
24354
  moved = true;
24255
24355
  }
@@ -24268,7 +24368,7 @@ function createNativeHookWriter(options) {
24268
24368
  renameSync8(backup, target);
24269
24369
  throw error;
24270
24370
  } finally {
24271
- if (committed || !existsSync27(backup))
24371
+ if (committed || !existsSync26(backup))
24272
24372
  rmSync11(transaction, { recursive: true, force: true });
24273
24373
  }
24274
24374
  } finally {
@@ -24278,7 +24378,7 @@ function createNativeHookWriter(options) {
24278
24378
  async remove(id, removeOptions) {
24279
24379
  const target = hookPackagePath(store, id);
24280
24380
  assertHookPath(store, target);
24281
- if (!existsSync27(target))
24381
+ if (!existsSync26(target))
24282
24382
  return options.legacyRemove(id, removeOptions);
24283
24383
  const owner = readHookOwner(target);
24284
24384
  if (owner === null || owner.pluginId !== id || removeOptions?.source !== undefined && owner.source !== removeOptions.source) {
@@ -24301,12 +24401,12 @@ function createNativeHookWriter(options) {
24301
24401
  committed = true;
24302
24402
  } catch (error) {
24303
24403
  restoreRegistration(registration, before, after);
24304
- if (!existsSync27(target))
24404
+ if (!existsSync26(target))
24305
24405
  renameSync8(backup, target);
24306
24406
  throw error;
24307
24407
  }
24308
24408
  } finally {
24309
- if (committed || !existsSync27(backup))
24409
+ if (committed || !existsSync26(backup))
24310
24410
  rmSync11(transaction, { recursive: true, force: true });
24311
24411
  }
24312
24412
  },
@@ -24320,11 +24420,10 @@ function nextRegistration(registration, raw, enabled) {
24320
24420
  return enabled ? registration.content : undefined;
24321
24421
  const value = registrationDocument(registration, raw);
24322
24422
  const previous = value[registration.field] ?? [];
24323
- const entries = previous.filter((entry) => entry !== registration.entry);
24324
- if (enabled)
24325
- entries.push(registration.entry);
24326
- if (entries.length === 0 && !Object.hasOwn(value, registration.field) && !enabled)
24423
+ const present = previous.includes(registration.entry);
24424
+ if (enabled === present)
24327
24425
  return raw;
24426
+ const entries = enabled ? [...previous, registration.entry] : previous.filter((entry) => entry !== registration.entry);
24328
24427
  value[registration.field] = entries;
24329
24428
  return JSON.stringify(value, null, 2) + `
24330
24429
  `;
@@ -24349,7 +24448,7 @@ function writeExactFile(path, text) {
24349
24448
  rmSync11(path, { force: true });
24350
24449
  return;
24351
24450
  }
24352
- const mode = existsSync27(path) ? lstatSync19(path).mode & 511 : 420;
24451
+ const mode = existsSync26(path) ? lstatSync20(path).mode & 511 : 420;
24353
24452
  mkdirSync11(dirname13(path), { recursive: true });
24354
24453
  const temporary = mkdtempSync10(join34(dirname13(path), ".plugnz-hook-write-"));
24355
24454
  try {
@@ -24363,7 +24462,7 @@ function writeExactFile(path, text) {
24363
24462
  }
24364
24463
 
24365
24464
  // src/hosts/pi-writer.ts
24366
- import { existsSync as existsSync28, lstatSync as lstatSync20, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync11, readFileSync as readFileSync29, readdirSync as readdirSync19, renameSync as renameSync9, rmSync as rmSync12, writeFileSync as writeFileSync12 } from "node:fs";
24465
+ import { existsSync as existsSync27, lstatSync as lstatSync21, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync11, readFileSync as readFileSync29, readdirSync as readdirSync19, renameSync as renameSync9, rmSync as rmSync12, writeFileSync as writeFileSync12 } from "node:fs";
24367
24466
  import { basename as basename4, dirname as dirname14, join as join35, resolve as resolve21 } from "node:path";
24368
24467
  import { tmpdir as tmpdir8 } from "node:os";
24369
24468
  var MARKER7 = ".plgnz-install.json";
@@ -24397,7 +24496,7 @@ var piWriter = {
24397
24496
  const backups = [];
24398
24497
  try {
24399
24498
  for (const candidate of [...new Set([target, ...prior])]) {
24400
- if (!existsSync28(candidate)) {
24499
+ if (!existsSync27(candidate)) {
24401
24500
  backups.push({ target: candidate });
24402
24501
  continue;
24403
24502
  }
@@ -24454,7 +24553,7 @@ var piWriter = {
24454
24553
  function stagePlugin4(source, stage, plugin, market) {
24455
24554
  assertTree(source);
24456
24555
  const root = join35(source, "skills");
24457
- if (!existsSync28(root) || !lstatSync20(root).isDirectory())
24556
+ if (!existsSync27(root) || !lstatSync21(root).isDirectory())
24458
24557
  throw new Error("Pi standalone delivery requires plugin skills/ directories");
24459
24558
  const destination = join35(stage, packageName(plugin, market));
24460
24559
  projectPluginForPi(source, destination, plugin);
@@ -24462,7 +24561,7 @@ function stagePlugin4(source, stage, plugin, market) {
24462
24561
  const walk = (dir) => {
24463
24562
  for (const entry of readdirSync19(dir)) {
24464
24563
  const path = join35(dir, entry);
24465
- const stat = lstatSync20(path);
24564
+ const stat = lstatSync21(path);
24466
24565
  if (stat.isDirectory())
24467
24566
  walk(path);
24468
24567
  else if (entry === "SKILL.md")
@@ -24506,7 +24605,7 @@ function packageName(plugin, market) {
24506
24605
  }
24507
24606
  function owner2(dir) {
24508
24607
  const file = join35(dir, MARKER7);
24509
- if (!existsSync28(file))
24608
+ if (!existsSync27(file))
24510
24609
  return null;
24511
24610
  try {
24512
24611
  const x = JSON.parse(readFileSync29(file, "utf8"));
@@ -24522,12 +24621,12 @@ function owner2(dir) {
24522
24621
  }
24523
24622
  function ownedFor(id, source) {
24524
24623
  assertPiStore();
24525
- if (!existsSync28(skillsDir()))
24624
+ if (!existsSync27(skillsDir()))
24526
24625
  return [];
24527
24626
  const out = [];
24528
24627
  for (const name of readdirSync19(skillsDir())) {
24529
24628
  const path = join35(skillsDir(), name);
24530
- if (!lstatSync20(path).isDirectory())
24629
+ if (!lstatSync21(path).isDirectory())
24531
24630
  continue;
24532
24631
  const mark = owner2(path);
24533
24632
  if (mark?.pluginId === id && (source === undefined || mark.source === source))
@@ -24537,7 +24636,7 @@ function ownedFor(id, source) {
24537
24636
  }
24538
24637
  function checkTarget(target, id, source) {
24539
24638
  assertUnder(skillsDir(), target);
24540
- if (!existsSync28(target))
24639
+ if (!existsSync27(target))
24541
24640
  return;
24542
24641
  const mark = owner2(target);
24543
24642
  if (mark === null)
@@ -24546,7 +24645,7 @@ function checkTarget(target, id, source) {
24546
24645
  throw new Error(`Pi standalone skill belongs to another source; refusing to replace it: ${target}`);
24547
24646
  }
24548
24647
  function sameTree6(stage, target) {
24549
- if (!existsSync28(target))
24648
+ if (!existsSync27(target))
24550
24649
  return false;
24551
24650
  const bytes = readFileSync29;
24552
24651
  const list = (root) => {
@@ -24555,7 +24654,7 @@ function sameTree6(stage, target) {
24555
24654
  for (const name of readdirSync19(dir).sort()) {
24556
24655
  if (name === MARKER7)
24557
24656
  continue;
24558
- const path = join35(dir, name), relative = prefix ? `${prefix}/${name}` : name, stat = lstatSync20(path);
24657
+ const path = join35(dir, name), relative = prefix ? `${prefix}/${name}` : name, stat = lstatSync21(path);
24559
24658
  if (stat.isDirectory())
24560
24659
  walk(path, relative);
24561
24660
  else if (stat.isFile())
@@ -24570,11 +24669,11 @@ function sameTree6(stage, target) {
24570
24669
  return JSON.stringify(list(stage)) === JSON.stringify(list(target));
24571
24670
  }
24572
24671
  function assertTree(root) {
24573
- const stat = lstatSync20(root);
24672
+ const stat = lstatSync21(root);
24574
24673
  if (stat.isSymbolicLink() || !stat.isDirectory())
24575
24674
  throw new Error(`Pi plugin root is not a real directory: ${root}`);
24576
24675
  for (const name of readdirSync19(root)) {
24577
- const path = join35(root, name), child = lstatSync20(path);
24676
+ const path = join35(root, name), child = lstatSync21(path);
24578
24677
  if (child.isSymbolicLink())
24579
24678
  throw new Error(`Pi plugin contains symlink: ${path}`);
24580
24679
  if (child.isDirectory())
@@ -24604,18 +24703,18 @@ function assertPiStore() {
24604
24703
  let current = home;
24605
24704
  for (const part of [basename4(dirname14(root)), basename4(root)]) {
24606
24705
  current = join35(current, part);
24607
- if (existsSync28(current) && lstatSync20(current).isSymbolicLink())
24706
+ if (existsSync27(current) && lstatSync21(current).isSymbolicLink())
24608
24707
  throw new Error(`Pi managed path component is a symlink: ${current}`);
24609
24708
  }
24610
- if (existsSync28(root))
24709
+ if (existsSync27(root))
24611
24710
  assertRealDirectory(root);
24612
- if (existsSync28(skillsDir())) {
24711
+ if (existsSync27(skillsDir())) {
24613
24712
  assertUnder(root, skillsDir());
24614
24713
  assertRealDirectory(skillsDir());
24615
24714
  }
24616
24715
  }
24617
24716
  function assertRealDirectory(path) {
24618
- const stat = lstatSync20(path);
24717
+ const stat = lstatSync21(path);
24619
24718
  if (stat.isSymbolicLink())
24620
24719
  throw new Error(`Pi managed path component is a symlink: ${path}`);
24621
24720
  if (!stat.isDirectory())
@@ -24628,7 +24727,7 @@ function assertUnder(root, path) {
24628
24727
  let current = base;
24629
24728
  for (const part of candidate.slice(base.length).split("/").filter(Boolean)) {
24630
24729
  current = join35(current, part);
24631
- if (existsSync28(current) && lstatSync20(current).isSymbolicLink())
24730
+ if (existsSync27(current) && lstatSync21(current).isSymbolicLink())
24632
24731
  throw new Error(`Pi managed path component is a symlink: ${current}`);
24633
24732
  }
24634
24733
  }
@@ -24644,7 +24743,7 @@ var piHookWriter = createNativeHookWriter({
24644
24743
  });
24645
24744
 
24646
24745
  // src/hosts/dcode-writer.ts
24647
- import { cpSync as cpSync11, existsSync as existsSync29, lstatSync as lstatSync21, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync12, readFileSync as readFileSync30, readdirSync as readdirSync20, realpathSync as realpathSync5, renameSync as renameSync10, rmSync as rmSync13, writeFileSync as writeFileSync13 } from "node:fs";
24746
+ import { cpSync as cpSync11, existsSync as existsSync28, lstatSync as lstatSync22, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync12, readFileSync as readFileSync30, readdirSync as readdirSync20, realpathSync as realpathSync5, renameSync as renameSync10, rmSync as rmSync13, writeFileSync as writeFileSync13 } from "node:fs";
24648
24747
  import { basename as basename5, dirname as dirname15, join as join36, resolve as resolve22 } from "node:path";
24649
24748
  import { tmpdir as tmpdir9 } from "node:os";
24650
24749
  import { spawn as spawnChild } from "node:child_process";
@@ -24673,7 +24772,7 @@ function nativePython() {
24673
24772
  throw new Error("dcode native lock runtime is unavailable");
24674
24773
  const shebang = readFileSync30(binary, "utf8").split(/\r?\n/, 1)[0] ?? "";
24675
24774
  const match = /^#!(\/[^\s]+python(?:\d+(?:\.\d+)?)?)$/u.exec(shebang);
24676
- if (match?.[1] === undefined || !existsSync29(match[1]))
24775
+ if (match?.[1] === undefined || !existsSync28(match[1]))
24677
24776
  throw new Error("dcode native Python interpreter is unverified; set OPEN_PLUGIN_DCODE_PYTHON_BIN to its verified interpreter");
24678
24777
  return match[1];
24679
24778
  }
@@ -24774,7 +24873,7 @@ function observeDcodeTarget(target) {
24774
24873
  throw new Error(`dcode install record ${nativeId} has duplicate rows`);
24775
24874
  const path = rowInstall(rows[0], nativeId);
24776
24875
  assertCachePath(path);
24777
- const present = existsSync29(path);
24876
+ const present = existsSync28(path);
24778
24877
  const marker = present ? ownership3(path) : null;
24779
24878
  const body = present ? readDoc2(join36(path, MARKER8), {}, "ownership marker") : {};
24780
24879
  const owned = marker?.pluginId === nativeId;
@@ -24795,7 +24894,7 @@ function observeDcodeTarget(target) {
24795
24894
  });
24796
24895
  }
24797
24896
  function dcodeLifecycleReadback(binding) {
24798
- if (existsSync29(join36(dcodeStateDir(), READBACK_FAULT)))
24897
+ if (existsSync28(join36(dcodeStateDir(), READBACK_FAULT)))
24799
24898
  throw new Error(`dcode readback failed for ${binding.nativeId}`);
24800
24899
  const installations = observeDcodeTarget(binding.target);
24801
24900
  const row = installations.find((item) => item.nativeId === binding.nativeId);
@@ -24816,7 +24915,7 @@ function dcodeLifecycleReadback(binding) {
24816
24915
  transition: { requirement: present ? "restart" : "none", status: "effective" },
24817
24916
  installedFingerprint: present ? row.installedFingerprint : null,
24818
24917
  contentRoots: present ? row.contentRoots : [],
24819
- retention: { pluginData: existsSync29(dataRoot) ? { state: "present", fingerprint: fingerprintTree(dataRoot) } : { state: "absent", fingerprint: null }, inactiveMetadata: { state: "absent", fingerprint: null } }
24918
+ retention: { pluginData: existsSync28(dataRoot) ? { state: "present", fingerprint: fingerprintTree(dataRoot) } : { state: "absent", fingerprint: null }, inactiveMetadata: { state: "absent", fingerprint: null } }
24820
24919
  };
24821
24920
  }
24822
24921
  function captureDcodeRollback(binding, attemptId, operationId) {
@@ -24825,13 +24924,13 @@ function captureDcodeRollback(binding, attemptId, operationId) {
24825
24924
  const registry = readRegistry3(dcodeRegistryFile());
24826
24925
  const enabled = boolObject(readEnablement(dcodeEnablementFile()).enabledPlugins, "enabledPlugins");
24827
24926
  const row = object9(registry.plugins, "registry plugins")[binding.nativeId];
24828
- const state = { row: row ?? null, enabled: enabled[binding.nativeId] ?? null, registryExisted: existsSync29(dcodeRegistryFile()), enablementExisted: existsSync29(dcodeEnablementFile()) };
24927
+ const state = { row: row ?? null, enabled: enabled[binding.nativeId] ?? null, registryExisted: existsSync28(dcodeRegistryFile()), enablementExisted: existsSync28(dcodeEnablementFile()) };
24829
24928
  writeFileSync13(join36(dir, "state.json"), JSON.stringify(state));
24830
24929
  for (const [index, item] of rowsFor(row).entries()) {
24831
24930
  const path = rowInstall(item, binding.nativeId);
24832
24931
  assertCachePath(path);
24833
24932
  assertNoSymlinks6(path);
24834
- if (existsSync29(path))
24933
+ if (existsSync28(path))
24835
24934
  cpSync11(path, join36(dir, `content-${index}`), { recursive: true });
24836
24935
  }
24837
24936
  return dir;
@@ -24917,7 +25016,7 @@ var dcodeDefinition = {
24917
25016
  stageActivation: async (request) => {
24918
25017
  const dir = lifecycleDirectory(request.snapshot.attemptId, request.snapshot.operationId);
24919
25018
  const stagingRoot = join36(dir, "stage");
24920
- if (existsSync29(stagingRoot))
25019
+ if (existsSync28(stagingRoot))
24921
25020
  throw new Error("dcode preparation stage already exists");
24922
25021
  mkdirSync13(stagingRoot, { recursive: true });
24923
25022
  const manifest = declaredManifest(request.snapshot.packageRoot, request.snapshot.packageName);
@@ -24939,7 +25038,7 @@ var dcodeDefinition = {
24939
25038
  const found = new Set;
24940
25039
  for (const candidate of dcodeMcpCandidates()) {
24941
25040
  const file = join36(projection.stagingRoot, candidate.kind === "spec" ? candidate.file : candidate.manifest);
24942
- if (!existsSync29(file))
25041
+ if (!existsSync28(file))
24943
25042
  continue;
24944
25043
  const body = readDoc2(file, {}, "MCP document");
24945
25044
  if (typeof body.mcpServers !== "object" || body.mcpServers === null || Array.isArray(body.mcpServers))
@@ -24979,7 +25078,7 @@ var dcodeDefinition = {
24979
25078
  if (manifest.version !== projection.packageVersion)
24980
25079
  throw new Error("dcode legacy version differs; refusing adoption");
24981
25080
  }
24982
- if (existsSync29(target) && ownership3(target)?.pluginId !== projection.nativeId)
25081
+ if (existsSync28(target) && ownership3(target)?.pluginId !== projection.nativeId)
24983
25082
  throw new Error("dcode lifecycle target is not owned");
24984
25083
  const rollbackReference = captureDcodeRollback(projection, projection.attemptId, projection.operationId);
24985
25084
  writeFileSync13(join36(rollbackReference, "next-path.json"), JSON.stringify({ target }));
@@ -24998,7 +25097,7 @@ var dcodeDefinition = {
24998
25097
  const target = lifecycleSlot(prepared.handle.nativeId, prepared.handle.projectedFingerprint);
24999
25098
  assertCachePath(target);
25000
25099
  mkdirSync13(dirname15(target), { recursive: true });
25001
- if (existsSync29(target)) {
25100
+ if (existsSync28(target)) {
25002
25101
  const marker = ownership3(target);
25003
25102
  if (marker?.pluginId !== prepared.handle.nativeId)
25004
25103
  throw new Error("dcode lifecycle activation would overwrite foreign content");
@@ -25038,22 +25137,22 @@ var dcodeDefinition = {
25038
25137
  },
25039
25138
  rollback: async (handle) => {
25040
25139
  await acquireNativeLock(handle.attemptId, handle.operationId);
25041
- if (!existsSync29(join36(handle.rollbackReference, "state.json")))
25140
+ if (!existsSync28(join36(handle.rollbackReference, "state.json")))
25042
25141
  throw new Error("dcode rollback snapshot is missing; recovery refused");
25043
25142
  const state = readDoc2(join36(handle.rollbackReference, "state.json"), {}, "rollback state");
25044
25143
  if (recoveringNativeLocks.has(`${handle.attemptId}:${handle.operationId}`))
25045
25144
  assertRecoveryRollbackMetadata(handle, state);
25046
25145
  for (const [index, root] of handle.prior.contentRoots.entries()) {
25047
25146
  const backup = join36(handle.rollbackReference, `content-${index}`);
25048
- if (!existsSync29(backup) || fingerprintTree(backup) !== root.fingerprint)
25147
+ if (!existsSync28(backup) || fingerprintTree(backup) !== root.fingerprint)
25049
25148
  throw new Error("dcode rollback snapshot bytes do not match the sealed prior");
25050
- if (recoveringNativeLocks.has(`${handle.attemptId}:${handle.operationId}`) && existsSync29(root.path) && fingerprintTree(root.path) !== root.fingerprint)
25149
+ if (recoveringNativeLocks.has(`${handle.attemptId}:${handle.operationId}`) && existsSync28(root.path) && fingerprintTree(root.path) !== root.fingerprint)
25051
25150
  throw new Error("dcode prior root changed outside the sealed operation; refusing stale overwrite");
25052
25151
  }
25053
25152
  const target = handle.projectedFingerprint === null ? undefined : lifecycleSlot(handle.nativeId, handle.projectedFingerprint);
25054
25153
  if (target !== undefined)
25055
25154
  assertCachePath(target);
25056
- if (target !== undefined && existsSync29(target) && !handle.prior.contentRoots.some((root) => resolve22(root.path) === resolve22(target))) {
25155
+ if (target !== undefined && existsSync28(target) && !handle.prior.contentRoots.some((root) => resolve22(root.path) === resolve22(target))) {
25057
25156
  if (ownership3(target)?.pluginId !== handle.nativeId || recoveringNativeLocks.has(`${handle.attemptId}:${handle.operationId}`) && fingerprintTree(target) !== handle.projectedFingerprint)
25058
25157
  throw new Error("dcode rollback candidate differs from the sealed operation; refusing stale overwrite");
25059
25158
  rmSync13(target, { recursive: true });
@@ -25062,7 +25161,7 @@ var dcodeDefinition = {
25062
25161
  const path = rowInstall(row, handle.nativeId);
25063
25162
  assertCachePath(path);
25064
25163
  const backup = join36(handle.rollbackReference, `content-${index}`);
25065
- if (existsSync29(backup)) {
25164
+ if (existsSync28(backup)) {
25066
25165
  mkdirSync13(dirname15(path), { recursive: true });
25067
25166
  cpSync11(backup, path, { recursive: true });
25068
25167
  }
@@ -25096,14 +25195,14 @@ var dcodeDefinition = {
25096
25195
  const next = readDoc2(nextFile, {}, "cleanup target");
25097
25196
  if (disposition === "verified-commit" && recovering !== undefined) {
25098
25197
  const retiredRoots = recovering.prior.contentRoots.filter((root) => !recovering.expected.contentRoots.some((next) => resolve22(next.path) === resolve22(root.path)));
25099
- if (existsSync29(priorFile))
25198
+ if (existsSync28(priorFile))
25100
25199
  assertRecoveryRollbackMetadata(recovering, readDoc2(priorFile, {}, "rollback state"));
25101
- else if (retiredRoots.some((root) => existsSync29(root.path)))
25200
+ else if (retiredRoots.some((root) => existsSync28(root.path)))
25102
25201
  throw new Error("dcode cleanup prior metadata is missing; recovery refused");
25103
- if (existsSync29(nextFile) && (typeof next.target !== "string" || !recovering.expected.contentRoots.some((root) => resolve22(root.path) === resolve22(next.target))))
25202
+ if (existsSync28(nextFile) && (typeof next.target !== "string" || !recovering.expected.contentRoots.some((root) => resolve22(root.path) === resolve22(next.target))))
25104
25203
  throw new Error("dcode cleanup target differs from the sealed expected root; recovery refused");
25105
25204
  for (const root of retiredRoots) {
25106
- if (existsSync29(root.path) && fingerprintTree(root.path) !== root.fingerprint)
25205
+ if (existsSync28(root.path) && fingerprintTree(root.path) !== root.fingerprint)
25107
25206
  throw new Error("dcode cleanup prior root changed; refusing stale deletion");
25108
25207
  }
25109
25208
  for (const root of retiredRoots)
@@ -25185,7 +25284,7 @@ var dcodeWriter = {
25185
25284
  const slot = ownership3(target);
25186
25285
  if (slot !== null && (slot.source !== resolved.sourceUri || slot.pluginId !== id))
25187
25286
  throw new Error(`dcode plugin ${id} belongs to another source; refusing to replace it`);
25188
- if (existsSync29(target) && slot === null)
25287
+ if (existsSync28(target) && slot === null)
25189
25288
  throw new Error(`dcode cache target is unowned; refusing to replace it: ${target}`);
25190
25289
  const former = prior.kind === "none" ? undefined : prior.path;
25191
25290
  const unchanged = (former === undefined || resolve22(former) === resolve22(target)) && slot?.kind === "current" && slot.fingerprint === sourceFingerprint && slot.projectedFingerprint === projected && slot.sourceRevision === resolved.sha && sameTree7(stage, target);
@@ -25229,13 +25328,13 @@ var dcodeWriter = {
25229
25328
  }
25230
25329
  } finally {
25231
25330
  rmSync13(stage, { recursive: true, force: true });
25232
- if (opts?.dryRun !== true && existsSync29(managedRoot) && readdirSync20(managedRoot).every((name) => name.startsWith(".plgnz-dcode-"))) {
25331
+ if (opts?.dryRun !== true && existsSync28(managedRoot) && readdirSync20(managedRoot).every((name) => name.startsWith(".plgnz-dcode-"))) {
25233
25332
  rmSync13(managedRoot, { recursive: true, force: true });
25234
25333
  }
25235
25334
  }
25236
25335
  },
25237
25336
  async pin(plugin, opts) {
25238
- if (plugin.path === undefined || !existsSync29(plugin.path))
25337
+ if (plugin.path === undefined || !existsSync28(plugin.path))
25239
25338
  return { changes: [], refusals: [] };
25240
25339
  assertCachePath(plugin.path);
25241
25340
  if (ownership3(plugin.path)?.pluginId !== plugin.id)
@@ -25319,7 +25418,7 @@ function assessPrior(value, id, source, adopt, name, version, sourceDir) {
25319
25418
  throw new Error(`dcode plugin ${id} has a conflicting ownership marker`);
25320
25419
  if (!adopt)
25321
25420
  throw new Error(`dcode install record ${id} is not plgnz-owned; refusing to replace it`);
25322
- if (!existsSync29(install) || lstatSync21(install).isSymbolicLink() || !lstatSync21(install).isDirectory()) {
25421
+ if (!existsSync28(install) || lstatSync22(install).isSymbolicLink() || !lstatSync22(install).isDirectory()) {
25323
25422
  throw new Error(`dcode install record ${id} is not plgnz-owned; refusing to replace it`);
25324
25423
  }
25325
25424
  assertNoSymlinks6(install);
@@ -25342,7 +25441,7 @@ function assessPrior(value, id, source, adopt, name, version, sourceDir) {
25342
25441
  return { kind: "adoptable", path: install };
25343
25442
  }
25344
25443
  function declaredManifest(dir, expectedName) {
25345
- const manifest = MANIFESTS.map((relative) => join36(dir, relative)).find((file) => existsSync29(file));
25444
+ const manifest = MANIFESTS.map((relative) => join36(dir, relative)).find((file) => existsSync28(file));
25346
25445
  if (manifest === undefined)
25347
25446
  throw new Error("dcode stage has no supported plugin manifest");
25348
25447
  let parsed;
@@ -25367,7 +25466,7 @@ function stagePlugin5(source, stage, name, version) {
25367
25466
  throw new Error(`dcode manifest identity does not match ${name}`);
25368
25467
  }
25369
25468
  function forceAutoUpdateOff(dir) {
25370
- const manifest = MANIFESTS.map((relative) => join36(dir, relative)).find((file) => existsSync29(file));
25469
+ const manifest = MANIFESTS.map((relative) => join36(dir, relative)).find((file) => existsSync28(file));
25371
25470
  if (manifest === undefined)
25372
25471
  throw new Error("dcode stage has no supported plugin manifest");
25373
25472
  const parsed = object9(JSON.parse(readFileSync30(manifest, "utf8")), "manifest");
@@ -25381,7 +25480,7 @@ function forceAutoUpdateOff(dir) {
25381
25480
  `);
25382
25481
  }
25383
25482
  function assertReadback(id, registryFile, enablementFile, target, version, projected, sourceRevision) {
25384
- if (existsSync29(join36(dcodeStateDir(), READBACK_FAULT)))
25483
+ if (existsSync28(join36(dcodeStateDir(), READBACK_FAULT)))
25385
25484
  throw new Error(`dcode readback failed for ${id}`);
25386
25485
  const registry = readRegistry3(registryFile);
25387
25486
  const enablement = readEnablement(enablementFile);
@@ -25407,18 +25506,18 @@ function assertReadback(id, registryFile, enablementFile, target, version, proje
25407
25506
  function retireFormer(path) {
25408
25507
  try {
25409
25508
  assertCachePath(path);
25410
- const stat = lstatSync21(path);
25509
+ const stat = lstatSync22(path);
25411
25510
  if (stat.isSymbolicLink() || !stat.isDirectory())
25412
25511
  throw new Error("former cache is not a directory");
25413
25512
  const backup = join36(dirname15(path), `.plgnz-dcode-retire-${basename5(path)}`);
25414
- if (existsSync29(backup)) {
25415
- if (!lstatSync21(backup).isDirectory())
25513
+ if (existsSync28(backup)) {
25514
+ if (!lstatSync22(backup).isDirectory())
25416
25515
  throw new Error("retire destination is not a directory");
25417
25516
  rmSync13(backup, { recursive: true, force: true });
25418
25517
  }
25419
25518
  renameSync10(path, backup);
25420
25519
  rmSync13(backup, { recursive: true, force: true });
25421
- if (existsSync29(path))
25520
+ if (existsSync28(path))
25422
25521
  throw new Error("former cache remains");
25423
25522
  return;
25424
25523
  } catch {
@@ -25440,7 +25539,7 @@ function listTree(root) {
25440
25539
  continue;
25441
25540
  const file = join36(dir, entry);
25442
25541
  const relative = prefix ? `${prefix}/${entry}` : entry;
25443
- const stat = lstatSync21(file);
25542
+ const stat = lstatSync22(file);
25444
25543
  if (stat.isSymbolicLink())
25445
25544
  throw new Error(`dcode plugin contains symlink: ${file}`);
25446
25545
  if (stat.isDirectory())
@@ -25455,12 +25554,12 @@ function listTree(root) {
25455
25554
  return out;
25456
25555
  }
25457
25556
  function sameTree7(left, right) {
25458
- if (!existsSync29(right))
25557
+ if (!existsSync28(right))
25459
25558
  return false;
25460
25559
  return JSON.stringify(listTree(left)) === JSON.stringify(listTree(right));
25461
25560
  }
25462
25561
  function readDoc2(file, fallback, label) {
25463
- if (!existsSync29(file))
25562
+ if (!existsSync28(file))
25464
25563
  return fallback;
25465
25564
  try {
25466
25565
  const value = JSON.parse(readFileSync30(file, "utf8"));
@@ -25520,7 +25619,7 @@ function ownership3(dir) {
25520
25619
  assertManagedPath4(dir);
25521
25620
  const file = join36(dir, MARKER8);
25522
25621
  assertManagedPath4(file);
25523
- if (!existsSync29(file))
25622
+ if (!existsSync28(file))
25524
25623
  return null;
25525
25624
  try {
25526
25625
  const value = object9(JSON.parse(readFileSync30(file, "utf8")), "ownership marker");
@@ -25550,7 +25649,7 @@ function writeDoc2(file, value) {
25550
25649
  }
25551
25650
  function snapshot2(file) {
25552
25651
  const read = readFileSync30;
25553
- return existsSync29(file) ? read(file) : undefined;
25652
+ return existsSync28(file) ? read(file) : undefined;
25554
25653
  }
25555
25654
  function restore3(file, before) {
25556
25655
  try {
@@ -25563,7 +25662,7 @@ function restore3(file, before) {
25563
25662
  } catch {}
25564
25663
  }
25565
25664
  function activate5(stage, target, parent) {
25566
- if (!existsSync29(target)) {
25665
+ if (!existsSync28(target)) {
25567
25666
  renameSync10(stage, target);
25568
25667
  return { commit: () => {}, rollback: () => rmSync13(target, { recursive: true, force: true }) };
25569
25668
  }
@@ -25589,7 +25688,7 @@ function moveAside3(path, parent = dirname15(path)) {
25589
25688
  return {
25590
25689
  commit: () => rmSync13(backupRoot, { recursive: true, force: true }),
25591
25690
  rollback: () => {
25592
- if (existsSync29(backup))
25691
+ if (existsSync28(backup))
25593
25692
  renameSync10(backup, path);
25594
25693
  rmSync13(backupRoot, { recursive: true, force: true });
25595
25694
  }
@@ -25598,7 +25697,7 @@ function moveAside3(path, parent = dirname15(path)) {
25598
25697
  function assertNoSymlinks6(dir) {
25599
25698
  for (const entry of readdirSync20(dir)) {
25600
25699
  const file = join36(dir, entry);
25601
- const stat = lstatSync21(file);
25700
+ const stat = lstatSync22(file);
25602
25701
  if (stat.isSymbolicLink())
25603
25702
  throw new Error(`dcode plugin contains symlink: ${file}`);
25604
25703
  if (stat.isDirectory())
@@ -25615,19 +25714,19 @@ function assertCachePath(path) {
25615
25714
  if (target === root || !target.startsWith(`${root}/`))
25616
25715
  throw new Error(`dcode path escapes managed cache: ${path}`);
25617
25716
  let current = root;
25618
- if (existsSync29(current) && lstatSync21(current).isSymbolicLink())
25717
+ if (existsSync28(current) && lstatSync22(current).isSymbolicLink())
25619
25718
  throw new Error(`dcode native path contains symlink: ${current}`);
25620
25719
  const relative = target.slice(root.length).replace(/^\//, "");
25621
25720
  for (const part of relative.length === 0 ? [] : relative.split("/")) {
25622
25721
  if (part === "" || part === "." || part === "..")
25623
25722
  throw new Error(`dcode path escapes managed cache: ${path}`);
25624
25723
  current = join36(current, part);
25625
- if (!existsSync29(current))
25724
+ if (!existsSync28(current))
25626
25725
  return;
25627
- if (lstatSync21(current).isSymbolicLink())
25726
+ if (lstatSync22(current).isSymbolicLink())
25628
25727
  throw new Error(`dcode native path contains symlink: ${current}`);
25629
25728
  }
25630
- if (!existsSync29(target) || !existsSync29(root))
25729
+ if (!existsSync28(target) || !existsSync28(root))
25631
25730
  return;
25632
25731
  const realRoot = realpathSync5(root);
25633
25732
  const realTarget = realpathSync5(target);
@@ -25640,18 +25739,18 @@ function assertManagedPath4(path) {
25640
25739
  if (target !== root && !target.startsWith(`${root}/`))
25641
25740
  throw new Error(`dcode path escapes native root: ${path}`);
25642
25741
  let current = root;
25643
- if (existsSync29(current) && lstatSync21(current).isSymbolicLink())
25742
+ if (existsSync28(current) && lstatSync22(current).isSymbolicLink())
25644
25743
  throw new Error(`dcode native path contains symlink: ${current}`);
25645
25744
  const relative = target.slice(root.length).replace(/^\//, "");
25646
25745
  for (const part of relative ? relative.split("/") : []) {
25647
25746
  current = join36(current, part);
25648
- if (existsSync29(current) && lstatSync21(current).isSymbolicLink())
25747
+ if (existsSync28(current) && lstatSync22(current).isSymbolicLink())
25649
25748
  throw new Error(`dcode native path contains symlink: ${current}`);
25650
25749
  }
25651
25750
  }
25652
25751
 
25653
25752
  // src/hosts/opencode-writer.ts
25654
- import { cpSync as cpSync12, existsSync as existsSync30, lstatSync as lstatSync22, mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync13, readFileSync as readFileSync31, readdirSync as readdirSync21, renameSync as renameSync11, rmSync as rmSync14, writeFileSync as writeFileSync14 } from "node:fs";
25753
+ import { cpSync as cpSync12, existsSync as existsSync29, lstatSync as lstatSync23, mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync13, readFileSync as readFileSync31, readdirSync as readdirSync21, renameSync as renameSync11, rmSync as rmSync14, writeFileSync as writeFileSync14 } from "node:fs";
25655
25754
  import { dirname as dirname16, join as join37 } from "node:path";
25656
25755
  import { tmpdir as tmpdir10 } from "node:os";
25657
25756
  var MARKER9 = ".plgnz-install.json";
@@ -25683,7 +25782,7 @@ var opencodeWriter = {
25683
25782
  try {
25684
25783
  for (const key of keys2()) {
25685
25784
  const target = targets[key];
25686
- if (!existsSync30(target)) {
25785
+ if (!existsSync29(target)) {
25687
25786
  moves.push({ target });
25688
25787
  continue;
25689
25788
  }
@@ -25722,7 +25821,7 @@ var opencodeWriter = {
25722
25821
  const targets = targetsFor(name, plugin);
25723
25822
  assertStore();
25724
25823
  for (const key of keys2())
25725
- if (existsSync30(targets[key])) {
25824
+ if (existsSync29(targets[key])) {
25726
25825
  assertManagedTree(targets[key]);
25727
25826
  if (!owned(targets[key], id))
25728
25827
  throw new Error(`OpenCode target is not owned by ${id}: ${targets[key]}`);
@@ -25731,7 +25830,7 @@ var opencodeWriter = {
25731
25830
  try {
25732
25831
  for (const key of keys2()) {
25733
25832
  const target = targets[key];
25734
- if (!existsSync30(target))
25833
+ if (!existsSync29(target))
25735
25834
  continue;
25736
25835
  const root = mkdtempSync13(join37(dirname16(target), ".plgnz-opencode-remove-"));
25737
25836
  const backup = join37(root, "previous");
@@ -25777,13 +25876,13 @@ function stagePackage(source, stage, name, activePrivateRoot, ownerValue) {
25777
25876
  return { private: privateRoot, skills, commands };
25778
25877
  }
25779
25878
  function sourceCommands(source) {
25780
- const root = existsSync30(join37(source, ".claude", "commands")) ? join37(source, ".claude", "commands") : join37(source, "commands");
25781
- if (!existsSync30(root))
25879
+ const root = existsSync29(join37(source, ".claude", "commands")) ? join37(source, ".claude", "commands") : join37(source, "commands");
25880
+ if (!existsSync29(root))
25782
25881
  return [];
25783
25882
  const out = [];
25784
25883
  const walk = (dir) => {
25785
25884
  for (const entry of readdirSync21(dir).sort()) {
25786
- const path = join37(dir, entry), stat = lstatSync22(path);
25885
+ const path = join37(dir, entry), stat = lstatSync23(path);
25787
25886
  if (stat.isDirectory()) {
25788
25887
  walk(path);
25789
25888
  continue;
@@ -25804,12 +25903,12 @@ function sourceCommands(source) {
25804
25903
  }
25805
25904
  function manualSkills(source) {
25806
25905
  const root = join37(source, "skills");
25807
- if (!existsSync30(root))
25906
+ if (!existsSync29(root))
25808
25907
  return [];
25809
25908
  const out = [];
25810
25909
  const walk = (dir) => {
25811
25910
  for (const entry of readdirSync21(dir).sort()) {
25812
- const path = join37(dir, entry), stat = lstatSync22(path);
25911
+ const path = join37(dir, entry), stat = lstatSync23(path);
25813
25912
  if (stat.isDirectory())
25814
25913
  walk(path);
25815
25914
  else if (stat.isFile() && entry === "SKILL.md") {
@@ -25915,7 +26014,7 @@ function targetsFor(name, commandNamespace) {
25915
26014
  }
25916
26015
  function owner3(path) {
25917
26016
  const file = join37(path, MARKER9);
25918
- if (!existsSync30(file))
26017
+ if (!existsSync29(file))
25919
26018
  return null;
25920
26019
  try {
25921
26020
  const value = JSON.parse(readFileSync31(file, "utf8"));
@@ -25935,7 +26034,7 @@ function owned(privateTarget, id, source) {
25935
26034
  }
25936
26035
  function checkTargets(targets, id, source) {
25937
26036
  for (const key of keys2())
25938
- if (existsSync30(targets[key])) {
26037
+ if (existsSync29(targets[key])) {
25939
26038
  assertManagedTree(targets[key]);
25940
26039
  if (!owned(targets[key], id, source))
25941
26040
  throw new Error(`OpenCode target is unowned or belongs to another source: ${targets[key]}`);
@@ -25945,7 +26044,7 @@ function allSame(staged, targets) {
25945
26044
  return keys2().every((key) => sameTree8(staged[key], targets[key]));
25946
26045
  }
25947
26046
  function sameTree8(a, b) {
25948
- if (!existsSync30(a) || !existsSync30(b))
26047
+ if (!existsSync29(a) || !existsSync29(b))
25949
26048
  return false;
25950
26049
  const bytes = readFileSync31;
25951
26050
  const list = (root) => {
@@ -25954,7 +26053,7 @@ function sameTree8(a, b) {
25954
26053
  for (const name of readdirSync21(dir).sort()) {
25955
26054
  if (name === MARKER9)
25956
26055
  continue;
25957
- const path = join37(dir, name), rel = prefix ? `${prefix}/${name}` : name, stat = lstatSync22(path);
26056
+ const path = join37(dir, name), rel = prefix ? `${prefix}/${name}` : name, stat = lstatSync23(path);
25958
26057
  if (stat.isDirectory())
25959
26058
  walk(path, rel);
25960
26059
  else if (stat.isFile())
@@ -25969,11 +26068,11 @@ function sameTree8(a, b) {
25969
26068
  return JSON.stringify(list(a)) === JSON.stringify(list(b));
25970
26069
  }
25971
26070
  function assertTree2(root) {
25972
- const stat = lstatSync22(root);
26071
+ const stat = lstatSync23(root);
25973
26072
  if (stat.isSymbolicLink() || !stat.isDirectory())
25974
26073
  throw new Error(`OpenCode plugin root is not a real directory: ${root}`);
25975
26074
  for (const name of readdirSync21(root)) {
25976
- const path = join37(root, name), child = lstatSync22(path);
26075
+ const path = join37(root, name), child = lstatSync23(path);
25977
26076
  if (name === MARKER9)
25978
26077
  throw new Error(`OpenCode plugin reserves ${MARKER9}: ${path}`);
25979
26078
  if (child.isSymbolicLink())
@@ -25985,11 +26084,11 @@ function assertTree2(root) {
25985
26084
  }
25986
26085
  }
25987
26086
  function assertManagedTree(root) {
25988
- const stat = lstatSync22(root);
26087
+ const stat = lstatSync23(root);
25989
26088
  if (stat.isSymbolicLink() || !stat.isDirectory())
25990
26089
  throw new Error(`OpenCode managed tree is unsafe: ${root}`);
25991
26090
  for (const name of readdirSync21(root)) {
25992
- const path = join37(root, name), child = lstatSync22(path);
26091
+ const path = join37(root, name), child = lstatSync23(path);
25993
26092
  if (child.isSymbolicLink())
25994
26093
  throw new Error(`OpenCode managed tree contains symlink: ${path}`);
25995
26094
  if (child.isDirectory())
@@ -26000,11 +26099,11 @@ function assertManagedTree(root) {
26000
26099
  }
26001
26100
  function assertSupportedRoot(source) {
26002
26101
  for (const entry of ["agents", "hooks", ".claude/agents", ".claude/hooks", "mcp.json", ".mcp.json"])
26003
- if (existsSync30(join37(source, entry)))
26102
+ if (existsSync29(join37(source, entry)))
26004
26103
  throw new Error(`OpenCode cannot preserve root ${entry} semantics: ${join37(source, entry)}`);
26005
26104
  for (const file of ["plugin.json", ".plugin/plugin.json", ".claude-plugin/plugin.json"]) {
26006
26105
  const path = join37(source, file);
26007
- if (!existsSync30(path))
26106
+ if (!existsSync29(path))
26008
26107
  continue;
26009
26108
  let manifest;
26010
26109
  try {
@@ -26021,7 +26120,7 @@ function assertSupportedRoot(source) {
26021
26120
  }
26022
26121
  function assertStore() {
26023
26122
  for (const path of [opencodeRoot(), join37(opencodeRoot(), ".plgnz"), opencodePackagesDir(), opencodeSkillsDir(), opencodeCommandsDir()])
26024
- if (existsSync30(path) && (!lstatSync22(path).isDirectory() || lstatSync22(path).isSymbolicLink()))
26123
+ if (existsSync29(path) && (!lstatSync23(path).isDirectory() || lstatSync23(path).isSymbolicLink()))
26025
26124
  throw new Error(`OpenCode managed path is unsafe: ${path}`);
26026
26125
  }
26027
26126
  function ensureStore2() {
@@ -26043,7 +26142,7 @@ var opencodeHookWriter = createNativeHookWriter({
26043
26142
 
26044
26143
  // src/hosts/grok-writer.ts
26045
26144
  import { spawnSync as spawnSync6 } from "node:child_process";
26046
- import { cpSync as cpSync13, existsSync as existsSync31, lstatSync as lstatSync23, mkdirSync as mkdirSync15, mkdtempSync as mkdtempSync14, readFileSync as readFileSync32, readdirSync as readdirSync22, readlinkSync as readlinkSync3, renameSync as renameSync12, rmSync as rmSync15, symlinkSync as symlinkSync2, writeFileSync as writeFileSync15 } from "node:fs";
26145
+ import { cpSync as cpSync13, existsSync as existsSync30, lstatSync as lstatSync24, mkdirSync as mkdirSync15, mkdtempSync as mkdtempSync14, readFileSync as readFileSync32, readdirSync as readdirSync22, readlinkSync as readlinkSync3, renameSync as renameSync12, rmSync as rmSync15, symlinkSync as symlinkSync2, writeFileSync as writeFileSync15 } from "node:fs";
26047
26146
  import { dirname as dirname17, join as join38, resolve as resolve24 } from "node:path";
26048
26147
  import { tmpdir as tmpdir11 } from "node:os";
26049
26148
  var stableId = (plugin) => plugin.marketplace === undefined ? plugin.name : `${plugin.name}@${plugin.marketplace}`;
@@ -26082,7 +26181,7 @@ var grokWriter = {
26082
26181
  const activation = join38(grokRoot(), "plugins", plugin.name);
26083
26182
  const existingNative = grok.listInstalled().find((candidate) => candidate.name === plugin.name)?.path;
26084
26183
  assertActivationLink(activation, existingNative);
26085
- const unchanged = lstatExists2(activation) && prior !== undefined && priorMarker?.fingerprint === plugin.contentFingerprint && priorMarker?.nativeFingerprint === nativeFingerprint && existsSync31(join38(prior, "plugins", plugin.name)) && fingerprintTree(join38(prior, "plugins", plugin.name)) === nativeFingerprint && current(id, prior, plugin.name, nativeFingerprint);
26184
+ const unchanged = lstatExists2(activation) && prior !== undefined && priorMarker?.fingerprint === plugin.contentFingerprint && priorMarker?.nativeFingerprint === nativeFingerprint && existsSync30(join38(prior, "plugins", plugin.name)) && fingerprintTree(join38(prior, "plugins", plugin.name)) === nativeFingerprint && current(id, prior, plugin.name, nativeFingerprint);
26086
26185
  if (opts?.dryRun)
26087
26186
  return unchanged ? "unchanged" : undefined;
26088
26187
  if (unchanged)
@@ -26228,7 +26327,7 @@ function basename6(path) {
26228
26327
  function assertActivationLink(link, nativePath) {
26229
26328
  if (!lstatExists2(link))
26230
26329
  return;
26231
- if (nativePath === undefined || !lstatSync23(link).isSymbolicLink() || canonical(nativePath) === undefined || canonical(link) !== canonical(nativePath)) {
26330
+ if (nativePath === undefined || !lstatSync24(link).isSymbolicLink() || canonical(nativePath) === undefined || canonical(link) !== canonical(nativePath)) {
26232
26331
  throw new Error(`Grok activation path is not the registered native plugin: ${link}`);
26233
26332
  }
26234
26333
  }
@@ -26294,7 +26393,7 @@ function validateGrokSource(dir) {
26294
26393
  }
26295
26394
  function projectGrokSource(dir) {
26296
26395
  const manifest = join38(dir, "plugin.json");
26297
- if (existsSync31(manifest)) {
26396
+ if (existsSync30(manifest)) {
26298
26397
  const doc = JSON.parse(readFileSync32(manifest, "utf8"));
26299
26398
  if (doc["permissions"] !== undefined)
26300
26399
  throw new Error(`Grok permission semantics are unverified: ${manifest}`);
@@ -26302,13 +26401,13 @@ function projectGrokSource(dir) {
26302
26401
  throw new Error(`Grok custom command path is unverified: ${manifest}`);
26303
26402
  }
26304
26403
  const skills = join38(dir, "skills");
26305
- if (existsSync31(skills))
26404
+ if (existsSync30(skills))
26306
26405
  for (const name of readdirSync22(skills)) {
26307
26406
  const skill = join38(skills, name);
26308
- if (!lstatSync23(skill).isDirectory())
26407
+ if (!lstatSync24(skill).isDirectory())
26309
26408
  continue;
26310
26409
  const file = join38(skill, "SKILL.md");
26311
- if (!existsSync31(file))
26410
+ if (!existsSync30(file))
26312
26411
  continue;
26313
26412
  const raw = readFileSync32(file, "utf8");
26314
26413
  const fm = openingFrontmatter3(raw, file);
@@ -26318,7 +26417,7 @@ function projectGrokSource(dir) {
26318
26417
  normalizeBooleanPolicy(fm, "user-invocable", "user_invocable", file);
26319
26418
  const sidecar = join38(skill, "agents", "openai.yaml");
26320
26419
  let sidecarManual;
26321
- if (existsSync31(sidecar)) {
26420
+ if (existsSync30(sidecar)) {
26322
26421
  const parsed = yamlParse(readFileSync32(sidecar, "utf8"));
26323
26422
  const policy = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed["policy"] : undefined;
26324
26423
  if (policy !== undefined) {
@@ -26340,19 +26439,19 @@ function projectGrokSource(dir) {
26340
26439
  const commands = join38(dir, "commands");
26341
26440
  const claudeCommands = join38(dir, ".claude", "commands");
26342
26441
  const seen = new Set;
26343
- for (const source of [existsSync31(commands) ? commands : claudeCommands]) {
26344
- if (!existsSync31(source))
26442
+ for (const source of [existsSync30(commands) ? commands : claudeCommands]) {
26443
+ if (!existsSync30(source))
26345
26444
  continue;
26346
26445
  for (const entry of readdirSync22(source)) {
26347
26446
  const path = join38(source, entry);
26348
- const stat = lstatSync23(path);
26447
+ const stat = lstatSync24(path);
26349
26448
  if (!stat.isFile() || !/\.(md|toml)$/u.test(entry))
26350
26449
  continue;
26351
26450
  const name = entry.replace(/\.(md|toml)$/u, "");
26352
26451
  if (seen.has(name))
26353
26452
  throw new Error(`duplicate Grok command ${name}`);
26354
26453
  seen.add(name);
26355
- if (existsSync31(join38(skills, name, "SKILL.md")))
26454
+ if (existsSync30(join38(skills, name, "SKILL.md")))
26356
26455
  throw new Error(`Grok command ${name} collides with a native skill`);
26357
26456
  const output = join38(commands, `${name}.md`);
26358
26457
  if (entry.endsWith(".md")) {
@@ -26403,11 +26502,11 @@ ${doc.prompt}`);
26403
26502
  }
26404
26503
  const legacyMcp = join38(dir, "mcp.json");
26405
26504
  const nativeMcp = join38(dir, ".mcp.json");
26406
- if (existsSync31(legacyMcp) && existsSync31(nativeMcp) && canonicalJson2(JSON.parse(readFileSync32(legacyMcp, "utf8")).mcpServers) !== canonicalJson2(JSON.parse(readFileSync32(nativeMcp, "utf8")).mcpServers))
26505
+ if (existsSync30(legacyMcp) && existsSync30(nativeMcp) && canonicalJson2(JSON.parse(readFileSync32(legacyMcp, "utf8")).mcpServers) !== canonicalJson2(JSON.parse(readFileSync32(nativeMcp, "utf8")).mcpServers))
26407
26506
  throw new Error(`conflicting Grok MCP declarations: ${legacyMcp} and ${nativeMcp}`);
26408
- if (existsSync31(legacyMcp) && !existsSync31(nativeMcp))
26507
+ if (existsSync30(legacyMcp) && !existsSync30(nativeMcp))
26409
26508
  cpSync13(legacyMcp, nativeMcp);
26410
- if (existsSync31(nativeMcp)) {
26509
+ if (existsSync30(nativeMcp)) {
26411
26510
  const value = JSON.parse(readFileSync32(nativeMcp, "utf8"));
26412
26511
  const servers = value?.["mcpServers"];
26413
26512
  if (!value || typeof value !== "object" || !servers || typeof servers !== "object" || Array.isArray(servers))
@@ -26457,28 +26556,28 @@ function legacyCandidate(plugin, adopt, prior) {
26457
26556
  throw new Error(`Grok ${plugin.name}: an existing native install is not plgnz-owned; refusing to replace it`);
26458
26557
  const installed = canonical(matches[0].path);
26459
26558
  const base = canonical(join38(grokRoot(), "installed-plugins"));
26460
- if (installed === undefined || base === undefined || !installed.startsWith(`${base}/`) || lstatSync23(matches[0].path).isSymbolicLink())
26559
+ if (installed === undefined || base === undefined || !installed.startsWith(`${base}/`) || lstatSync24(matches[0].path).isSymbolicLink())
26461
26560
  throw new Error(`Grok ${plugin.name}: legacy native path is unsafe`);
26462
26561
  const rows = repos().filter(([, repo]) => canonical(typeof repo.path === "string" ? repo.path : "") === installed);
26463
26562
  if (rows.length !== 1 || provenanceOf(rows[0][1]) !== null || namesOf(rows[0][1]).length !== 1 || namesOf(rows[0][1])[0] !== plugin.name)
26464
26563
  throw new Error(`Grok ${plugin.name}: legacy native identity is ambiguous`);
26465
26564
  const source = localSourceOf(rows[0][1]);
26466
- if (source === undefined || !existsSync31(source) || lstatSync23(source).isSymbolicLink())
26565
+ if (source === undefined || !existsSync30(source) || lstatSync24(source).isSymbolicLink())
26467
26566
  throw new Error(`Grok ${plugin.name}: legacy source is missing or unsafe`);
26468
26567
  const oldManifest = JSON.parse(readFileSync32(join38(installed, "plugin.json"), "utf8"));
26469
26568
  const newManifest = JSON.parse(readFileSync32(join38(plugin.dir, "plugin.json"), "utf8"));
26470
26569
  if (oldManifest.name !== plugin.name || newManifest.name !== plugin.name || oldManifest.version !== newManifest.version || fingerprintTree(source) !== fingerprintTree(installed))
26471
26570
  throw new Error(`Grok ${plugin.name}: legacy source, version, and native bytes must match before adoption`);
26472
26571
  const link = join38(grokRoot(), "plugins", plugin.name);
26473
- if (existsSync31(link) || lstatExists2(link)) {
26474
- if (!lstatSync23(link).isSymbolicLink() || canonical(resolve24(dirname17(link), readlinkSync3(link))) !== installed)
26572
+ if (existsSync30(link) || lstatExists2(link)) {
26573
+ if (!lstatSync24(link).isSymbolicLink() || canonical(resolve24(dirname17(link), readlinkSync3(link))) !== installed)
26475
26574
  throw new Error(`Grok ${plugin.name}: unmanaged same-name plugin link blocks adoption`);
26476
26575
  }
26477
26576
  return { source, fingerprint: fingerprintTree(installed), ...lstatExists2(link) ? { link } : {} };
26478
26577
  }
26479
26578
  function lstatExists2(path) {
26480
26579
  try {
26481
- lstatSync23(path);
26580
+ lstatSync24(path);
26482
26581
  return true;
26483
26582
  } catch {
26484
26583
  return false;
@@ -26505,7 +26604,7 @@ function assertOwnedRoot(root) {
26505
26604
  let current = base;
26506
26605
  for (const part of relative) {
26507
26606
  current = join38(current, part);
26508
- const stat = lstatSync23(current);
26607
+ const stat = lstatSync24(current);
26509
26608
  if (stat.isSymbolicLink() || !stat.isDirectory())
26510
26609
  throw new Error(`Grok marketplace root is not a safe owned directory: ${current}`);
26511
26610
  }
@@ -26697,7 +26796,7 @@ function configPriorRecord(attemptId, operationId) {
26697
26796
  }
26698
26797
  function discardStage(attemptId, operationId) {
26699
26798
  const record = stageRecord(attemptId, operationId);
26700
- if (existsSync31(record)) {
26799
+ if (existsSync30(record)) {
26701
26800
  const stage = readFileSync32(record, "utf8").trim();
26702
26801
  if (stage !== "")
26703
26802
  rmSync15(stage, { recursive: true, force: true });
@@ -26763,7 +26862,7 @@ function marketplacePathOf(repo) {
26763
26862
  }
26764
26863
  function savedRegistryRepo(directory) {
26765
26864
  const file = join38(directory, "registry-repo.json");
26766
- if (!existsSync31(file))
26865
+ if (!existsSync30(file))
26767
26866
  return { key: null, repo: null };
26768
26867
  const value = JSON.parse(readFileSync32(file, "utf8"));
26769
26868
  const key = typeof value.key === "string" ? value.key : null;
@@ -26833,7 +26932,7 @@ function captureHostSnapshot(directory, nativeId, packageName, attemptId, operat
26833
26932
  rmSync15(directory, { recursive: true, force: true });
26834
26933
  mkdirSync15(directory, { recursive: true });
26835
26934
  const priorConfig = configPriorRecord(attemptId, operationId);
26836
- if (existsSync31(priorConfig))
26935
+ if (existsSync30(priorConfig))
26837
26936
  cpSync13(priorConfig, join38(directory, "config-prior.json"));
26838
26937
  const plugin = grok.listInstalled().find((candidate) => candidate.id === nativeId);
26839
26938
  if (plugin?.path !== undefined) {
@@ -26851,7 +26950,7 @@ function captureHostSnapshot(directory, nativeId, packageName, attemptId, operat
26851
26950
  const matched = matchingRegistryRepo(nativeId, packageName);
26852
26951
  writeFileSync15(join38(directory, "registry-repo.json"), JSON.stringify(matched === undefined ? { key: null } : { key: matched[0], repo: matched[1] }));
26853
26952
  const link = join38(grokRoot(), "plugins", packageName);
26854
- if (lstatExists2(link) && lstatSync23(link).isSymbolicLink())
26953
+ if (lstatExists2(link) && lstatSync24(link).isSymbolicLink())
26855
26954
  writeFileSync15(join38(directory, "link.txt"), readlinkSync3(link));
26856
26955
  }
26857
26956
  function freshNativePaths(directory, marketplacePath) {
@@ -26870,17 +26969,17 @@ function freshNativePaths(directory, marketplacePath) {
26870
26969
  }
26871
26970
  function restoreActivationLink(directory, packageName) {
26872
26971
  const link = join38(grokRoot(), "plugins", packageName);
26873
- if (existsSync31(join38(directory, "link.txt"))) {
26972
+ if (existsSync30(join38(directory, "link.txt"))) {
26874
26973
  if (lstatExists2(link))
26875
26974
  rmSync15(link);
26876
26975
  symlinkSync2(readFileSync32(join38(directory, "link.txt"), "utf8"), link);
26877
26976
  return;
26878
26977
  }
26879
- if (lstatExists2(link) && lstatSync23(link).isSymbolicLink())
26978
+ if (lstatExists2(link) && lstatSync24(link).isSymbolicLink())
26880
26979
  rmSync15(link);
26881
26980
  }
26882
26981
  function restoreConfigFile(record) {
26883
- if (!existsSync31(record))
26982
+ if (!existsSync30(record))
26884
26983
  return;
26885
26984
  const value = JSON.parse(readFileSync32(record, "utf8"));
26886
26985
  const file = configFile3();
@@ -26898,8 +26997,8 @@ function restoreHostSnapshot(directory, scopeId, nativeId, packageName) {
26898
26997
  const finalPath = lifecycleMarketplace(scopeId, nativeId);
26899
26998
  const backupPath = join38(directory, "backup-path.txt");
26900
26999
  const nativePathFile = join38(directory, "native-path.txt");
26901
- const hadNative = existsSync31(nativePathFile);
26902
- const hadMarketplace = existsSync31(join38(directory, "marketplace"));
27000
+ const hadNative = existsSync30(nativePathFile);
27001
+ const hadMarketplace = existsSync30(join38(directory, "marketplace"));
26903
27002
  if (!hadNative)
26904
27003
  for (const native of freshNativePaths(directory, finalPath))
26905
27004
  rmSync15(native, { recursive: true, force: true });
@@ -26919,7 +27018,7 @@ function restoreHostSnapshot(directory, scopeId, nativeId, packageName) {
26919
27018
  restoreRegistryKey(directory, finalPath, packageName);
26920
27019
  restoreActivationLink(directory, packageName);
26921
27020
  restoreRecordedConfig(directory);
26922
- if (existsSync31(backupPath))
27021
+ if (existsSync30(backupPath))
26923
27022
  rmSync15(readFileSync32(backupPath, "utf8"), { recursive: true, force: true });
26924
27023
  if (hadNative) {
26925
27024
  run(["plugin", "update", packageName]);
@@ -26946,7 +27045,7 @@ ${tail}`;
26946
27045
  }
26947
27046
  function pinPluginAutoUpdate(attemptId, operationId) {
26948
27047
  const file = configFile3();
26949
- const present = existsSync31(file);
27048
+ const present = existsSync30(file);
26950
27049
  const current = present ? readFileSync32(file, "utf8") : "";
26951
27050
  const record = configPriorRecord(attemptId, operationId);
26952
27051
  mkdirSync15(dirname17(record), { recursive: true });
@@ -27048,7 +27147,7 @@ var grokLifecycleDefinition = {
27048
27147
  refreshStagedFingerprint(prepared.stagingRoot, nativeFingerprint);
27049
27148
  const finalPath = lifecycleMarketplace(prepared.handle.scopeId, prepared.handle.nativeId);
27050
27149
  const stagedRoot = dirname17(dirname17(prepared.stagingRoot));
27051
- const backup = existsSync31(finalPath) ? `${finalPath}.plgnz-backup-${prepared.handle.attemptId}` : undefined;
27150
+ const backup = existsSync30(finalPath) ? `${finalPath}.plgnz-backup-${prepared.handle.attemptId}` : undefined;
27052
27151
  if (backup !== undefined)
27053
27152
  renameSync12(finalPath, backup);
27054
27153
  renameSync12(stagedRoot, finalPath);
@@ -27136,25 +27235,25 @@ function createGrokLifecycleAdapter() {
27136
27235
 
27137
27236
  // src/hosts/zcode-cli-writer.ts
27138
27237
  init_zcode_cli_hooks();
27139
- import { chmodSync as chmodSync3, cpSync as cpSync14, existsSync as existsSync32, lstatSync as lstatSync25, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync15, readFileSync as readFileSync34, readdirSync as readdirSync24, realpathSync as realpathSync6, renameSync as renameSync13, rmSync as rmSync16, statSync as statSync13, writeFileSync as writeFileSync16 } from "node:fs";
27238
+ import { chmodSync as chmodSync3, cpSync as cpSync14, existsSync as existsSync31, lstatSync as lstatSync26, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync15, readFileSync as readFileSync34, readdirSync as readdirSync24, realpathSync as realpathSync6, renameSync as renameSync13, rmSync as rmSync16, statSync as statSync13, writeFileSync as writeFileSync16 } from "node:fs";
27140
27239
  import { basename as basename7, dirname as dirname19, join as join40, resolve as resolve26 } from "node:path";
27141
27240
  import { tmpdir as tmpdir12 } from "node:os";
27142
27241
 
27143
27242
  // src/hosts/zcode-cli-projection.ts
27144
- import { lstatSync as lstatSync24, readFileSync as readFileSync33, readdirSync as readdirSync23 } from "node:fs";
27243
+ import { lstatSync as lstatSync25, readFileSync as readFileSync33, readdirSync as readdirSync23 } from "node:fs";
27145
27244
  import { dirname as dirname18, join as join39, relative as relative8, resolve as resolve25 } from "node:path";
27146
27245
  var encode2 = (value) => new TextEncoder().encode(value);
27147
27246
  var decode = (value) => new TextDecoder().decode(value);
27148
27247
  function readZcodeProjectionTree(root) {
27149
27248
  const tree = new Map;
27150
27249
  const walk = (path, prefix) => {
27151
- const stat = lstatSync24(path);
27250
+ const stat = lstatSync25(path);
27152
27251
  if (stat.isSymbolicLink())
27153
27252
  throw new Error(`ZCode projection contains symlink: ${path}`);
27154
27253
  if (!stat.isDirectory())
27155
27254
  throw new Error(`ZCode projection root is not a directory: ${path}`);
27156
27255
  for (const name of readdirSync23(path).sort()) {
27157
- const file = join39(path, name), key = prefix === "" ? name : `${prefix}/${name}`, child = lstatSync24(file);
27256
+ const file = join39(path, name), key = prefix === "" ? name : `${prefix}/${name}`, child = lstatSync25(file);
27158
27257
  if (child.isSymbolicLink())
27159
27258
  throw new Error(`ZCode projection contains symlink: ${file}`);
27160
27259
  if (child.isDirectory()) {
@@ -27426,7 +27525,7 @@ function projectZcodePlugin(source, destination, resourceCopy, resourceLinkRoot,
27426
27525
  const target = resolve26(destination);
27427
27526
  const ownedResources = resolve26(resourceCopy);
27428
27527
  const links = resolve26(resourceLinkRoot);
27429
- if (!existsSync32(input) || !statSync13(input).isDirectory())
27528
+ if (!existsSync31(input) || !statSync13(input).isDirectory())
27430
27529
  throw new Error(`ZCode plugin source is not a directory: ${input}`);
27431
27530
  if (target === input || ownedResources === input || target.startsWith(`${input}/`) || ownedResources.startsWith(`${input}/`))
27432
27531
  throw new Error("ZCode projected outputs must not be inside the source");
@@ -27438,7 +27537,7 @@ function projectZcodePlugin(source, destination, resourceCopy, resourceLinkRoot,
27438
27537
  }
27439
27538
  for (const output of [target, ownedResources]) {
27440
27539
  try {
27441
- lstatSync25(output);
27540
+ lstatSync26(output);
27442
27541
  assertNoSymlinks7(output);
27443
27542
  } catch (error) {
27444
27543
  if (error.code !== "ENOENT")
@@ -27487,7 +27586,7 @@ function readJson3(file) {
27487
27586
  }
27488
27587
  }
27489
27588
  function commandNames(dir, prefix = "") {
27490
- if (!existsSync32(dir))
27589
+ if (!existsSync31(dir))
27491
27590
  return [];
27492
27591
  const out = [];
27493
27592
  for (const name of readdirSync24(dir)) {
@@ -27532,7 +27631,7 @@ function nativeForLogical(logicalId) {
27532
27631
  }
27533
27632
  function sameCandidate(prior, market, resources, resourceRoot, logical, native, source, fingerprint) {
27534
27633
  const marker = readZcodeOwnership(prior.installPath);
27535
- if (marker?.logicalId !== logical || marker.nativeId !== native || marker.source !== source || marker.fingerprint !== fingerprint || marker.resourcePath !== resourceRoot || !existsSync32(resourceRoot))
27634
+ if (marker?.logicalId !== logical || marker.nativeId !== native || marker.source !== source || marker.fingerprint !== fingerprint || marker.resourcePath !== resourceRoot || !existsSync31(resourceRoot))
27536
27635
  return false;
27537
27636
  try {
27538
27637
  return fingerprintTree(join40(market, "plugins", prior.name)) === fingerprintTree(prior.installPath) && fingerprintTree(resources) === fingerprintTree(resourceRoot);
@@ -27541,21 +27640,21 @@ function sameCandidate(prior, market, resources, resourceRoot, logical, native,
27541
27640
  }
27542
27641
  }
27543
27642
  function assertReplaceableOwnedRoots(market, resources, name, prior, logical, native, source) {
27544
- if (!existsSync32(market) && !existsSync32(resources))
27643
+ if (!existsSync31(market) && !existsSync31(resources))
27545
27644
  return;
27546
27645
  if (prior === undefined)
27547
- throw new Error(`Official ZCode owned path already exists without a proven native install: ${existsSync32(market) ? market : resources}`);
27646
+ throw new Error(`Official ZCode owned path already exists without a proven native install: ${existsSync31(market) ? market : resources}`);
27548
27647
  const priorRoot = zcodeSafeInstallRoot(prior.installPath);
27549
27648
  const marker = priorRoot === undefined ? null : readZcodeOwnership(priorRoot);
27550
27649
  if (marker?.logicalId !== logical || marker.nativeId !== native || marker.source !== source)
27551
27650
  throw new Error(`Official ZCode existing paths are not proven owned: ${native}`);
27552
- if (existsSync32(market)) {
27651
+ if (existsSync31(market)) {
27553
27652
  assertNoSymlinks7(market);
27554
27653
  const staged = readZcodeOwnership(join40(market, "plugins", name));
27555
27654
  if (staged?.logicalId !== logical || staged.nativeId !== native || staged.source !== source)
27556
27655
  throw new Error(`Official ZCode marketplace root is not proven owned: ${market}`);
27557
27656
  }
27558
- if (existsSync32(resources) && marker.resourcePath !== resources)
27657
+ if (existsSync31(resources) && marker.resourcePath !== resources)
27559
27658
  throw new Error(`Official ZCode resource root is not proven owned: ${resources}`);
27560
27659
  }
27561
27660
  function provePrior(prior, logical, native, source) {
@@ -27613,12 +27712,12 @@ function requireFingerprint(plugin) {
27613
27712
  return fp.toLowerCase();
27614
27713
  }
27615
27714
  function moveAside4(path) {
27616
- if (!existsSync32(path))
27715
+ if (!existsSync31(path))
27617
27716
  return { rollback: () => {}, commit: () => {} };
27618
27717
  const backup = `${path}.plgnz-backup-${Date.now()}`;
27619
27718
  renameSync13(path, backup);
27620
27719
  return { rollback: () => {
27621
- if (!existsSync32(path))
27720
+ if (!existsSync31(path))
27622
27721
  renameSync13(backup, path);
27623
27722
  }, commit: () => rmSync16(backup, { recursive: true, force: true }) };
27624
27723
  }
@@ -27628,7 +27727,7 @@ function assertName(value, label) {
27628
27727
  }
27629
27728
  function assertNoSymlinks7(root) {
27630
27729
  const visit = (path) => {
27631
- const stat = lstatSync25(path);
27730
+ const stat = lstatSync26(path);
27632
27731
  if (stat.isSymbolicLink())
27633
27732
  throw new Error(`ZCode source contains symlink: ${path}`);
27634
27733
  if (stat.isDirectory())
@@ -27745,7 +27844,7 @@ function capturedNativeRoot(reference, attemptId, operationId) {
27745
27844
  const root = dirname19(dirname19(dirname19(reference)));
27746
27845
  for (const ancestor of [join40(root, "plgnz-lifecycle"), join40(root, "plgnz-lifecycle", attemptId), reference]) {
27747
27846
  try {
27748
- if (lstatSync25(ancestor).isSymbolicLink())
27847
+ if (lstatSync26(ancestor).isSymbolicLink())
27749
27848
  throw new Error("ZCode captured snapshot ancestor was redirected");
27750
27849
  } catch (error) {
27751
27850
  if (!isObject4(error) || error["code"] !== "ENOENT")
@@ -27757,7 +27856,7 @@ function capturedNativeRoot(reference, attemptId, operationId) {
27757
27856
  return root;
27758
27857
  }
27759
27858
  function assertStageCleanupAuthority(stage, reference) {
27760
- if (lstatSync25(dirname19(stage)).isSymbolicLink() || lstatSync25(stage).isSymbolicLink())
27859
+ if (lstatSync26(dirname19(stage)).isSymbolicLink() || lstatSync26(stage).isSymbolicLink())
27761
27860
  throw new Error("ZCode cleanup stage is redirected");
27762
27861
  assertNoSymlinks7(stage);
27763
27862
  const artifact = reference.artifactId;
@@ -27796,7 +27895,7 @@ function assertStageCleanupAuthority(stage, reference) {
27796
27895
  }
27797
27896
  function readConfigObject() {
27798
27897
  const file = join40(zcodeCliConfigRoot(), "config.json");
27799
- if (!existsSync32(file))
27898
+ if (!existsSync31(file))
27800
27899
  return null;
27801
27900
  const value = JSON.parse(readFileSync34(file, "utf8"));
27802
27901
  if (!isObject4(value))
@@ -27814,7 +27913,7 @@ function optionValue(nativeId) {
27814
27913
  }
27815
27914
  function retainedState(nativeId) {
27816
27915
  const dataDir = zcodePluginDataDir(nativeId);
27817
- const pluginData = existsSync32(dataDir) && statSync13(dataDir).isDirectory() ? { state: "present", fingerprint: fingerprintTree(dataDir) } : { state: "absent", fingerprint: null };
27916
+ const pluginData = existsSync31(dataDir) && statSync13(dataDir).isDirectory() ? { state: "present", fingerprint: fingerprintTree(dataDir) } : { state: "absent", fingerprint: null };
27818
27917
  const options = optionValue(nativeId);
27819
27918
  const inactiveMetadata = options === undefined ? { state: "absent", fingerprint: null } : { state: "present", fingerprint: sha2562(canonicalJson3(options)) };
27820
27919
  return { pluginData, inactiveMetadata };
@@ -27906,9 +28005,9 @@ function resourceObservation2(root, digest) {
27906
28005
  const expected = join40(zcodeResourceRoot(), marketplaceName2(marker.nativeId), marker.fingerprint);
27907
28006
  if (canonicalExistingPath(resourcePath) !== canonicalExistingPath(expected))
27908
28007
  throw new Error("ZCode resource receipt names a foreign root");
27909
- if (!existsSync32(resourcePath))
28008
+ if (!existsSync31(resourcePath))
27910
28009
  return { roots, conforming: false };
27911
- if (lstatSync25(resourcePath).isSymbolicLink())
28010
+ if (lstatSync26(resourcePath).isSymbolicLink())
27912
28011
  throw new Error("ZCode resource receipt root is redirected");
27913
28012
  const resource = realpathSync6(resourcePath);
27914
28013
  const owned = realpathSync6(zcodeResourceRoot());
@@ -27922,7 +28021,7 @@ function retirementSnapshot(attemptId, operationId, nativeId) {
27922
28021
  const dir = join40(realpathSync6(zcodeCliRoot()), "plgnz-lifecycle", attemptId, operationId);
27923
28022
  if (canonicalExistingPath(dir) !== dir)
27924
28023
  throw new Error("ZCode rollback snapshot path is redirected");
27925
- if (existsSync32(dir)) {
28024
+ if (existsSync31(dir)) {
27926
28025
  if (!statSync13(dir).isDirectory())
27927
28026
  throw new Error(`ZCode rollback snapshot already exists and is not a directory: ${dir}`);
27928
28027
  return dir;
@@ -27934,17 +28033,17 @@ function retirementSnapshot(attemptId, operationId, nativeId) {
27934
28033
  cpSync14(root, join40(dir, "cache"), { recursive: true });
27935
28034
  writeFileSync16(join40(dir, "install-path.txt"), root ?? "");
27936
28035
  const registry = zcodeRegistryFile();
27937
- if (existsSync32(registry))
28036
+ if (existsSync31(registry))
27938
28037
  cpSync14(registry, join40(dir, "installed_plugins.json"));
27939
28038
  const config = join40(zcodeCliConfigRoot(), "config.json");
27940
- if (existsSync32(config))
28039
+ if (existsSync31(config))
27941
28040
  cpSync14(config, join40(dir, "config.json"));
27942
28041
  return dir;
27943
28042
  }
27944
28043
  function canonicalExistingPath(path) {
27945
28044
  const missing = [];
27946
28045
  let current = path;
27947
- while (!existsSync32(current)) {
28046
+ while (!existsSync31(current)) {
27948
28047
  const parent = dirname19(current);
27949
28048
  if (parent === current)
27950
28049
  throw new Error(`ZCode path does not exist: ${path}`);
@@ -27960,7 +28059,7 @@ function isCacheInstallPath(path) {
27960
28059
  }
27961
28060
  function removeRegistryPlugin(nativeId) {
27962
28061
  const file = zcodeRegistryFile();
27963
- if (!existsSync32(file))
28062
+ if (!existsSync31(file))
27964
28063
  return false;
27965
28064
  const value = JSON.parse(readFileSync34(file, "utf8"));
27966
28065
  if (!isObject4(value) || !Array.isArray(value["plugins"]))
@@ -27976,7 +28075,7 @@ function removeRegistryPlugin(nativeId) {
27976
28075
  }
27977
28076
  function removeEnabledFlag(nativeId) {
27978
28077
  const file = join40(zcodeCliConfigRoot(), "config.json");
27979
- if (!existsSync32(file))
28078
+ if (!existsSync31(file))
27980
28079
  return;
27981
28080
  const value = readConfigObject();
27982
28081
  if (value === null || !isObject4(value["plugins"]) || !isObject4(value["plugins"]["enabledPlugins"]))
@@ -27988,7 +28087,7 @@ function removeEnabledFlag(nativeId) {
27988
28087
  `);
27989
28088
  }
27990
28089
  function snapshotRegistryRow(file, nativeId) {
27991
- if (!existsSync32(file))
28090
+ if (!existsSync31(file))
27992
28091
  return;
27993
28092
  const value = JSON.parse(readFileSync34(file, "utf8"));
27994
28093
  if (!isObject4(value) || !Array.isArray(value["plugins"]))
@@ -28001,9 +28100,9 @@ function snapshotRegistryRow(file, nativeId) {
28001
28100
  function restoreRegistryPlugin(nativeId, snapshotFile) {
28002
28101
  const saved = snapshotRegistryRow(snapshotFile, nativeId);
28003
28102
  const file = zcodeRegistryFile();
28004
- if (!existsSync32(file) && saved === undefined)
28103
+ if (!existsSync31(file) && saved === undefined)
28005
28104
  return;
28006
- const live = existsSync32(file) ? JSON.parse(readFileSync34(file, "utf8")) : { version: 1, plugins: [] };
28105
+ const live = existsSync31(file) ? JSON.parse(readFileSync34(file, "utf8")) : { version: 1, plugins: [] };
28007
28106
  if (!isObject4(live) || !Array.isArray(live["plugins"]))
28008
28107
  throw new Error(`Official ZCode registry is unsupported: ${file}`);
28009
28108
  const plugins = live["plugins"].filter((row) => !isObject4(row) || row["id"] !== nativeId);
@@ -28023,8 +28122,8 @@ function configSection(config, key) {
28023
28122
  }
28024
28123
  function restorePluginConfig(nativeId, snapshotFile) {
28025
28124
  const file = join40(zcodeCliConfigRoot(), "config.json");
28026
- const snapshot = existsSync32(snapshotFile) ? readConfigObjectFrom(snapshotFile) : null;
28027
- const live = existsSync32(file) ? readConfigObject() : {};
28125
+ const snapshot = existsSync31(snapshotFile) ? readConfigObjectFrom(snapshotFile) : null;
28126
+ const live = existsSync31(file) ? readConfigObject() : {};
28028
28127
  if (live === null)
28029
28128
  throw new Error(`Official ZCode config is unsupported: ${file}`);
28030
28129
  const savedPlugins = snapshot !== null && isObject4(snapshot["plugins"]) ? snapshot["plugins"] : undefined;
@@ -28067,7 +28166,7 @@ function stageLayout(stagingRoot) {
28067
28166
  return { marketStage, resourcesStage: join40(dirname19(marketStage), "resources") };
28068
28167
  }
28069
28168
  function recordTree(dir, name, path) {
28070
- const existed = existsSync32(path);
28169
+ const existed = existsSync31(path);
28071
28170
  writeFileSync16(join40(dir, `${name}-path.txt`), path);
28072
28171
  writeFileSync16(join40(dir, `${name}-existed.txt`), existed ? "1" : "0");
28073
28172
  if (existed)
@@ -28078,7 +28177,7 @@ function knownMarketplacesFile() {
28078
28177
  }
28079
28178
  function readKnownMarketplaces() {
28080
28179
  const file = knownMarketplacesFile();
28081
- if (!existsSync32(file))
28180
+ if (!existsSync31(file))
28082
28181
  return {};
28083
28182
  const value = JSON.parse(readFileSync34(file, "utf8"));
28084
28183
  if (!isObject4(value))
@@ -28097,7 +28196,7 @@ function writeKnownMarketplaces(markets) {
28097
28196
  }
28098
28197
  function recordMarketplaceEntry(dir, market) {
28099
28198
  const flag = join40(dir, "marketplace-entry.txt");
28100
- if (existsSync32(flag))
28199
+ if (existsSync31(flag))
28101
28200
  return;
28102
28201
  const markets = readKnownMarketplaces();
28103
28202
  const present = Object.hasOwn(markets, market);
@@ -28107,7 +28206,7 @@ function recordMarketplaceEntry(dir, market) {
28107
28206
  }
28108
28207
  function restoreMarketplaceEntry(dir, market) {
28109
28208
  const flag = join40(dir, "marketplace-entry.txt");
28110
- if (!existsSync32(flag))
28209
+ if (!existsSync31(flag))
28111
28210
  return;
28112
28211
  const markets = readKnownMarketplaces();
28113
28212
  if (readFileSync34(flag, "utf8") !== "1") {
@@ -28118,7 +28217,7 @@ function restoreMarketplaceEntry(dir, market) {
28118
28217
  return;
28119
28218
  }
28120
28219
  const savedFile = join40(dir, "marketplace-entry.json");
28121
- if (!existsSync32(savedFile))
28220
+ if (!existsSync31(savedFile))
28122
28221
  throw new Error("ZCode rollback marketplace entry is missing");
28123
28222
  const saved = JSON.parse(readFileSync34(savedFile, "utf8"));
28124
28223
  markets[market] = saved;
@@ -28126,9 +28225,9 @@ function restoreMarketplaceEntry(dir, market) {
28126
28225
  }
28127
28226
  function activationSnapshot(attemptId, operationId, nativeId, marketplace, resources) {
28128
28227
  const dir = retirementSnapshot(attemptId, operationId, nativeId);
28129
- if (!existsSync32(join40(dir, "marketplace-path.txt")))
28228
+ if (!existsSync31(join40(dir, "marketplace-path.txt")))
28130
28229
  recordTree(dir, "marketplace", marketplace);
28131
- if (!existsSync32(join40(dir, "resources-path.txt")))
28230
+ if (!existsSync31(join40(dir, "resources-path.txt")))
28132
28231
  recordTree(dir, "resources", resources);
28133
28232
  recordMarketplaceEntry(dir, marketplaceName2(nativeId));
28134
28233
  return dir;
@@ -28136,7 +28235,7 @@ function activationSnapshot(attemptId, operationId, nativeId, marketplace, resou
28136
28235
  function restoreRecordedTree(dir, name, ownedRoot) {
28137
28236
  const pathFile = join40(dir, `${name}-path.txt`);
28138
28237
  const existedFile = join40(dir, `${name}-existed.txt`);
28139
- if (!existsSync32(pathFile) || !existsSync32(existedFile))
28238
+ if (!existsSync31(pathFile) || !existsSync31(existedFile))
28140
28239
  return;
28141
28240
  const path = readFileSync34(pathFile, "utf8");
28142
28241
  const existed = readFileSync34(existedFile, "utf8") === "1";
@@ -28147,9 +28246,9 @@ function restoreRecordedTree(dir, name, ownedRoot) {
28147
28246
  if (!target.startsWith(`${owned}/`))
28148
28247
  throw new Error(`ZCode rollback ${name} path is outside its root`);
28149
28248
  const copy = join40(dir, name);
28150
- if (existed && !existsSync32(copy))
28249
+ if (existed && !existsSync31(copy))
28151
28250
  throw new Error(`ZCode rollback ${name} copy is missing`);
28152
- if (!existed && existsSync32(copy))
28251
+ if (!existed && existsSync31(copy))
28153
28252
  throw new Error(`ZCode rollback ${name} copy has no path`);
28154
28253
  rmSync16(target, { recursive: true, force: true });
28155
28254
  if (!existed)
@@ -28219,7 +28318,7 @@ var zcodeCliLifecycleDefinition = {
28219
28318
  const resourceRoot = join40(realpathSync6(zcodeCliRoot()), "plgnz-resources", market, snapshot.packageFingerprint);
28220
28319
  const stageParent = join40(zcodeCliRoot(), ".plgnz-zcode-stage");
28221
28320
  mkdirSync16(stageParent, { recursive: true });
28222
- if (lstatSync25(stageParent).isSymbolicLink())
28321
+ if (lstatSync26(stageParent).isSymbolicLink())
28223
28322
  throw new Error("ZCode staging parent is redirected");
28224
28323
  const stage = activationStage(request.selection.attemptId, request.selection.operationId);
28225
28324
  mkdirSync16(stage);
@@ -28311,7 +28410,7 @@ var zcodeCliLifecycleDefinition = {
28311
28410
  const resourceRoot = marker.resourcePath;
28312
28411
  const prior = nativeById(nativeId);
28313
28412
  const priorRoot = prior === undefined ? undefined : zcodeSafeInstallRoot(prior.installPath);
28314
- const unchanged = prior !== undefined && priorRoot !== undefined && prior.version === nativeVersion && readZcodeEnabledPluginIds().get(nativeId) === true && fingerprintTree(priorRoot) === fingerprintTree(prepared.stagingRoot) && existsSync32(resourceRoot) && fingerprintTree(resourceRoot) === fingerprintTree(resourcesStage);
28413
+ const unchanged = prior !== undefined && priorRoot !== undefined && prior.version === nativeVersion && readZcodeEnabledPluginIds().get(nativeId) === true && fingerprintTree(priorRoot) === fingerprintTree(prepared.stagingRoot) && existsSync31(resourceRoot) && fingerprintTree(resourceRoot) === fingerprintTree(resourcesStage);
28315
28414
  if (unchanged)
28316
28415
  return { receiptId: `apply:${prepared.handle.attemptId}:${prepared.handle.operationId}`, changed: false };
28317
28416
  const marketBackup = moveAside4(marketRoot);
@@ -28364,11 +28463,11 @@ var zcodeCliLifecycleDefinition = {
28364
28463
  rollback: async (handle) => {
28365
28464
  capturedNativeRoot(handle.rollbackReference, handle.attemptId, handle.operationId);
28366
28465
  const dir = handle.rollbackReference;
28367
- if (!existsSync32(dir) || !statSync13(dir).isDirectory())
28466
+ if (!existsSync31(dir) || !statSync13(dir).isDirectory())
28368
28467
  throw new Error("ZCode rollback snapshot is missing");
28369
- const installPath = existsSync32(join40(dir, "install-path.txt")) ? readFileSync34(join40(dir, "install-path.txt"), "utf8") : "";
28468
+ const installPath = existsSync31(join40(dir, "install-path.txt")) ? readFileSync34(join40(dir, "install-path.txt"), "utf8") : "";
28370
28469
  const cache = join40(dir, "cache");
28371
- const cachePresent = existsSync32(cache);
28470
+ const cachePresent = existsSync31(cache);
28372
28471
  if (installPath.length > 0 && !cachePresent)
28373
28472
  throw new Error("ZCode rollback cache copy is missing");
28374
28473
  if (installPath.length === 0 && cachePresent)
@@ -28406,7 +28505,7 @@ var zcodeCliLifecycleDefinition = {
28406
28505
  const parent = join40(realpathSync6(zcodeCliRoot()), "plgnz-lifecycle");
28407
28506
  for (const candidate of [parent, join40(parent, reference.attemptId), join40(parent, reference.attemptId, reference.operationId)]) {
28408
28507
  try {
28409
- const stat = lstatSync25(candidate);
28508
+ const stat = lstatSync26(candidate);
28410
28509
  if (stat.isSymbolicLink() || candidate === join40(parent, reference.attemptId, reference.operationId))
28411
28510
  throw new Error("ZCode pre-seal cleanup has no captured snapshot authority");
28412
28511
  } catch (error) {
@@ -28416,7 +28515,7 @@ var zcodeCliLifecycleDefinition = {
28416
28515
  }
28417
28516
  }
28418
28517
  try {
28419
- if (lstatSync25(dirname19(stage)).isSymbolicLink())
28518
+ if (lstatSync26(dirname19(stage)).isSymbolicLink())
28420
28519
  throw new Error("ZCode cleanup staging parent is redirected");
28421
28520
  } catch (error) {
28422
28521
  if (!isObject4(error) || error["code"] !== "ENOENT")
@@ -28424,7 +28523,7 @@ var zcodeCliLifecycleDefinition = {
28424
28523
  }
28425
28524
  let stagePresent = true;
28426
28525
  try {
28427
- lstatSync25(stage);
28526
+ lstatSync26(stage);
28428
28527
  } catch (error) {
28429
28528
  if (!isObject4(error) || error["code"] !== "ENOENT")
28430
28529
  throw error;
@@ -28442,7 +28541,7 @@ var zcodeCliLifecycleDefinition = {
28442
28541
  var zcodeCliLifecycle = createLifecycleHostAdapter(zcodeCliLifecycleDefinition);
28443
28542
 
28444
28543
  // src/hosts/hermes-writer.ts
28445
- import { chmodSync as chmodSync4, cpSync as cpSync15, existsSync as existsSync33, lstatSync as lstatSync26, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync16, readFileSync as readFileSync35, readdirSync as readdirSync25, realpathSync as realpathSync7, renameSync as renameSync14, rmSync as rmSync17, statSync as statSync14, writeFileSync as writeFileSync17 } from "node:fs";
28544
+ import { chmodSync as chmodSync4, cpSync as cpSync15, existsSync as existsSync32, lstatSync as lstatSync27, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync16, readFileSync as readFileSync35, readdirSync as readdirSync25, realpathSync as realpathSync7, renameSync as renameSync14, rmSync as rmSync17, statSync as statSync14, writeFileSync as writeFileSync17 } from "node:fs";
28446
28545
  import { basename as basename8, dirname as dirname20, isAbsolute as isAbsolute12, join as join41, resolve as resolve27 } from "node:path";
28447
28546
  import { tmpdir as tmpdir13 } from "node:os";
28448
28547
 
@@ -28714,12 +28813,12 @@ var hermesWriter = {
28714
28813
  assertReplaceable(target, packageStage, id, ownershipId, resolved.sourceUri, opts?.adoptExisting === true, validatePackage);
28715
28814
  if (hasCompanion)
28716
28815
  assertReplaceable(companion, companionStage, companionId, ownershipId, resolved.sourceUri, opts?.adoptExisting === true, validateCompanion);
28717
- else if (existsSync33(companion))
28816
+ else if (existsSync32(companion))
28718
28817
  assertReplaceable(companion, undefined, companionId, ownershipId, resolved.sourceUri, opts?.adoptExisting === true, validateCompanion);
28719
28818
  const primaryMarker = readOwnership5(target);
28720
28819
  const companionMarker = readOwnership5(companion);
28721
28820
  const unchangedPrimary = primaryMarker?.pluginId === ownershipId && primaryMarker.fingerprint === ownership.fingerprint && sameTree9(packageStage, target);
28722
- const unchangedCompanion = hasCompanion ? companionMarker?.pluginId === ownershipId && companionMarker.fingerprint === ownership.fingerprint && sameTree9(companionStage, companion) : !existsSync33(companion);
28821
+ const unchangedCompanion = hasCompanion ? companionMarker?.pluginId === ownershipId && companionMarker.fingerprint === ownership.fingerprint && sameTree9(companionStage, companion) : !existsSync32(companion);
28723
28822
  if (opts?.dryRun)
28724
28823
  return unchangedPrimary && unchangedCompanion ? "unchanged" : undefined;
28725
28824
  if (unchangedPrimary && unchangedCompanion) {
@@ -28731,7 +28830,7 @@ var hermesWriter = {
28731
28830
  changes.push(replaceTarget(packageStage, target, root));
28732
28831
  if (hasCompanion)
28733
28832
  changes.push(replaceTarget(companionStage, companion, root));
28734
- else if (existsSync33(companion))
28833
+ else if (existsSync32(companion))
28735
28834
  changes.push(removeTarget(companion, root));
28736
28835
  updatePluginConfig(effectiveConfigPath(), [id, ...hasCompanion ? [companionId] : []], hasCompanion ? [] : [companionId]);
28737
28836
  for (const change of changes)
@@ -28763,14 +28862,14 @@ var hermesWriter = {
28763
28862
  return;
28764
28863
  const changes = [];
28765
28864
  try {
28766
- if (existsSync33(target))
28865
+ if (existsSync32(target))
28767
28866
  changes.push(removeTarget(target, root));
28768
28867
  const companionMarker = readOwnership5(companion);
28769
28868
  const disable = [nativeId];
28770
28869
  if (companionMarker !== null && companionMarker.pluginId === marker.pluginId && companionMarker.source === marker.source && companionMarker.fingerprint === marker.fingerprint) {
28771
28870
  changes.push(removeTarget(companion, root));
28772
28871
  disable.push(companionId);
28773
- } else if (!existsSync33(companion))
28872
+ } else if (!existsSync32(companion))
28774
28873
  disable.push(companionId);
28775
28874
  updatePluginConfig(effectiveConfigPath(), [], disable);
28776
28875
  for (const change of changes)
@@ -28783,7 +28882,7 @@ var hermesWriter = {
28783
28882
  }
28784
28883
  };
28785
28884
  function assertReplaceable(target, stage, expected, ownershipId, source, adopt, validate) {
28786
- if (!existsSync33(target))
28885
+ if (!existsSync32(target))
28787
28886
  return;
28788
28887
  const marker = readOwnership5(target);
28789
28888
  if (marker !== null) {
@@ -28801,7 +28900,7 @@ function assertReplaceable(target, stage, expected, ownershipId, source, adopt,
28801
28900
  function validatePackage(root, expected) {
28802
28901
  assertTree3(root);
28803
28902
  const manifest = join41(root, "plugin.json");
28804
- if (!existsSync33(manifest))
28903
+ if (!existsSync32(manifest))
28805
28904
  throw new Error("Hermes stage has no Agent Plugins manifest");
28806
28905
  let value;
28807
28906
  try {
@@ -28817,7 +28916,7 @@ function validatePackage(root, expected) {
28817
28916
  function validateCompanion(root, expected) {
28818
28917
  assertTree3(root);
28819
28918
  const manifest = join41(root, "plugin.yaml");
28820
- if (!existsSync33(manifest) || !existsSync33(join41(root, "__init__.py")))
28919
+ if (!existsSync32(manifest) || !existsSync32(join41(root, "__init__.py")))
28821
28920
  throw new Error(`Hermes native companion is incomplete: ${root}`);
28822
28921
  const value = yamlParse(readFileSync35(manifest, "utf8"));
28823
28922
  if (!value || typeof value !== "object" || Array.isArray(value) || value.name !== expected)
@@ -28825,7 +28924,7 @@ function validateCompanion(root, expected) {
28825
28924
  }
28826
28925
  function readOwnership5(target) {
28827
28926
  const file = join41(target, MARKER11);
28828
- if (!existsSync33(file))
28927
+ if (!existsSync32(file))
28829
28928
  return null;
28830
28929
  try {
28831
28930
  const value = JSON.parse(readFileSync35(file, "utf8"));
@@ -28840,7 +28939,7 @@ function readOwnership5(target) {
28840
28939
  }
28841
28940
  }
28842
28941
  function replaceTarget(stage, target, root) {
28843
- if (!existsSync33(target)) {
28942
+ if (!existsSync32(target)) {
28844
28943
  renameSync14(stage, target);
28845
28944
  return { commit: () => {}, rollback: () => rmSync17(target, { recursive: true, force: true }) };
28846
28945
  }
@@ -28865,14 +28964,14 @@ function removeTarget(target, root) {
28865
28964
  const backup = join41(backupRoot, "previous");
28866
28965
  renameSync14(target, backup);
28867
28966
  return { commit: () => rmSync17(backupRoot, { recursive: true, force: true }), rollback: () => {
28868
- if (!existsSync33(target))
28967
+ if (!existsSync32(target))
28869
28968
  renameSync14(backup, target);
28870
28969
  rmSync17(backupRoot, { recursive: true, force: true });
28871
28970
  } };
28872
28971
  }
28873
28972
  function updatePluginConfig(configured, enable, disable) {
28874
- const actual = existsSync33(configured) && lstatSync26(configured).isSymbolicLink() ? realpathSync7(configured) : configured;
28875
- const exists = existsSync33(actual);
28973
+ const actual = existsSync32(configured) && lstatSync27(configured).isSymbolicLink() ? realpathSync7(configured) : configured;
28974
+ const exists = existsSync32(actual);
28876
28975
  const original = exists ? readFileSync35(actual, "utf8") : "";
28877
28976
  let parsed = {};
28878
28977
  if (original.trim() !== "") {
@@ -28930,7 +29029,7 @@ function effectiveConfigPath() {
28930
29029
  const configured = resolve27(hermesConfigPath());
28931
29030
  if (native === configured)
28932
29031
  return configured;
28933
- if (!existsSync33(native) || !existsSync33(configured))
29032
+ if (!existsSync32(native) || !existsSync32(configured))
28934
29033
  throw new Error(`Hermes only reads ${native}; configured path ${configured} must already resolve to the same file`);
28935
29034
  const nativeReal = realpathSync7(native);
28936
29035
  const configuredReal = realpathSync7(configured);
@@ -28939,7 +29038,7 @@ function effectiveConfigPath() {
28939
29038
  throw new Error(`Hermes only reads ${native}; configured path ${configured} is a different file`);
28940
29039
  }
28941
29040
  function sameTree9(left, right) {
28942
- if (!existsSync33(right))
29041
+ if (!existsSync32(right))
28943
29042
  return false;
28944
29043
  const list = (root) => {
28945
29044
  const out = [];
@@ -28947,7 +29046,7 @@ function sameTree9(left, right) {
28947
29046
  for (const name of readdirSync25(dir).sort()) {
28948
29047
  if (name === MARKER11)
28949
29048
  continue;
28950
- const path = join41(dir, name), relative = prefix ? `${prefix}/${name}` : name, stat = lstatSync26(path);
29049
+ const path = join41(dir, name), relative = prefix ? `${prefix}/${name}` : name, stat = lstatSync27(path);
28951
29050
  if (stat.isSymbolicLink())
28952
29051
  throw new Error(`Hermes plugin contains symlink: ${path}`);
28953
29052
  if (stat.isDirectory())
@@ -28967,13 +29066,13 @@ function readBytes2(path) {
28967
29066
  return readFileSync35(path);
28968
29067
  }
28969
29068
  function assertTree3(root) {
28970
- const stat = lstatSync26(root);
29069
+ const stat = lstatSync27(root);
28971
29070
  if (stat.isSymbolicLink() || !stat.isDirectory())
28972
29071
  throw new Error(`Hermes plugin source is not a real directory: ${root}`);
28973
29072
  for (const name of readdirSync25(root)) {
28974
29073
  if (name === MARKER11)
28975
29074
  continue;
28976
- const path = join41(root, name), entry = lstatSync26(path);
29075
+ const path = join41(root, name), entry = lstatSync27(path);
28977
29076
  if (entry.isSymbolicLink())
28978
29077
  throw new Error(`Hermes plugin contains symlink: ${path}`);
28979
29078
  if (entry.isDirectory())
@@ -28988,15 +29087,15 @@ function assertManagedPath5(root, target) {
28988
29087
  throw new Error(`Hermes managed path escapes its store: ${target}`);
28989
29088
  let current = base;
28990
29089
  for (const part of selected.slice(base.length).split("/").filter(Boolean)) {
28991
- if (existsSync33(current)) {
28992
- const stat = lstatSync26(current);
29090
+ if (existsSync32(current)) {
29091
+ const stat = lstatSync27(current);
28993
29092
  if (stat.isSymbolicLink() || !stat.isDirectory())
28994
29093
  throw new Error(`Hermes managed path component is unsafe: ${current}`);
28995
29094
  }
28996
29095
  current = join41(current, part);
28997
29096
  }
28998
- if (existsSync33(current)) {
28999
- const stat = lstatSync26(current);
29097
+ if (existsSync32(current)) {
29098
+ const stat = lstatSync27(current);
29000
29099
  if (stat.isSymbolicLink() || !stat.isDirectory())
29001
29100
  throw new Error(`Hermes managed path component is unsafe: ${current}`);
29002
29101
  }
@@ -29144,7 +29243,7 @@ function verifiedSourceImportClosure(root) {
29144
29243
  if (entry.startsWith(".") || entry === "__pycache__" || entry === "node_modules")
29145
29244
  continue;
29146
29245
  const path = join41(directory, entry);
29147
- const stat = lstatSync26(path);
29246
+ const stat = lstatSync27(path);
29148
29247
  if (stat.isSymbolicLink()) {
29149
29248
  if (entry.endsWith(".py") || statSync14(path).isDirectory())
29150
29249
  return false;
@@ -29156,7 +29255,7 @@ function verifiedSourceImportClosure(root) {
29156
29255
  return visit(root, true);
29157
29256
  }
29158
29257
  function hermesExecutableSource(binary, depth = 0) {
29159
- if (depth > 4 || !isAbsolute12(binary) || !existsSync33(binary))
29258
+ if (depth > 4 || !isAbsolute12(binary) || !existsSync32(binary))
29160
29259
  return;
29161
29260
  const executable = realpathSync7(binary);
29162
29261
  if (!statSync14(executable).isFile())
@@ -29168,7 +29267,7 @@ exec `)) {
29168
29267
  exec `.length));
29169
29268
  if (args?.length === 2 && args[1] === "$@")
29170
29269
  return hermesExecutableSource(args[0], depth + 1);
29171
- if (args?.length !== 5 || args[1] !== "-I" || args[2] !== "-c" || args[4] !== "$@" || !isAbsolute12(args[0]) || !/^python(?:\d+(?:\.\d+)*)?$/u.test(basename8(args[0])) || !existsSync33(args[0]))
29270
+ if (args?.length !== 5 || args[1] !== "-I" || args[2] !== "-c" || args[4] !== "$@" || !isAbsolute12(args[0]) || !/^python(?:\d+(?:\.\d+)*)?$/u.test(basename8(args[0])) || !existsSync32(args[0]))
29172
29271
  return;
29173
29272
  const code = args[3];
29174
29273
  if (!code.startsWith(`import os, re, sys
@@ -29180,26 +29279,26 @@ exec `.length));
29180
29279
  const root = literalPythonPath(bindings[0][1]);
29181
29280
  if (root === undefined || code.replaceAll(bindings[0][1], "'/__PLUGNZ_HERMES_ROOT__'") !== hermesNativeBootstrap)
29182
29281
  return;
29183
- return root !== undefined && isAbsolute12(root) && existsSync33(join41(root, "hermes_cli", "main.py")) && realpathSync7(join41(root, "hermes_cli", "main.py")).startsWith(`${realpathSync7(root)}/`) && verifiedSourceImportClosure(realpathSync7(root)) ? realpathSync7(root) : undefined;
29282
+ return root !== undefined && isAbsolute12(root) && existsSync32(join41(root, "hermes_cli", "main.py")) && realpathSync7(join41(root, "hermes_cli", "main.py")).startsWith(`${realpathSync7(root)}/`) && verifiedSourceImportClosure(realpathSync7(root)) ? realpathSync7(root) : undefined;
29184
29283
  }
29185
29284
  const interpreter = /^#!([^\n]+)\n/u.exec(text)?.[1];
29186
- if (interpreter === undefined || !isAbsolute12(interpreter) || !existsSync33(interpreter) || !/^python(?:\d+(?:\.\d+)*)?$/u.test(basename8(interpreter)) || text.slice(text.indexOf(`
29285
+ if (interpreter === undefined || !isAbsolute12(interpreter) || !existsSync32(interpreter) || !/^python(?:\d+(?:\.\d+)*)?$/u.test(basename8(interpreter)) || text.slice(text.indexOf(`
29187
29286
  `) + 1) !== hermesUvConsoleBody)
29188
29287
  return;
29189
29288
  const venv = dirname20(dirname20(executable));
29190
- if (dirname20(interpreter) !== join41(venv, "bin") || !existsSync33(join41(venv, "pyvenv.cfg")))
29289
+ if (dirname20(interpreter) !== join41(venv, "bin") || !existsSync32(join41(venv, "pyvenv.cfg")))
29191
29290
  return;
29192
- if (existsSync33(join41(venv, "bin", "pyvenv.cfg")) || !isolatedVenvConfig(readFileSync35(join41(venv, "pyvenv.cfg"), "utf8")) || process.env["PYTHONHOME"] || process.env["PYTHONPATH"])
29291
+ if (existsSync32(join41(venv, "bin", "pyvenv.cfg")) || !isolatedVenvConfig(readFileSync35(join41(venv, "pyvenv.cfg"), "utf8")) || process.env["PYTHONHOME"] || process.env["PYTHONPATH"])
29193
29292
  return;
29194
29293
  if (hasImportShadow(join41(venv, "bin"), ["hermes_cli", "sitecustomize", "usercustomize", "_virtualenv"]))
29195
29294
  return;
29196
29295
  const lib = join41(venv, "lib");
29197
- if (!existsSync33(lib))
29296
+ if (!existsSync32(lib))
29198
29297
  return;
29199
29298
  const roots = [];
29200
29299
  for (const python of readdirSync25(lib).filter((name) => /^python\d+\.\d+$/u.test(name))) {
29201
29300
  const packages = join41(lib, python, "site-packages");
29202
- if (!existsSync33(packages))
29301
+ if (!existsSync32(packages))
29203
29302
  continue;
29204
29303
  if (hasImportShadow(packages, ["hermes_cli", "sitecustomize", "usercustomize", "_virtualenv"], ["_virtualenv.py"]))
29205
29304
  return;
@@ -29207,13 +29306,13 @@ exec `.length));
29207
29306
  const distribution = join41(packages, name);
29208
29307
  const metadata = join41(distribution, "direct_url.json");
29209
29308
  const entry = join41(distribution, "entry_points.txt");
29210
- if (!existsSync33(metadata) || !existsSync33(entry) || !/^hermes\s*=\s*hermes_cli\.main:main$/mu.test(readFileSync35(entry, "utf8")))
29309
+ if (!existsSync32(metadata) || !existsSync32(entry) || !/^hermes\s*=\s*hermes_cli\.main:main$/mu.test(readFileSync35(entry, "utf8")))
29211
29310
  continue;
29212
29311
  const direct = JSON.parse(readFileSync35(metadata, "utf8"));
29213
29312
  if (typeof direct !== "object" || direct === null || !("url" in direct) || typeof direct.url !== "string" || !("dir_info" in direct) || typeof direct.dir_info !== "object" || direct.dir_info === null || !("editable" in direct.dir_info) || direct.dir_info.editable !== true || !direct.url.startsWith("file:///"))
29214
29313
  continue;
29215
29314
  const root = decodeURIComponent(direct.url.slice("file://".length));
29216
- if (!isAbsolute12(root) || !existsSync33(join41(root, "hermes_cli", "main.py")))
29315
+ if (!isAbsolute12(root) || !existsSync32(join41(root, "hermes_cli", "main.py")))
29217
29316
  continue;
29218
29317
  const sourceModules = [
29219
29318
  "hermes_cli",
@@ -29221,7 +29320,7 @@ exec `.length));
29221
29320
  "hermes_constants",
29222
29321
  "pm",
29223
29322
  ...readdirSync25(root).filter((name) => name.endsWith(".py")).map((name) => name.slice(0, -3)),
29224
- ...readdirSync25(root).filter((name) => existsSync33(join41(root, name, "__init__.py")))
29323
+ ...readdirSync25(root).filter((name) => existsSync32(join41(root, name, "__init__.py")))
29225
29324
  ];
29226
29325
  if (hasImportShadow(packages, sourceModules) || hasImportShadow(join41(venv, "bin"), sourceModules))
29227
29326
  return;
@@ -29236,11 +29335,11 @@ exec `.length));
29236
29335
  const pth = readFileSync35(join41(packages, pthName), "utf8").trim();
29237
29336
  if (pthName === `_virtualenv.pth` && pth === "import _virtualenv") {
29238
29337
  const helper = join41(packages, "_virtualenv.py");
29239
- if (!existsSync33(helper) || new CryptoHasher("sha256").update(readFileSync35(helper, "utf8")).digest("hex") !== "cfb3db86aaa53bb62b5ff764970bec2d71c9228590a0ebec57f6ec926cc0bf1a")
29338
+ if (!existsSync32(helper) || new CryptoHasher("sha256").update(readFileSync35(helper, "utf8")).digest("hex") !== "cfb3db86aaa53bb62b5ff764970bec2d71c9228590a0ebec57f6ec926cc0bf1a")
29240
29339
  return;
29241
29340
  } else if (pthName === `__editable__.hermes_agent-${version}.pth` && pth === root)
29242
29341
  binding = true;
29243
- else if (pthName === `__editable__.hermes_agent-${version}.pth` && pth === `import ${finder}; ${finder}.install()` && existsSync33(join41(packages, `${finder}.py`)) && verifiedEditableFinder(readFileSync35(join41(packages, `${finder}.py`), "utf8"), root, version))
29342
+ else if (pthName === `__editable__.hermes_agent-${version}.pth` && pth === `import ${finder}; ${finder}.install()` && existsSync32(join41(packages, `${finder}.py`)) && verifiedEditableFinder(readFileSync35(join41(packages, `${finder}.py`), "utf8"), root, version))
29244
29343
  binding = true;
29245
29344
  else
29246
29345
  return;
@@ -29253,7 +29352,7 @@ exec `.length));
29253
29352
  }
29254
29353
  function observeHermesRevision() {
29255
29354
  const binary = process.env["OPEN_PLUGIN_HERMES_BIN"] ?? which("hermes");
29256
- if (!binary || !existsSync33(binary))
29355
+ if (!binary || !existsSync32(binary))
29257
29356
  return { kind: "unknown", diagnostic: "Select an existing Hermes launcher with OPEN_PLUGIN_HERMES_BIN; a profile config does not identify its runtime" };
29258
29357
  try {
29259
29358
  const root = hermesExecutableSource(binary);
@@ -29327,14 +29426,14 @@ function resolveInstanceConfig(root, configPath) {
29327
29426
  const configured = resolve27(configPath);
29328
29427
  if (native === configured)
29329
29428
  return configured;
29330
- if (!existsSync33(native) || !existsSync33(configured))
29429
+ if (!existsSync32(native) || !existsSync32(configured))
29331
29430
  throw new Error(`Hermes only reads ${native}; configured path ${configured} must already resolve to the same file`);
29332
29431
  if (realpathSync7(native) === realpathSync7(configured))
29333
29432
  return configured;
29334
29433
  throw new Error(`Hermes only reads ${native}; configured path ${configured} is a different file`);
29335
29434
  }
29336
29435
  function actualConfig(configPath) {
29337
- return existsSync33(configPath) && lstatSync26(configPath).isSymbolicLink() ? realpathSync7(configPath) : configPath;
29436
+ return existsSync32(configPath) && lstatSync27(configPath).isSymbolicLink() ? realpathSync7(configPath) : configPath;
29338
29437
  }
29339
29438
  function workDir(store, attemptId, operationId) {
29340
29439
  return join41(store.root, ".plgnz-lifecycle", encodeURIComponent(attemptId), encodeURIComponent(operationId));
@@ -29403,7 +29502,7 @@ function sameLifecycleOwner(marker, claim) {
29403
29502
  return installed !== null && installed.pluginId === claim.pluginId && installed.scopeId === claim.scopeId && installed.sourceType === claim.sourceType && installed.locator === claim.locator;
29404
29503
  }
29405
29504
  function assertLifecycleOwned(target, claim, handle) {
29406
- if (!existsSync33(target))
29505
+ if (!existsSync32(target))
29407
29506
  return;
29408
29507
  const marker = readMarker(target);
29409
29508
  if (marker === null)
@@ -29433,7 +29532,7 @@ function copyReplace(stage, target, root) {
29433
29532
  }
29434
29533
  function flagSet(configPath, key) {
29435
29534
  const actual = actualConfig(configPath);
29436
- if (!existsSync33(actual))
29535
+ if (!existsSync32(actual))
29437
29536
  return new Set;
29438
29537
  const parsed = yamlParse(readFileSync35(actual, "utf8"));
29439
29538
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
@@ -29459,7 +29558,7 @@ function activationMatches(configPath, packageName, companionId, hasCompanion) {
29459
29558
  }
29460
29559
  function entryValue(configPath, packageName) {
29461
29560
  const actual = actualConfig(configPath);
29462
- if (!existsSync33(actual))
29561
+ if (!existsSync32(actual))
29463
29562
  return;
29464
29563
  const parsed = yamlParse(readFileSync35(actual, "utf8"));
29465
29564
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
@@ -29492,7 +29591,7 @@ function sha2563(value) {
29492
29591
  }
29493
29592
  function retentionFor(store, packageName) {
29494
29593
  const dataDir = join41(store.root, "plugin-data", hermesPluginDataNamespace(packageName));
29495
- const pluginData = existsSync33(dataDir) && lstatSync26(dataDir).isDirectory() ? { state: "present", fingerprint: fingerprintTree(dataDir) } : { state: "absent", fingerprint: null };
29594
+ const pluginData = existsSync32(dataDir) && lstatSync27(dataDir).isDirectory() ? { state: "present", fingerprint: fingerprintTree(dataDir) } : { state: "absent", fingerprint: null };
29496
29595
  const entry = entryValue(store.configPath, packageName);
29497
29596
  const inactiveMetadata = entry === undefined ? { state: "absent", fingerprint: null } : { state: "present", fingerprint: sha2563(JSON.stringify(canonicalValue(entry))) };
29498
29597
  return { pluginData, inactiveMetadata };
@@ -29501,7 +29600,7 @@ function atomicFingerprint(packageDir, companionDir) {
29501
29600
  const temp = mkdtempSync16(join41(tmpdir13(), "plgnz-hermes-atomic-"));
29502
29601
  try {
29503
29602
  cpSync15(packageDir, join41(temp, "package"), { recursive: true });
29504
- if (companionDir !== undefined && existsSync33(companionDir))
29603
+ if (companionDir !== undefined && existsSync32(companionDir))
29505
29604
  cpSync15(companionDir, join41(temp, "commands"), { recursive: true });
29506
29605
  return fingerprintTree(temp);
29507
29606
  } finally {
@@ -29510,7 +29609,7 @@ function atomicFingerprint(packageDir, companionDir) {
29510
29609
  }
29511
29610
  function readConfigDocument2(configPath) {
29512
29611
  const actual = actualConfig(configPath);
29513
- if (!existsSync33(actual))
29612
+ if (!existsSync32(actual))
29514
29613
  return null;
29515
29614
  const text = readFileSync35(actual, "utf8");
29516
29615
  if (text.trim() === "")
@@ -29568,7 +29667,7 @@ function membership(list, id, present) {
29568
29667
  }
29569
29668
  function writeConfigDocument(configPath, doc) {
29570
29669
  const actual = actualConfig(configPath);
29571
- const exists = existsSync33(actual);
29670
+ const exists = existsSync32(actual);
29572
29671
  const mode = exists ? statSync14(actual).mode & 511 : null;
29573
29672
  mkdirSync17(dirname20(actual), { recursive: true });
29574
29673
  const temp = join41(dirname20(actual), `.plgnz-hermes-rollback-${Date.now()}-${Math.random().toString(16).slice(2)}.yaml`);
@@ -29616,18 +29715,18 @@ function saveRollback(store, reference, packageName, packageDir, companionDir) {
29616
29715
  mkdirSync17(reference, { recursive: true });
29617
29716
  const companionId = hermesCommandCompanionId(packageName);
29618
29717
  writeFileSync17(join41(reference, "config-slice.json"), JSON.stringify(captureConfigSlice(store.configPath, packageName, companionId)));
29619
- if (existsSync33(packageDir))
29718
+ if (existsSync32(packageDir))
29620
29719
  cpSync15(packageDir, join41(reference, "package"), { recursive: true });
29621
- if (existsSync33(companionDir))
29720
+ if (existsSync32(companionDir))
29622
29721
  cpSync15(companionDir, join41(reference, "commands"), { recursive: true });
29623
29722
  }
29624
29723
  function restoreRollback3(store, reference, packageDir, companionDir) {
29625
29724
  const slice = JSON.parse(readFileSync35(join41(reference, "config-slice.json"), "utf8"));
29626
29725
  rmSync17(packageDir, { recursive: true, force: true });
29627
29726
  rmSync17(companionDir, { recursive: true, force: true });
29628
- if (existsSync33(join41(reference, "package")))
29727
+ if (existsSync32(join41(reference, "package")))
29629
29728
  cpSync15(join41(reference, "package"), packageDir, { recursive: true });
29630
- if (existsSync33(join41(reference, "commands")))
29729
+ if (existsSync32(join41(reference, "commands")))
29631
29730
  cpSync15(join41(reference, "commands"), companionDir, { recursive: true });
29632
29731
  restoreConfigSlice(store.configPath, slice);
29633
29732
  }
@@ -29676,7 +29775,7 @@ var hermesLifecycleDefinition = {
29676
29775
  try {
29677
29776
  const store = storeFor(target);
29678
29777
  const actual = actualConfig(store.configPath);
29679
- if (!existsSync33(actual) || !statSync14(actual).isFile())
29778
+ if (!existsSync32(actual) || !statSync14(actual).isFile())
29680
29779
  return { kind: "unknown" };
29681
29780
  const text = readFileSync35(actual, "utf8");
29682
29781
  if (text.trim() !== "") {
@@ -29759,9 +29858,9 @@ var hermesLifecycleDefinition = {
29759
29858
  const companionStage = join41(stagingRoot, "commands");
29760
29859
  mkdirSync17(packageStage, { recursive: true });
29761
29860
  projectPluginForHermes(request.snapshot.packageRoot, packageStage, companionStage);
29762
- if (existsSync33(companionStage) && readdirSync25(companionStage).length === 0)
29861
+ if (existsSync32(companionStage) && readdirSync25(companionStage).length === 0)
29763
29862
  rmSync17(companionStage, { recursive: true });
29764
- const hasCompanion = existsSync33(companionStage);
29863
+ const hasCompanion = existsSync32(companionStage);
29765
29864
  validatePackage(packageStage, request.snapshot.packageName);
29766
29865
  if (hasCompanion)
29767
29866
  validateCompanion(companionStage, hermesCommandCompanionId(request.snapshot.packageName));
@@ -29785,7 +29884,7 @@ var hermesLifecycleDefinition = {
29785
29884
  if (projection.pins.length === 0)
29786
29885
  return [];
29787
29886
  const mcp = join41(projection.stagingRoot, "package", "mcp.json");
29788
- if (!existsSync33(mcp))
29887
+ if (!existsSync32(mcp))
29789
29888
  throw new Error(`Hermes pin set has no mcp.json: ${mcp}`);
29790
29889
  const value = JSON.parse(readFileSync35(mcp, "utf8"));
29791
29890
  const servers = value.mcpServers ?? {};
@@ -29804,7 +29903,7 @@ var hermesLifecycleDefinition = {
29804
29903
  const paths = packagePaths(store, projection.packageName);
29805
29904
  const prior = withIdentity(inspect(store, projection.nativeId, projection.packageName, "none"), projection.target, projection.scopeId, projection.packageName, projection.nativeId);
29806
29905
  capturePriorSourceRepair(projection, prior.installedFingerprint);
29807
- const hasCompanion = existsSync33(join41(projection.stagingRoot, "commands"));
29906
+ const hasCompanion = existsSync32(join41(projection.stagingRoot, "commands"));
29808
29907
  const contentRoots = [{ label: "package", path: paths.packageDir, fingerprint: fingerprintTree(join41(projection.stagingRoot, "package")) }];
29809
29908
  if (hasCompanion)
29810
29909
  contentRoots.push({ label: "commands", path: paths.companionDir, fingerprint: fingerprintTree(join41(projection.stagingRoot, "commands")) });
@@ -29841,15 +29940,15 @@ var hermesLifecycleDefinition = {
29841
29940
  assertManagedPath5(store.pluginsDir, paths.companionDir);
29842
29941
  const stagedPackage = join41(prepared.stagingRoot, "package");
29843
29942
  const stagedCompanion = join41(prepared.stagingRoot, "commands");
29844
- const hasCompanion = existsSync33(stagedCompanion);
29943
+ const hasCompanion = existsSync32(stagedCompanion);
29845
29944
  const owner = ownerFromHandle(prepared.handle);
29846
29945
  assertLifecycleOwned(paths.packageDir, owner, prepared.handle);
29847
29946
  if (hasCompanion)
29848
29947
  assertLifecycleOwned(paths.companionDir, owner, prepared.handle);
29849
- else if (existsSync33(paths.companionDir))
29948
+ else if (existsSync32(paths.companionDir))
29850
29949
  assertLifecycleOwned(paths.companionDir, owner, prepared.handle);
29851
29950
  mkdirSync17(store.pluginsDir, { recursive: true });
29852
- const unchanged = existsSync33(paths.packageDir) && atomicFingerprint(paths.packageDir, hasCompanion ? paths.companionDir : undefined) === fingerprintTree(prepared.stagingRoot) && activationMatches(store.configPath, prepared.handle.packageName, paths.companionId, hasCompanion);
29951
+ const unchanged = existsSync32(paths.packageDir) && atomicFingerprint(paths.packageDir, hasCompanion ? paths.companionDir : undefined) === fingerprintTree(prepared.stagingRoot) && activationMatches(store.configPath, prepared.handle.packageName, paths.companionId, hasCompanion);
29853
29952
  if (unchanged)
29854
29953
  return { receiptId: `apply:${prepared.handle.attemptId}:${prepared.handle.operationId}`, changed: false };
29855
29954
  const changes = [];
@@ -29857,7 +29956,7 @@ var hermesLifecycleDefinition = {
29857
29956
  changes.push(copyReplace(stagedPackage, paths.packageDir, store.pluginsDir));
29858
29957
  if (hasCompanion)
29859
29958
  changes.push(copyReplace(stagedCompanion, paths.companionDir, store.pluginsDir));
29860
- else if (existsSync33(paths.companionDir))
29959
+ else if (existsSync32(paths.companionDir))
29861
29960
  changes.push(removeTarget(paths.companionDir, store.pluginsDir));
29862
29961
  updatePluginConfig(store.configPath, [prepared.handle.packageName, ...hasCompanion ? [paths.companionId] : []], hasCompanion ? [] : [paths.companionId]);
29863
29962
  for (const change of changes)
@@ -29883,11 +29982,11 @@ var hermesLifecycleDefinition = {
29883
29982
  const source = prepared.handle.sourceLocator ?? prepared.handle.sourceRevision;
29884
29983
  const changes = [];
29885
29984
  try {
29886
- if (existsSync33(paths.packageDir)) {
29985
+ if (existsSync32(paths.packageDir)) {
29887
29986
  assertLifecycleOwned(paths.packageDir, ownerFromHandle(prepared.handle));
29888
29987
  changes.push(removeTarget(paths.packageDir, store.pluginsDir));
29889
29988
  }
29890
- if (existsSync33(paths.companionDir)) {
29989
+ if (existsSync32(paths.companionDir)) {
29891
29990
  const marker = readMarker(paths.companionDir);
29892
29991
  if (marker !== null && marker.pluginId === prepared.handle.nativeId && marker.source === source)
29893
29992
  changes.push(removeTarget(paths.companionDir, store.pluginsDir));
@@ -30234,7 +30333,7 @@ function invalidSelection2(diagnostic) {
30234
30333
  }
30235
30334
 
30236
30335
  // src/recorded-pins.ts
30237
- import { existsSync as existsSync34, readFileSync as readFileSync36 } from "node:fs";
30336
+ import { existsSync as existsSync33, readFileSync as readFileSync36 } from "node:fs";
30238
30337
  import { isAbsolute as isAbsolute13, join as join42, resolve as resolve28 } from "node:path";
30239
30338
  function resolveRecordedPinExecutables(packageRoot, servers) {
30240
30339
  const pins = [];
@@ -30257,7 +30356,7 @@ function resolveRecordedPinExecutables(packageRoot, servers) {
30257
30356
  function recordedPinCommand(packageRoot, server) {
30258
30357
  for (const name of [".mcp.json", "mcp.json"]) {
30259
30358
  const file = join42(packageRoot, name);
30260
- if (!existsSync34(file))
30359
+ if (!existsSync33(file))
30261
30360
  continue;
30262
30361
  let parsed;
30263
30362
  try {
@@ -31434,6 +31533,14 @@ function writeState(records, file = stateFile()) {
31434
31533
  validateLegacyInstallRecords(records);
31435
31534
  atomicWrite(file, JSON.stringify({ version: 1, installs: records }, null, 2));
31436
31535
  }
31536
+ function writeInstallLedger(records, changed, binding) {
31537
+ const loaded = readLifecycleState();
31538
+ if (loaded.sourceVersion !== 2) {
31539
+ writeState(records);
31540
+ return;
31541
+ }
31542
+ writeLifecycleState(withLegacyWriterRecord(loaded.state, changed, binding), { globalPreflight: "succeeded" });
31543
+ }
31437
31544
  function withLegacyWriterRecord(state, record, binding) {
31438
31545
  const source = persistedSource(binding);
31439
31546
  const scope = createDeploymentScopeIdentity(source, { kind: record.host, instance: "default" });
@@ -33446,6 +33553,9 @@ function selectTargets(all, options) {
33446
33553
  return defaultPinTargets(all);
33447
33554
  }
33448
33555
 
33556
+ // src/update.ts
33557
+ init_compatibility();
33558
+
33449
33559
  // src/native-identity.ts
33450
33560
  function captureNativeIdentity(writer, plugin) {
33451
33561
  let nativeId = null;
@@ -33497,7 +33607,12 @@ function shortSha2(sha) {
33497
33607
  async function runUpdate(name, options = {}) {
33498
33608
  const hosts = options.writers ?? writers;
33499
33609
  let state = options.state ?? readState();
33500
- const save = options.writeState ?? writeState;
33610
+ const save = (records, changed, binding) => {
33611
+ if (options.writeState !== undefined)
33612
+ options.writeState(records);
33613
+ else
33614
+ writeInstallLedger(records, changed, binding);
33615
+ };
33501
33616
  const prefix = options.dryRun === true ? "[dry-run] " : "";
33502
33617
  const findings = [];
33503
33618
  let mutationStarted = false;
@@ -33626,7 +33741,7 @@ async function runUpdate(name, options = {}) {
33626
33741
  const pending = { ...record, pending: "install" };
33627
33742
  record = pending;
33628
33743
  const next = state.map((candidate) => candidate === persistedRecord ? pending : candidate);
33629
- save(next);
33744
+ save(next, pending, resolved.snapshot.binding);
33630
33745
  state = next;
33631
33746
  recordMutationStarted = true;
33632
33747
  mutationStarted = true;
@@ -33713,7 +33828,7 @@ async function runUpdate(name, options = {}) {
33713
33828
  delete finalized.pending;
33714
33829
  const next = state.map((candidate) => candidate === record ? finalized : candidate);
33715
33830
  try {
33716
- save(next);
33831
+ save(next, finalized, resolved.snapshot.binding);
33717
33832
  } catch (error) {
33718
33833
  findings.push(findingFor(record, {
33719
33834
  mark: "✗",
@@ -33847,6 +33962,9 @@ function findConsumerProfile(id) {
33847
33962
  return byId.get(id);
33848
33963
  }
33849
33964
 
33965
+ // src/cli.ts
33966
+ init_compatibility();
33967
+
33850
33968
  // src/legacy-install-outcome.ts
33851
33969
  function serializeLegacyInstallOutcomes(report) {
33852
33970
  const rows = report.outcomes.map((outcome) => ({
@@ -33903,7 +34021,7 @@ function legacyCommandAction(command) {
33903
34021
  // package.json
33904
34022
  var package_default = {
33905
34023
  name: "plugnz",
33906
- version: "0.0.22",
34024
+ version: "0.0.24",
33907
34025
  description: "Install, diagnose and update agent plugins (Agent Plugins spec) and MCP configs across Claude Code, Codex, Cursor, Kimi and more",
33908
34026
  license: "MIT",
33909
34027
  type: "module",
@@ -34361,6 +34479,10 @@ function printReport(report, mode) {
34361
34479
  const legacy = serializeLegacyInstallOutcomes(report);
34362
34480
  for (const item of legacy)
34363
34481
  console.log(`${item.target} ${item.status} ${item.plugin}${item.diagnostic ? ` ${item.diagnostic}` : ""}`);
34482
+ for (const facts of report.verification?.operations ?? []) {
34483
+ const outcome = report.outcomes.find((row) => row.operationId === facts.operationId);
34484
+ console.log(`${outcome.scope.target.kind} ${outcome.package} compatibility=${facts.compatibility} registration=${facts.registration} executionApproval=${facts.executionApproval} delivery=${facts.delivery}`);
34485
+ }
34364
34486
  }
34365
34487
  }
34366
34488
  function select(available, targets) {
@@ -34663,14 +34785,6 @@ async function runPlannerAdd(source, binding, targets, flags) {
34663
34785
  command: { ...executed.report.command, name: "add" }
34664
34786
  });
34665
34787
  }
34666
- function writeInstallLedger(records, changed, binding) {
34667
- const loaded = readLifecycleState();
34668
- if (loaded.sourceVersion !== 2) {
34669
- writeState(records);
34670
- return;
34671
- }
34672
- writeLifecycleState(withLegacyWriterRecord(loaded.state, changed, binding), { globalPreflight: "succeeded" });
34673
- }
34674
34788
  async function runWriterAdd(source, selectedWriters, flags, mode) {
34675
34789
  let resolved;
34676
34790
  try {
@@ -35002,7 +35116,8 @@ async function runRecordedLifecycleUpdate(flags, state) {
35002
35116
  const scope = scopes.get(activation.scopeId);
35003
35117
  if (scope === undefined || scope.target.instance !== "default" || !kinds.has(scope.target.kind))
35004
35118
  return [];
35005
- if (requested !== undefined && requested !== activation.packageId && requested !== activation.nativeId)
35119
+ const writer = present.selected.find((candidate) => candidate.id === scope.target.kind);
35120
+ if (!requestedPersistedIdentityMatches(writer, activation.packageId, activation.nativeId, requested))
35006
35121
  return [];
35007
35122
  return [{ scope, packageId: activation.packageId }];
35008
35123
  });
@@ -35080,6 +35195,7 @@ async function runRecordedLifecycleUpdate(flags, state) {
35080
35195
  });
35081
35196
  }
35082
35197
  function emitAddReport(report, mode) {
35198
+ report = parseLifecycleReport({ ...report, verification: installationVerification(report) });
35083
35199
  if (mode === "json")
35084
35200
  return emitValidatedReport(report, true);
35085
35201
  printReport(report, mode);