agentwheel 0.22.2 → 0.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -16558,7 +16558,8 @@ var init_local = __esm({
16558
16558
  atomicCopy,
16559
16559
  rm: (path) => rm3(path, { recursive: true, force: true }),
16560
16560
  async execFile(command, args, options = {}) {
16561
- await execFileAsync(command, args, { cwd: options.cwd });
16561
+ const { stdout } = await execFileAsync(command, args, { cwd: options.cwd });
16562
+ return stdout;
16562
16563
  }
16563
16564
  };
16564
16565
  }
@@ -16627,7 +16628,7 @@ function createSshTransport(config2) {
16627
16628
  execFile(command, commandArgs, options = {}) {
16628
16629
  const quoted = [command, ...commandArgs].map(quoteSh).join(" ");
16629
16630
  const remoteCommand = options.cwd ? `cd ${quoteSh(options.cwd)} && ${quoted}` : quoted;
16630
- return run(remoteCommand).then(() => void 0);
16631
+ return run(remoteCommand);
16631
16632
  }
16632
16633
  };
16633
16634
  }
@@ -17180,6 +17181,189 @@ var init_transport = __esm({
17180
17181
  }
17181
17182
  });
17182
17183
 
17184
+ // src/resolve/semver.ts
17185
+ function parseSemver(value) {
17186
+ const match = semverPattern.exec(value.trim());
17187
+ if (!match) return void 0;
17188
+ return {
17189
+ major: Number(match[1]),
17190
+ minor: Number(match[2]),
17191
+ patch: Number(match[3]),
17192
+ prerelease: match[4]
17193
+ };
17194
+ }
17195
+ function satisfiesVersionRange(version2, range) {
17196
+ if (!range || range.trim() === "" || range.trim() === "*") return true;
17197
+ const parsedVersion = parseSemver(version2);
17198
+ const trimmed = range.trim();
17199
+ if (!parsedVersion) {
17200
+ return trimmed === "*" || trimmed === version2;
17201
+ }
17202
+ const comparators = parseRange(trimmed);
17203
+ if (!comparators) return trimmed === version2;
17204
+ return comparators.every((comparator) => compareWith(parsedVersion, comparator));
17205
+ }
17206
+ function semverMajorOrVersion(version2) {
17207
+ const parsed = parseSemver(version2);
17208
+ return parsed ? String(parsed.major) : version2;
17209
+ }
17210
+ function compareSemverStrings(a, b) {
17211
+ const parsedA = parseSemver(a);
17212
+ const parsedB = parseSemver(b);
17213
+ if (!parsedA || !parsedB) return a.localeCompare(b);
17214
+ return compareSemver(parsedA, parsedB);
17215
+ }
17216
+ function isSupportedVersionRange(range) {
17217
+ const trimmed = range.trim();
17218
+ return trimmed === "*" || parseRange(trimmed) !== void 0;
17219
+ }
17220
+ function parseRange(range) {
17221
+ if (range === "*") return [];
17222
+ if (range.startsWith("^")) {
17223
+ const base = parseSemver(range.slice(1));
17224
+ if (!base) return void 0;
17225
+ return [
17226
+ { op: ">=", version: base },
17227
+ { op: "<", version: caretUpperBound(base) }
17228
+ ];
17229
+ }
17230
+ if (range.startsWith("~")) {
17231
+ const base = parseSemver(range.slice(1));
17232
+ if (!base) return void 0;
17233
+ return [
17234
+ { op: ">=", version: base },
17235
+ { op: "<", version: { major: base.major, minor: base.minor + 1, patch: 0 } }
17236
+ ];
17237
+ }
17238
+ const parts = range.split(/\s+/).filter(Boolean);
17239
+ const comparators = [];
17240
+ for (const part of parts) {
17241
+ const match = /^(>=|<=|>|<|=)?(.+)$/.exec(part);
17242
+ if (!match) return void 0;
17243
+ const version2 = parseSemver(match[2] ?? "");
17244
+ if (!version2) return void 0;
17245
+ comparators.push({ op: match[1] ?? "=", version: version2 });
17246
+ }
17247
+ return comparators;
17248
+ }
17249
+ function caretUpperBound(version2) {
17250
+ if (version2.major > 0) return { major: version2.major + 1, minor: 0, patch: 0 };
17251
+ if (version2.minor > 0) return { major: 0, minor: version2.minor + 1, patch: 0 };
17252
+ return { major: 0, minor: 0, patch: version2.patch + 1 };
17253
+ }
17254
+ function compareWith(version2, comparator) {
17255
+ const order = compareSemver(version2, comparator.version);
17256
+ switch (comparator.op) {
17257
+ case "=":
17258
+ return order === 0;
17259
+ case ">":
17260
+ return order > 0;
17261
+ case ">=":
17262
+ return order >= 0;
17263
+ case "<":
17264
+ return order < 0;
17265
+ case "<=":
17266
+ return order <= 0;
17267
+ }
17268
+ }
17269
+ function compareSemver(a, b) {
17270
+ for (const key of ["major", "minor", "patch"]) {
17271
+ if (a[key] !== b[key]) return a[key] > b[key] ? 1 : -1;
17272
+ }
17273
+ if (a.prerelease === b.prerelease) return 0;
17274
+ if (!a.prerelease) return 1;
17275
+ if (!b.prerelease) return -1;
17276
+ return a.prerelease.localeCompare(b.prerelease);
17277
+ }
17278
+ var semverPattern;
17279
+ var init_semver = __esm({
17280
+ "src/resolve/semver.ts"() {
17281
+ "use strict";
17282
+ semverPattern = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
17283
+ }
17284
+ });
17285
+
17286
+ // src/targets/plugins/openclaw.ts
17287
+ import { readFile as readFile8 } from "fs/promises";
17288
+ import { join as join10 } from "path";
17289
+ function openClawPluginInstallCommand(request) {
17290
+ return ["openclaw", "plugins", "install", "--force", ...request.acceptCapabilities ? ["--accept-capabilities"] : [], request.path];
17291
+ }
17292
+ function createOpenClawCapabilityDetector(run) {
17293
+ let cached2;
17294
+ return () => cached2 ??= detectOpenClawCapabilitySupport(run);
17295
+ }
17296
+ async function detectOpenClawCapabilitySupport(run) {
17297
+ try {
17298
+ const help = await run(["plugins", "install", "--help"]);
17299
+ if (help?.trim()) return /(?:^|\s)--accept-capabilities(?=[\s=,]|$)/m.test(help);
17300
+ } catch {
17301
+ }
17302
+ try {
17303
+ const output = await run(["--version"]);
17304
+ const version2 = output?.match(/(?:^|\s)v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?=\s|$)/)?.[1];
17305
+ return version2 !== void 0 && parseSemver(version2) !== void 0 && satisfiesVersionRange(version2, ">=2026.8.1");
17306
+ } catch {
17307
+ return false;
17308
+ }
17309
+ }
17310
+ function openClawPluginUninstallCommand(pluginName) {
17311
+ return ["openclaw", "plugins", "uninstall", pluginName, "--force"];
17312
+ }
17313
+ async function openClawPluginSpec(request) {
17314
+ if (request.format === "openclaw-clawhub-plugin") {
17315
+ const metadata = await openClawClawHubPluginMetadata(request.path, request.fallbackPluginName);
17316
+ return {
17317
+ runtime: "openclaw",
17318
+ pluginName: metadata.pluginName,
17319
+ installCommands: [openClawPluginInstallCommand({ path: metadata.installSpec, dryRun: true })],
17320
+ uninstallCommands: [openClawPluginUninstallCommand(metadata.pluginName)]
17321
+ };
17322
+ }
17323
+ const pluginName = await openClawPluginName(request.path, request.fallbackPluginName);
17324
+ return {
17325
+ runtime: "openclaw",
17326
+ pluginName,
17327
+ installCommands: [openClawPluginInstallCommand({ path: request.path, dryRun: true })],
17328
+ uninstallCommands: [openClawPluginUninstallCommand(pluginName)]
17329
+ };
17330
+ }
17331
+ async function openClawPluginName(root, fallback) {
17332
+ for (const manifestName of ["plugin.json", "openclaw.plugin.json"]) {
17333
+ const manifestPath = join10(root, manifestName);
17334
+ if (!await pathExists(manifestPath)) continue;
17335
+ const parsed = JSON.parse(await readFile8(manifestPath, "utf8"));
17336
+ if (typeof parsed.name === "string" && parsed.name.trim().length > 0) return parsed.name.trim();
17337
+ }
17338
+ return fallback;
17339
+ }
17340
+ async function openClawClawHubPluginMetadata(root, fallback) {
17341
+ const metadataPath = join10(root, "clawhub.json");
17342
+ if (!await pathExists(metadataPath)) {
17343
+ throw new Error("OpenClaw ClawHub plugins must contain clawhub.json");
17344
+ }
17345
+ const parsed = JSON.parse(await readFile8(metadataPath, "utf8"));
17346
+ const installSpec = stringField(parsed.installSpec);
17347
+ if (!installSpec?.startsWith("clawhub:")) {
17348
+ throw new Error("OpenClaw ClawHub plugin metadata must declare installSpec starting with clawhub:");
17349
+ }
17350
+ const pluginName = stringField(parsed.runtimeId) ?? installNameFor(stringField(parsed.name) ?? fallback);
17351
+ return { installSpec, pluginName };
17352
+ }
17353
+ function stringField(value) {
17354
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
17355
+ }
17356
+ function installNameFor(value) {
17357
+ return value.split("/").at(-1).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
17358
+ }
17359
+ var init_openclaw2 = __esm({
17360
+ "src/targets/plugins/openclaw.ts"() {
17361
+ "use strict";
17362
+ init_fs();
17363
+ init_semver();
17364
+ }
17365
+ });
17366
+
17183
17367
  // src/transport/run-as-policy.ts
17184
17368
  function assertRunAsPlanSupported(plan, transport) {
17185
17369
  if (transport.kind !== "local-run-as") return;
@@ -17194,12 +17378,12 @@ var init_run_as_policy = __esm({
17194
17378
  });
17195
17379
 
17196
17380
  // src/install/json-merge.ts
17197
- import { readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
17381
+ import { readFile as readFile9, writeFile as writeFile5 } from "fs/promises";
17198
17382
  import { dirname as dirname7 } from "path";
17199
17383
  import { mkdir as mkdir5 } from "fs/promises";
17200
17384
  async function mergeJsonFile(sourcePath, destPath) {
17201
- const source = JSON.parse(await readFile8(sourcePath, "utf8"));
17202
- const current = await pathExists(destPath) ? JSON.parse(await readFile8(destPath, "utf8")) : {};
17385
+ const source = JSON.parse(await readFile9(sourcePath, "utf8"));
17386
+ const current = await pathExists(destPath) ? JSON.parse(await readFile9(destPath, "utf8")) : {};
17203
17387
  const merged = deepMerge(current, source);
17204
17388
  await mkdir5(dirname7(destPath), { recursive: true });
17205
17389
  await writeFile5(destPath, `${JSON.stringify(merged, null, 2)}
@@ -17240,11 +17424,11 @@ var init_json_merge = __esm({
17240
17424
  });
17241
17425
 
17242
17426
  // src/install/openclaw-json-merge.ts
17243
- import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile6 } from "fs/promises";
17427
+ import { mkdir as mkdir6, readFile as readFile10, writeFile as writeFile6 } from "fs/promises";
17244
17428
  import { dirname as dirname8 } from "path";
17245
17429
  async function mergeOpenClawJsonFile(sourcePath, destPath) {
17246
17430
  const source = await renderOpenClawJsonMergeSource(sourcePath);
17247
- const current = await pathExists(destPath) ? JSON.parse(await readFile9(destPath, "utf8")) : {};
17431
+ const current = await pathExists(destPath) ? JSON.parse(await readFile10(destPath, "utf8")) : {};
17248
17432
  const merged = mergeOpenClawJson(current, source);
17249
17433
  await mkdir6(dirname8(destPath), { recursive: true });
17250
17434
  await writeFile6(destPath, `${JSON.stringify(merged, null, 2)}
@@ -17252,7 +17436,7 @@ async function mergeOpenClawJsonFile(sourcePath, destPath) {
17252
17436
  }
17253
17437
  async function renderOpenClawJsonMergeSource(sourcePath) {
17254
17438
  return expandEnvPlaceholders(
17255
- normalizeOpenClawConfig(JSON.parse(await readFile9(sourcePath, "utf8"))),
17439
+ normalizeOpenClawConfig(JSON.parse(await readFile10(sourcePath, "utf8"))),
17256
17440
  sourcePath
17257
17441
  );
17258
17442
  }
@@ -17517,9 +17701,9 @@ var init_manifest = __esm({
17517
17701
  });
17518
17702
 
17519
17703
  // src/install/paths.ts
17520
- import { join as join10 } from "path";
17704
+ import { join as join11 } from "path";
17521
17705
  function metadataDir(targetRoot) {
17522
- return join10(targetRoot, ".agentwheel");
17706
+ return join11(targetRoot, ".agentwheel");
17523
17707
  }
17524
17708
  function stateKeyFor(adapter, scope = {}) {
17525
17709
  assertPathSafeAdapterName(adapter);
@@ -17539,10 +17723,10 @@ function assertPathSafeAdapterName(adapter) {
17539
17723
  }
17540
17724
  }
17541
17725
  function installManifestPath(targetRoot, adapter, scope = {}) {
17542
- return join10(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.install-manifest.json`);
17726
+ return join11(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.install-manifest.json`);
17543
17727
  }
17544
17728
  function sourceLockPath(targetRoot, adapter, scope = {}) {
17545
- return join10(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.source-lock.json`);
17729
+ return join11(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.source-lock.json`);
17546
17730
  }
17547
17731
  function sanitizeStateKey(value) {
17548
17732
  return value.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "default";
@@ -17556,7 +17740,7 @@ var init_paths = __esm({
17556
17740
 
17557
17741
  // src/install/manifest.ts
17558
17742
  import { createHash as createHash7 } from "crypto";
17559
- import { join as join11, resolve as resolve10 } from "path";
17743
+ import { join as join12, resolve as resolve10 } from "path";
17560
17744
  async function readInstallManifest(targetRoot, adapter, transport = localTransport, scope = {}) {
17561
17745
  const path = installManifestPath(targetRoot, adapter, scope);
17562
17746
  if (!await transport.pathExists(path)) return void 0;
@@ -17574,7 +17758,7 @@ async function listInstallManifests(targetRoot, adapter, transport = localTransp
17574
17758
  for (const fileName of await transport.listDir(dir)) {
17575
17759
  if (!fileName.endsWith(suffix)) continue;
17576
17760
  const stateKey = fileName.slice(0, -suffix.length);
17577
- const path = join11(dir, fileName);
17761
+ const path = join12(dir, fileName);
17578
17762
  try {
17579
17763
  const raw = JSON.parse(await transport.readFile(path));
17580
17764
  const parsed = installManifestSchema.parse(raw);
@@ -17759,108 +17943,6 @@ if private and (s.st_uid!=os.geteuid() or not stat.S_ISREG(s.st_mode) or s.st_nl
17759
17943
  }
17760
17944
  });
17761
17945
 
17762
- // src/resolve/semver.ts
17763
- function parseSemver(value) {
17764
- const match = semverPattern.exec(value.trim());
17765
- if (!match) return void 0;
17766
- return {
17767
- major: Number(match[1]),
17768
- minor: Number(match[2]),
17769
- patch: Number(match[3]),
17770
- prerelease: match[4]
17771
- };
17772
- }
17773
- function satisfiesVersionRange(version2, range) {
17774
- if (!range || range.trim() === "" || range.trim() === "*") return true;
17775
- const parsedVersion = parseSemver(version2);
17776
- const trimmed = range.trim();
17777
- if (!parsedVersion) {
17778
- return trimmed === "*" || trimmed === version2;
17779
- }
17780
- const comparators = parseRange(trimmed);
17781
- if (!comparators) return trimmed === version2;
17782
- return comparators.every((comparator) => compareWith(parsedVersion, comparator));
17783
- }
17784
- function semverMajorOrVersion(version2) {
17785
- const parsed = parseSemver(version2);
17786
- return parsed ? String(parsed.major) : version2;
17787
- }
17788
- function compareSemverStrings(a, b) {
17789
- const parsedA = parseSemver(a);
17790
- const parsedB = parseSemver(b);
17791
- if (!parsedA || !parsedB) return a.localeCompare(b);
17792
- return compareSemver(parsedA, parsedB);
17793
- }
17794
- function isSupportedVersionRange(range) {
17795
- const trimmed = range.trim();
17796
- return trimmed === "*" || parseRange(trimmed) !== void 0;
17797
- }
17798
- function parseRange(range) {
17799
- if (range === "*") return [];
17800
- if (range.startsWith("^")) {
17801
- const base = parseSemver(range.slice(1));
17802
- if (!base) return void 0;
17803
- return [
17804
- { op: ">=", version: base },
17805
- { op: "<", version: caretUpperBound(base) }
17806
- ];
17807
- }
17808
- if (range.startsWith("~")) {
17809
- const base = parseSemver(range.slice(1));
17810
- if (!base) return void 0;
17811
- return [
17812
- { op: ">=", version: base },
17813
- { op: "<", version: { major: base.major, minor: base.minor + 1, patch: 0 } }
17814
- ];
17815
- }
17816
- const parts = range.split(/\s+/).filter(Boolean);
17817
- const comparators = [];
17818
- for (const part of parts) {
17819
- const match = /^(>=|<=|>|<|=)?(.+)$/.exec(part);
17820
- if (!match) return void 0;
17821
- const version2 = parseSemver(match[2] ?? "");
17822
- if (!version2) return void 0;
17823
- comparators.push({ op: match[1] ?? "=", version: version2 });
17824
- }
17825
- return comparators;
17826
- }
17827
- function caretUpperBound(version2) {
17828
- if (version2.major > 0) return { major: version2.major + 1, minor: 0, patch: 0 };
17829
- if (version2.minor > 0) return { major: 0, minor: version2.minor + 1, patch: 0 };
17830
- return { major: 0, minor: 0, patch: version2.patch + 1 };
17831
- }
17832
- function compareWith(version2, comparator) {
17833
- const order = compareSemver(version2, comparator.version);
17834
- switch (comparator.op) {
17835
- case "=":
17836
- return order === 0;
17837
- case ">":
17838
- return order > 0;
17839
- case ">=":
17840
- return order >= 0;
17841
- case "<":
17842
- return order < 0;
17843
- case "<=":
17844
- return order <= 0;
17845
- }
17846
- }
17847
- function compareSemver(a, b) {
17848
- for (const key of ["major", "minor", "patch"]) {
17849
- if (a[key] !== b[key]) return a[key] > b[key] ? 1 : -1;
17850
- }
17851
- if (a.prerelease === b.prerelease) return 0;
17852
- if (!a.prerelease) return 1;
17853
- if (!b.prerelease) return -1;
17854
- return a.prerelease.localeCompare(b.prerelease);
17855
- }
17856
- var semverPattern;
17857
- var init_semver = __esm({
17858
- "src/resolve/semver.ts"() {
17859
- "use strict";
17860
- semverPattern = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
17861
- }
17862
- });
17863
-
17864
17946
  // src/model/selection.ts
17865
17947
  function artifactSelectorKey(artifact) {
17866
17948
  return `${artifact.type}/${artifact.name}`;
@@ -17918,9 +18000,9 @@ var init_selection = __esm({
17918
18000
  });
17919
18001
 
17920
18002
  // src/model/workspace.ts
17921
- import { readFile as readFile10 } from "fs/promises";
18003
+ import { readFile as readFile11 } from "fs/promises";
17922
18004
  import { homedir as homedir4 } from "os";
17923
- import { dirname as dirname9, join as join12, resolve as resolve13 } from "path";
18005
+ import { dirname as dirname9, join as join13, resolve as resolve13 } from "path";
17924
18006
  function packagesForTarget(packages, target, targetForPackage2) {
17925
18007
  return packages.filter((pkg) => !pkg.runtimes || pkg.runtimes.includes((targetForPackage2?.(pkg) ?? target).adapter));
17926
18008
  }
@@ -17928,12 +18010,12 @@ function supportsFleetConfig(config2) {
17928
18010
  return config2.schemaVersion === 3 || config2.schemaVersion === 4;
17929
18011
  }
17930
18012
  function workspaceConfigPath(workspaceRoot) {
17931
- return join12(workspaceRoot, ".agentwheel", "config.json");
18013
+ return join13(workspaceRoot, ".agentwheel", "config.json");
17932
18014
  }
17933
18015
  async function readWorkspaceConfig(workspaceRoot) {
17934
18016
  const path = workspaceConfigPath(workspaceRoot);
17935
18017
  if (!await pathExists(path)) return emptyWorkspaceConfig();
17936
- return workspaceConfigSchema.parse(JSON.parse(await readFile10(path, "utf8")));
18018
+ return workspaceConfigSchema.parse(JSON.parse(await readFile11(path, "utf8")));
17937
18019
  }
17938
18020
  async function writeWorkspaceConfig(workspaceRoot, config2) {
17939
18021
  const path = workspaceConfigPath(workspaceRoot);
@@ -17947,7 +18029,7 @@ async function pinConfiguredPackages(workspaceRoot, input, options = {}) {
17947
18029
  throw new Error("Package declarations require unique aliases.");
17948
18030
  }
17949
18031
  const path2 = workspaceConfigPath(workspaceRoot);
17950
- const config3 = JSON.parse(await readFile10(path2, "utf8"));
18032
+ const config3 = JSON.parse(await readFile11(path2, "utf8"));
17951
18033
  workspaceConfigSchema.parse(config3);
17952
18034
  config3.packages = input;
17953
18035
  workspaceConfigSchema.parse(config3);
@@ -17970,7 +18052,7 @@ async function pinConfiguredPackages(workspaceRoot, input, options = {}) {
17970
18052
  throw new Error("Pin requires unique configured aliases.");
17971
18053
  }
17972
18054
  const path = workspaceConfigPath(workspaceRoot);
17973
- const config2 = JSON.parse(await readFile10(path, "utf8"));
18055
+ const config2 = JSON.parse(await readFile11(path, "utf8"));
17974
18056
  workspaceConfigSchema.parse(config2);
17975
18057
  const updates = pins.map(({ alias, commit, select }) => {
17976
18058
  const matches = (config2.packages ?? []).filter((pkg2) => pkg2.name === alias);
@@ -18004,7 +18086,7 @@ function upsertPackage(config2, entry) {
18004
18086
  return workspaceConfigSchema.parse({ ...parsed, packages });
18005
18087
  }
18006
18088
  function globalWorkspaceConfigPath(globalRoot = homedir4()) {
18007
- return join12(globalRoot, ".agentwheel", "config.json");
18089
+ return join13(globalRoot, ".agentwheel", "config.json");
18008
18090
  }
18009
18091
  async function findWorkspaceRoot(start = process.cwd()) {
18010
18092
  let current = resolve13(start);
@@ -18063,7 +18145,7 @@ function isCompositeWorkspaceProfile(profile) {
18063
18145
  }
18064
18146
  async function readConfigPath(path) {
18065
18147
  if (!await pathExists(path)) return emptyWorkspaceConfig();
18066
- return workspaceConfigSchema.parse(JSON.parse(await readFile10(path, "utf8")));
18148
+ return workspaceConfigSchema.parse(JSON.parse(await readFile11(path, "utf8")));
18067
18149
  }
18068
18150
  function mergeWorkspaceTrust(global, project) {
18069
18151
  return {
@@ -18324,7 +18406,7 @@ var init_workspace = __esm({
18324
18406
  });
18325
18407
 
18326
18408
  // src/model/fleet.ts
18327
- import { lstat as lstat2, readFile as readFile11, realpath } from "fs/promises";
18409
+ import { lstat as lstat2, readFile as readFile12, realpath } from "fs/promises";
18328
18410
  import { homedir as homedir5 } from "os";
18329
18411
  import { isAbsolute as isAbsolute10, relative as relative6, resolve as resolve14 } from "path";
18330
18412
  async function resolveWorkspaceScope(request = {}) {
@@ -18441,7 +18523,7 @@ async function readRequiredConfig(root, label) {
18441
18523
  const path = workspaceConfigPath(root);
18442
18524
  if (!await pathExists(path)) throw missingScopeError(label);
18443
18525
  try {
18444
- return workspaceConfigSchema.parse(JSON.parse(await readFile11(path, "utf8")));
18526
+ return workspaceConfigSchema.parse(JSON.parse(await readFile12(path, "utf8")));
18445
18527
  } catch (error46) {
18446
18528
  throw new Error(`Invalid ${label} Agentwheel config at ${path}: ${error46 instanceof Error ? error46.message : String(error46)}`);
18447
18529
  }
@@ -18512,8 +18594,8 @@ var init_fleet = __esm({
18512
18594
 
18513
18595
  // src/mutation/repository.ts
18514
18596
  import { createHash as createHash8 } from "crypto";
18515
- import { lstat as lstat3, readFile as readFile12, readlink, readdir as readdir5 } from "fs/promises";
18516
- import { posix as posix4, relative as relative7, resolve as resolve15, sep as sep5 } from "path";
18597
+ import { lstat as lstat3, readFile as readFile13, readlink, readdir as readdir5 } from "fs/promises";
18598
+ import { dirname as dirname10, posix as posix4, relative as relative7, resolve as resolve15, sep as sep5 } from "path";
18517
18599
  async function discoverGitRepository(start) {
18518
18600
  const probe = await runProcess("git", ["-C", start, "rev-parse", "--show-toplevel"], { allowExitCodes: [0, 128] });
18519
18601
  if (probe.exitCode !== 0) return void 0;
@@ -18540,6 +18622,9 @@ async function assertGitPreflight(repository) {
18540
18622
  }
18541
18623
  }
18542
18624
  async function assertHeadLease(repositoryRoot, expectedHead, head, paths, provider) {
18625
+ return assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, paths, provider, []);
18626
+ }
18627
+ async function assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, paths, provider, recoveryPaths, terminalChanges = /* @__PURE__ */ new Map()) {
18543
18628
  if (head === expectedHead) return;
18544
18629
  if (provider?.headLease !== "path-scoped" || paths.length === 0) {
18545
18630
  throw new Error(`Git HEAD lease mismatch: expected ${expectedHead}, found ${head}.`);
@@ -18575,10 +18660,65 @@ async function assertHeadLease(repositoryRoot, expectedHead, head, paths, provid
18575
18660
  "-z",
18576
18661
  commit
18577
18662
  ])).stdout);
18578
- if (touched.some((path) => protectedPaths.some((protectedPath) => path === protectedPath || path.startsWith(`${protectedPath}/`) || protectedPath.startsWith(`${path}/`)))) {
18579
- throw new Error(`Git HEAD lease overlaps protected paths in intervening commit ${commit}.`);
18663
+ for (const path of touched) {
18664
+ if (!protectedPaths.some((protectedPath) => overlaps(path, protectedPath))) continue;
18665
+ if (terminalChanges.get(commit)?.has(path)) continue;
18666
+ const proof = recoveryPaths.find((entry) => entry.path === path && paths.includes(path));
18667
+ if (!proof || overlaps(path, ".agentwheel/config.json") || overlaps(path, ".syncwheel/manifest.json") || await gitPathMode(repositoryRoot, commit, path) !== "100644" || await hashHeadPath(repositoryRoot, expectedHead, path) !== proof.beforeSha256 || await hashHeadPath(repositoryRoot, commit, path) !== proof.afterSha256 || await hashHeadPath(repositoryRoot, head, path) !== proof.afterSha256 || await hashWorkingPath(repositoryRoot, path) !== proof.afterSha256) {
18668
+ throw new Error(`Git HEAD lease overlaps protected paths in intervening commit ${commit}.`);
18669
+ }
18670
+ }
18671
+ }
18672
+ }
18673
+ function overlaps(left, right) {
18674
+ return left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`);
18675
+ }
18676
+ async function committedRecoveryPaths(repositoryRoot, expectedHead, head, declarations, receiptPaths, provider) {
18677
+ await verifyRevisionPaths(repositoryRoot, expectedHead, receiptPaths);
18678
+ const committed = [];
18679
+ for (const entry of receiptPaths) {
18680
+ if (!declarations.includes(entry.path)) throw new Error(`Recovery path was not declared: ${entry.path}.`);
18681
+ if (await hashHeadPath(repositoryRoot, head, entry.path) === entry.afterSha256 && entry.beforeSha256 !== entry.afterSha256) {
18682
+ await assertRecoveryFileIdentity(repositoryRoot, expectedHead, head, entry.path);
18683
+ committed.push(entry);
18580
18684
  }
18581
18685
  }
18686
+ await assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, declarations, provider, committed);
18687
+ return committed;
18688
+ }
18689
+ async function verifyCompletedRecoveryPaths(repositoryRoot, expectedHead, declarations, savedPaths, provider, productCommitSha, productPaths, controlCommitSha) {
18690
+ const head = await currentHead(repositoryRoot);
18691
+ await verifyRevisionPaths(repositoryRoot, expectedHead, savedPaths);
18692
+ for (const entry of savedPaths) {
18693
+ await assertRecoveryFileIdentity(repositoryRoot, expectedHead, head, entry.path);
18694
+ if (await hashHeadPath(repositoryRoot, head, entry.path) !== entry.afterSha256) {
18695
+ throw new Error(`Committed recovery path changed during provider completion: ${entry.path}.`);
18696
+ }
18697
+ }
18698
+ const terminalChanges = /* @__PURE__ */ new Map();
18699
+ if (productCommitSha) terminalChanges.set(productCommitSha, new Set(productPaths));
18700
+ if (controlCommitSha) terminalChanges.set(controlCommitSha, /* @__PURE__ */ new Set([".syncwheel/manifest.json"]));
18701
+ await assertHeadLeaseWithRecovery(repositoryRoot, expectedHead, head, declarations, provider, savedPaths, terminalChanges);
18702
+ }
18703
+ async function gitPathMode(repositoryRoot, head, path) {
18704
+ const tree = (await runProcess("git", ["-C", repositoryRoot, "ls-tree", "-z", head, "--", path])).stdout.toString("utf8");
18705
+ const entry = tree.split("\0").find((value) => value.slice(value.indexOf(" ") + 1) === path);
18706
+ return entry?.split(" ")[0];
18707
+ }
18708
+ async function assertRecoveryFileIdentity(repositoryRoot, expectedHead, head, path) {
18709
+ if (await gitPathMode(repositoryRoot, expectedHead, path) !== "100644" || await gitPathMode(repositoryRoot, head, path) !== "100644") {
18710
+ throw new Error(`Recovery requires an existing regular non-executable Git file: ${path}.`);
18711
+ }
18712
+ const absolute = resolve15(repositoryRoot, ...path.split("/"));
18713
+ const stats = await lstat3(absolute);
18714
+ if (!stats.isFile() || (stats.mode & 73) !== 0) throw new Error(`Recovery file identity changed: ${path}.`);
18715
+ let ancestor = dirname10(absolute);
18716
+ while (true) {
18717
+ if ((await lstat3(ancestor)).isSymbolicLink()) throw new Error(`Recovery symlink ancestor is unsupported: ${path}.`);
18718
+ const parent = dirname10(ancestor);
18719
+ if (parent === ancestor) break;
18720
+ ancestor = parent;
18721
+ }
18582
18722
  }
18583
18723
  function isAgentwheelWritablePath(path) {
18584
18724
  return /^\.agentwheel(?:\/|$)/u.test(path) || /^profiles\/[^/]+\/\.agentwheel(?:\/|$)/u.test(path);
@@ -18661,7 +18801,7 @@ async function hashWorkingPath(repositoryRoot, path) {
18661
18801
  throw error46;
18662
18802
  }
18663
18803
  if (stats.isSymbolicLink()) return sha256(Buffer.from(await readlink(absolute), "utf8"));
18664
- if (stats.isFile()) return sha256(await readFile12(absolute));
18804
+ if (stats.isFile()) return sha256(await readFile13(absolute));
18665
18805
  if (stats.isDirectory()) return hashDirectory(absolute);
18666
18806
  throw new Error(`Unsupported repository path kind: ${path}`);
18667
18807
  }
@@ -18674,7 +18814,7 @@ async function hashDirectory(root) {
18674
18814
  const relativePath = normalizeRepoPath(relative7(root, absolute));
18675
18815
  if (entry.isDirectory()) await walk2(absolute);
18676
18816
  else if (entry.isSymbolicLink()) hash3.update(relativePath).update("\0").update(await readlink(absolute)).update("\0");
18677
- else if (entry.isFile()) hash3.update(relativePath).update("\0").update(await readFile12(absolute)).update("\0");
18817
+ else if (entry.isFile()) hash3.update(relativePath).update("\0").update(await readFile13(absolute)).update("\0");
18678
18818
  }
18679
18819
  }
18680
18820
  await walk2(root);
@@ -18710,9 +18850,9 @@ var init_repository = __esm({
18710
18850
 
18711
18851
  // src/mutation/providers.ts
18712
18852
  import { createHash as createHash9 } from "crypto";
18713
- import { chmod as chmod2, mkdtemp, open as open3, readFile as readFile13, rename as rename5, rm as rm4, rmdir, stat as stat3, writeFile as writeFile7 } from "fs/promises";
18853
+ import { chmod as chmod2, mkdtemp, open as open3, readFile as readFile14, rename as rename5, rm as rm4, rmdir, stat as stat3, writeFile as writeFile7 } from "fs/promises";
18714
18854
  import { tmpdir as tmpdir2 } from "os";
18715
- import { isAbsolute as isAbsolute11, join as join13, resolve as resolve16 } from "path";
18855
+ import { isAbsolute as isAbsolute11, join as join14, resolve as resolve16 } from "path";
18716
18856
  function revisionProviderRejection(error46) {
18717
18857
  return error46 instanceof RevisionProviderRejectedError ? error46.response : void 0;
18718
18858
  }
@@ -18821,8 +18961,8 @@ async function openImmutableExecutableSnapshot(bytes) {
18821
18961
  `Command revision providers require an unlinked immutable executable snapshot, which is unsupported on ${process.platform}.`
18822
18962
  );
18823
18963
  }
18824
- const root = await mkdtemp(join13(tmpdir2(), "agentwheel-revision-command-"));
18825
- const path = join13(root, "entrypoint");
18964
+ const root = await mkdtemp(join14(tmpdir2(), "agentwheel-revision-command-"));
18965
+ const path = join14(root, "entrypoint");
18826
18966
  let snapshot;
18827
18967
  try {
18828
18968
  await chmod2(root, 448);
@@ -18976,8 +19116,8 @@ async function finalizeGit(providerId, request, config2) {
18976
19116
  const indexLease = await captureIndexLease(request.repositoryRoot);
18977
19117
  await assertIndexTree(request.repositoryRoot, repository.head);
18978
19118
  const hookBaseline = await snapshotRepository(request.repositoryRoot);
18979
- const tempRoot = await mkdtemp(join13(tmpdir2(), "agentwheel-git-index-"));
18980
- const indexPath = join13(tempRoot, "index");
19119
+ const tempRoot = await mkdtemp(join14(tmpdir2(), "agentwheel-git-index-"));
19120
+ const indexPath = join14(tempRoot, "index");
18981
19121
  const env2 = { ...process.env, GIT_INDEX_FILE: indexPath };
18982
19122
  let commitSha;
18983
19123
  try {
@@ -18988,14 +19128,14 @@ async function finalizeGit(providerId, request, config2) {
18988
19128
  await verifyTemporaryIndexPaths(request, env2);
18989
19129
  await runProcess("git", ["-C", request.repositoryRoot, "diff", "--cached", "--check"], { env: env2 });
18990
19130
  const tree = (await runProcess("git", ["-C", request.repositoryRoot, "write-tree"], { env: env2 })).stdout.toString("utf8").trim();
18991
- const messagePath = join13(tempRoot, "COMMIT_EDITMSG");
19131
+ const messagePath = join14(tempRoot, "COMMIT_EDITMSG");
18992
19132
  await writeFile7(messagePath, commitMessage(request, planDigest), { encoding: "utf8", mode: 384 });
18993
19133
  await runCommitHooks(request, env2, messagePath);
18994
19134
  assertRepositorySnapshotEqual(hookBaseline, await snapshotRepository(request.repositoryRoot), "Git commit hooks");
18995
19135
  const stagedAfterHooks = splitNull2((await runProcess("git", ["-C", request.repositoryRoot, "diff", "--cached", "--name-only", "-z"], { env: env2 })).stdout);
18996
19136
  assertExactSet(stagedAfterHooks, request.paths.map((entry) => entry.path), "temporary Git index after hooks");
18997
19137
  await verifyTemporaryIndexPaths(request, env2);
18998
- const message = await readFile13(messagePath, "utf8");
19138
+ const message = await readFile14(messagePath, "utf8");
18999
19139
  assertCommitMessageContract(message, request, planDigest);
19000
19140
  commitSha = (await runProcess("git", ["-C", request.repositoryRoot, "commit-tree", tree, "-p", repository.head], {
19001
19141
  env: env2,
@@ -19114,7 +19254,7 @@ async function captureIndexLease(repositoryRoot) {
19114
19254
  const rawPath = (await runProcess("git", ["-C", repositoryRoot, "rev-parse", "--git-path", "index"])).stdout.toString("utf8").trim();
19115
19255
  const path = isAbsolute11(rawPath) ? rawPath : resolve16(repositoryRoot, rawPath);
19116
19256
  try {
19117
- const [content, info] = await Promise.all([readFile13(path), stat3(path)]);
19257
+ const [content, info] = await Promise.all([readFile14(path), stat3(path)]);
19118
19258
  return { path, sha256: sha2562(content), mode: info.mode & 511 };
19119
19259
  } catch (error46) {
19120
19260
  if (isMissing4(error46)) return { path, sha256: null, mode: 384 };
@@ -19122,15 +19262,15 @@ async function captureIndexLease(repositoryRoot) {
19122
19262
  }
19123
19263
  }
19124
19264
  async function replaceIndexCas(repositoryRoot, lease, commitSha) {
19125
- const tempRoot = await mkdtemp(join13(tmpdir2(), "agentwheel-index-replacement-"));
19126
- const replacementPath = join13(tempRoot, "index");
19265
+ const tempRoot = await mkdtemp(join14(tmpdir2(), "agentwheel-index-replacement-"));
19266
+ const replacementPath = join14(tempRoot, "index");
19127
19267
  const lockPath = `${lease.path}.lock`;
19128
19268
  let handle;
19129
19269
  try {
19130
19270
  await runProcess("git", ["-C", repositoryRoot, "read-tree", commitSha], {
19131
19271
  env: { ...process.env, GIT_INDEX_FILE: replacementPath }
19132
19272
  });
19133
- const replacement = await readFile13(replacementPath);
19273
+ const replacement = await readFile14(replacementPath);
19134
19274
  handle = await open3(lockPath, "wx", lease.mode);
19135
19275
  const current = await readOptionalFile(lease.path);
19136
19276
  const currentSha256 = current ? sha2562(current) : null;
@@ -19172,7 +19312,7 @@ async function hashGitObject(repositoryRoot, spec) {
19172
19312
  }
19173
19313
  async function readOptionalFile(path) {
19174
19314
  try {
19175
- return await readFile13(path);
19315
+ return await readFile14(path);
19176
19316
  } catch (error46) {
19177
19317
  if (isMissing4(error46)) return null;
19178
19318
  throw error46;
@@ -19279,7 +19419,7 @@ var init_providers = __esm({
19279
19419
  // src/mutation/coordinator.ts
19280
19420
  import { randomUUID as randomUUID2 } from "crypto";
19281
19421
  import { homedir as homedir6 } from "os";
19282
- import { dirname as dirname10, isAbsolute as isAbsolute12, relative as relative8, resolve as resolve17, sep as sep6 } from "path";
19422
+ import { dirname as dirname11, isAbsolute as isAbsolute12, relative as relative8, resolve as resolve17, sep as sep6 } from "path";
19283
19423
  function dirtyRepositoryPaths(repositoryRoot, baseline, paths) {
19284
19424
  const conflicts = /* @__PURE__ */ new Set();
19285
19425
  for (const path of paths) {
@@ -19353,12 +19493,15 @@ async function resumeMutation(operationId, action) {
19353
19493
  );
19354
19494
  receipt = await updateMutationReceipt(receipt, { paths, status: "mutation-applied" });
19355
19495
  }
19356
- await invokeRevisionProvider(provider, providerRequest(receipt, "preflight", paths), {
19496
+ const request = action === "recover" && receipt.runtimeJournals.length > 0 ? await recoveryProviderRequest(receipt, paths) : providerRequest(receipt, action, paths);
19497
+ await invokeRevisionProvider(provider, revisionProviderRequestSchema.parse({ ...request, action: "preflight" }), {
19357
19498
  workspaceRoot: receipt.workspaceRoot
19358
19499
  });
19359
- const response = await invokeRevisionProvider(provider, providerRequest(receipt, action, paths), {
19500
+ if (action === "recover") await verifyRecoveryProjection(receipt, request);
19501
+ const response = await invokeRevisionProvider(provider, request, {
19360
19502
  workspaceRoot: receipt.workspaceRoot
19361
19503
  });
19504
+ await verifyCompletedRecoveryProjection(receipt, request, response);
19362
19505
  return updateMutationReceipt(receipt, {
19363
19506
  status: receiptStatusForProvider(response.status),
19364
19507
  providerResponse: response,
@@ -19401,17 +19544,19 @@ async function recoverMutationRuntime(operationId, options = {}) {
19401
19544
  `Mutation '${receipt.operationId}' repository HEAD lease changed before runtime recovery.`
19402
19545
  );
19403
19546
  }
19404
- await assertHeadLease(
19547
+ if (receipt.noCommit) await assertHeadLease(receipt.repositoryRoot, receipt.expectedHead, repository.head, [], receipt.provider);
19548
+ else await committedRecoveryPaths(
19405
19549
  receipt.repositoryRoot,
19406
19550
  receipt.expectedHead,
19407
19551
  repository.head,
19408
- receipt.noCommit ? [] : declarations,
19552
+ declarations,
19553
+ receipt.paths,
19409
19554
  receipt.provider
19410
19555
  );
19411
19556
  await assertGitPreflight(repository);
19412
19557
  await collectIntroducedPaths(receipt.repositoryRoot, receipt.expectedHead, baseline, declarations);
19413
19558
  }
19414
- mutation = GovernedMutation.activateExisting(receipt, baseline, lock);
19559
+ mutation = GovernedMutation.activateExisting(receipt, baseline, lock, options.beforeProviderCompletion);
19415
19560
  const [{ recoverPendingApply: recoverPendingApply2 }, { readLinkedLocalApplyJournal: readLinkedLocalApplyJournal2 }] = await Promise.all([
19416
19561
  Promise.resolve().then(() => (init_apply(), apply_exports)),
19417
19562
  Promise.resolve().then(() => (init_transaction(), transaction_exports))
@@ -19523,7 +19668,7 @@ async function mutationPolicyForWorkspace(workspaceRoot, globalRoot = homedir6()
19523
19668
  const globalConfig2 = await readWorkspaceConfig(globalRoot);
19524
19669
  const global = globalConfig2.schemaVersion === 4 ? globalConfig2.mutationPolicy : void 0;
19525
19670
  let existingRoot = resolve17(workspaceRoot);
19526
- while (!await pathExists(existingRoot) && dirname10(existingRoot) !== existingRoot) existingRoot = dirname10(existingRoot);
19671
+ while (!await pathExists(existingRoot) && dirname11(existingRoot) !== existingRoot) existingRoot = dirname11(existingRoot);
19527
19672
  const owner = await resolveWorkspaceOwnershipScope(existingRoot, { globalRoot });
19528
19673
  const fleetConfig = owner.fleetId ? await readWorkspaceConfig(owner.root) : void 0;
19529
19674
  const fleet = fleetConfig?.schemaVersion === 4 ? fleetConfig.mutationPolicy : void 0;
@@ -19545,6 +19690,50 @@ function mergeMutationPolicies(global, scoped) {
19545
19690
  revisioning
19546
19691
  });
19547
19692
  }
19693
+ async function recoveryProviderRequest(receipt, paths) {
19694
+ const request = providerRequest(receipt, "recover", paths);
19695
+ if (receipt.noCommit) return request;
19696
+ const head = await currentHead(request.repositoryRoot);
19697
+ const committed = await committedRecoveryPaths(
19698
+ request.repositoryRoot,
19699
+ request.expectedHead,
19700
+ head,
19701
+ readMutationPathDeclarations(receipt.operationId),
19702
+ paths,
19703
+ receipt.provider
19704
+ );
19705
+ if (committed.length === 0) return request;
19706
+ const saved = new Set(committed.map((entry) => entry.path));
19707
+ return revisionProviderRequestSchema.parse({
19708
+ ...request,
19709
+ expectedHead: head,
19710
+ paths: paths.filter((entry) => !saved.has(entry.path))
19711
+ });
19712
+ }
19713
+ async function verifyCompletedRecoveryProjection(receipt, request, response) {
19714
+ if (request.expectedHead === receipt.expectedHead) return;
19715
+ if (response.action !== "recover" && response.action !== "finalize") throw new Error("Recovery requires a terminal provider response.");
19716
+ const remaining = new Set(request.paths.map((entry) => entry.path));
19717
+ await verifyCompletedRecoveryPaths(
19718
+ request.repositoryRoot,
19719
+ receipt.expectedHead,
19720
+ readMutationPathDeclarations(receipt.operationId),
19721
+ receipt.paths.filter((entry) => !remaining.has(entry.path)),
19722
+ receipt.provider,
19723
+ response.productCommitSha,
19724
+ request.paths.map((entry) => entry.path),
19725
+ response.controlCommitSha
19726
+ );
19727
+ }
19728
+ async function verifyRecoveryProjection(receipt, request) {
19729
+ if (request.expectedHead === receipt.expectedHead) return;
19730
+ if (await currentHead(request.repositoryRoot) !== request.expectedHead) throw new Error("Recovery projection HEAD changed.");
19731
+ const verified = await recoveryProviderRequest(receipt, receipt.paths);
19732
+ if (JSON.stringify(verified) !== JSON.stringify(request)) throw new Error("Recovery projection changed before provider completion.");
19733
+ const repository = await discoverGitRepository(request.repositoryRoot);
19734
+ if (!repository) throw new Error("Recovery repository disappeared.");
19735
+ await assertGitPreflight(repository);
19736
+ }
19548
19737
  function providerRequest(receipt, action, paths) {
19549
19738
  if (!receipt.repositoryRoot || !receipt.expectedHead || !receipt.provider) {
19550
19739
  throw new Error(`Mutation '${receipt.operationId}' is missing revision provider request state.`);
@@ -19614,17 +19803,21 @@ var init_coordinator = __esm({
19614
19803
  init_repository();
19615
19804
  init_session_ownership();
19616
19805
  GovernedMutation = class _GovernedMutation {
19617
- constructor(policy, receipt, baseline, lock) {
19806
+ constructor(policy, receipt, baseline, lock, runtimeRecovery = false, beforeProviderCompletion) {
19618
19807
  this.policy = policy;
19619
19808
  this.receipt = receipt;
19620
19809
  this.baseline = baseline;
19621
19810
  this.lock = lock;
19811
+ this.runtimeRecovery = runtimeRecovery;
19812
+ this.beforeProviderCompletion = beforeProviderCompletion;
19622
19813
  this.operationId = receipt.operationId;
19623
19814
  }
19624
19815
  policy;
19625
19816
  receipt;
19626
19817
  baseline;
19627
19818
  lock;
19819
+ runtimeRecovery;
19820
+ beforeProviderCompletion;
19628
19821
  operationId;
19629
19822
  closed = false;
19630
19823
  static async begin(options) {
@@ -19730,7 +19923,7 @@ var init_coordinator = __esm({
19730
19923
  );
19731
19924
  }
19732
19925
  this.receipt = await updateMutationReceipt(this.receipt, { status: "handler-succeeded" });
19733
- paths = await this.collectPaths();
19926
+ paths = await this.collectPaths(action === "recover" && this.runtimeRecovery);
19734
19927
  this.receipt = await updateMutationReceipt(this.receipt, { paths, status: "mutation-applied" });
19735
19928
  } catch (error46) {
19736
19929
  this.receipt = await updateMutationReceipt(this.receipt, {
@@ -19748,12 +19941,16 @@ var init_coordinator = __esm({
19748
19941
  return this.receipt;
19749
19942
  }
19750
19943
  const provider = this.policy.revisioning.provider;
19751
- await invokeRevisionProvider(provider, providerRequest(this.receipt, "preflight", paths), {
19944
+ const request = this.runtimeRecovery && action === "recover" ? await recoveryProviderRequest(this.receipt, paths) : providerRequest(this.receipt, action, paths);
19945
+ await invokeRevisionProvider(provider, revisionProviderRequestSchema.parse({ ...request, action: "preflight" }), {
19752
19946
  workspaceRoot: this.receipt.workspaceRoot
19753
19947
  });
19754
- const response = await invokeRevisionProvider(provider, providerRequest(this.receipt, action, paths), {
19948
+ if (this.runtimeRecovery) await verifyRecoveryProjection(this.receipt, request);
19949
+ await this.beforeProviderCompletion?.();
19950
+ const response = await invokeRevisionProvider(provider, request, {
19755
19951
  workspaceRoot: this.receipt.workspaceRoot
19756
19952
  });
19953
+ await verifyCompletedRecoveryProjection(this.receipt, request, response);
19757
19954
  this.receipt = await updateMutationReceipt(this.receipt, {
19758
19955
  status: receiptStatusForProvider(response.status),
19759
19956
  providerResponse: response
@@ -19813,7 +20010,7 @@ var init_coordinator = __esm({
19813
20010
  const runtimeJournals = upsertRuntimeJournal(this.receipt.runtimeJournals, existing, status);
19814
20011
  this.receipt = await updateMutationReceipt(this.receipt, { runtimeJournals });
19815
20012
  }
19816
- static activateExisting(receipt, baseline, lock) {
20013
+ static activateExisting(receipt, baseline, lock, beforeProviderCompletion) {
19817
20014
  if (receipt.revisionMode === "commit-after-verify" && !receipt.provider) {
19818
20015
  throw new Error(`Mutation '${receipt.operationId}' is missing its revision provider recovery policy.`);
19819
20016
  }
@@ -19831,24 +20028,41 @@ var init_coordinator = __esm({
19831
20028
  journal: "required",
19832
20029
  revisioning: { mode: "off" }
19833
20030
  });
19834
- const mutation = new _GovernedMutation(policy, receipt, baseline, lock);
20031
+ const mutation = new _GovernedMutation(policy, receipt, baseline, lock, true, beforeProviderCompletion);
19835
20032
  activeMutation = mutation;
19836
20033
  return mutation;
19837
20034
  }
19838
- async collectPaths() {
20035
+ async collectPaths(recover = false) {
19839
20036
  if (!this.receipt.repositoryRoot || !this.receipt.expectedHead || !this.baseline) return [];
19840
20037
  const declarations = [.../* @__PURE__ */ new Set([
19841
20038
  ...declaredMutationPaths(),
19842
20039
  ...readMutationPathDeclarations(this.receipt.operationId)
19843
20040
  ])].sort((a, b) => a.localeCompare(b));
19844
- if (this.receipt.provider) await assertHeadLease(
20041
+ const head = await currentHead(this.receipt.repositoryRoot);
20042
+ const committed = recover && !this.receipt.noCommit ? await committedRecoveryPaths(
19845
20043
  this.receipt.repositoryRoot,
19846
20044
  this.receipt.expectedHead,
19847
- await currentHead(this.receipt.repositoryRoot),
20045
+ head,
20046
+ declarations,
20047
+ this.receipt.paths,
20048
+ this.receipt.provider
20049
+ ) : [];
20050
+ if (this.receipt.provider && !recover) await assertHeadLease(
20051
+ this.receipt.repositoryRoot,
20052
+ this.receipt.expectedHead,
20053
+ head,
19848
20054
  this.receipt.noCommit ? [] : declarations,
19849
20055
  this.receipt.provider
19850
20056
  );
19851
- return collectIntroducedPaths(this.receipt.repositoryRoot, this.receipt.expectedHead, this.baseline, declarations);
20057
+ if (recover && this.receipt.noCommit) await assertHeadLease(
20058
+ this.receipt.repositoryRoot,
20059
+ this.receipt.expectedHead,
20060
+ head,
20061
+ [],
20062
+ this.receipt.provider
20063
+ );
20064
+ const introduced = await collectIntroducedPaths(this.receipt.repositoryRoot, this.receipt.expectedHead, this.baseline, declarations);
20065
+ return [...committed, ...introduced].sort((a, b) => a.path.localeCompare(b.path));
19852
20066
  }
19853
20067
  async close() {
19854
20068
  if (this.closed) return;
@@ -19863,13 +20077,13 @@ var init_coordinator = __esm({
19863
20077
 
19864
20078
  // src/transport/ownership-snapshot.ts
19865
20079
  import { createHash as createHash10 } from "crypto";
19866
- import { lstat as lstat4, readdir as readdir6, readFile as readFile14 } from "fs/promises";
19867
- import { dirname as dirname11, join as join14, relative as relative9, resolve as resolve18 } from "path";
20080
+ import { lstat as lstat4, readdir as readdir6, readFile as readFile15 } from "fs/promises";
20081
+ import { dirname as dirname12, join as join15, relative as relative9, resolve as resolve18 } from "path";
19868
20082
  async function assertSnapshotAncestors(path) {
19869
20083
  let current = resolve18(path);
19870
20084
  while (true) {
19871
20085
  if ((await lstat4(current)).isSymbolicLink()) throw new Error(`Symlink path is unsupported: ${current}`);
19872
- const parent = dirname11(current);
20086
+ const parent = dirname12(current);
19873
20087
  if (parent === current) return;
19874
20088
  current = parent;
19875
20089
  }
@@ -19884,9 +20098,9 @@ async function ownershipRuntimeSnapshot(path) {
19884
20098
  }
19885
20099
  hash3.update(JSON.stringify([relative9(path, candidate), info.isDirectory() ? "dir" : "file", info.mode & 4095]));
19886
20100
  if (info.isDirectory()) {
19887
- for (const name of (await readdir6(candidate)).sort()) await visit2(join14(candidate, name));
20101
+ for (const name of (await readdir6(candidate)).sort()) await visit2(join15(candidate, name));
19888
20102
  } else {
19889
- const content = await readFile14(candidate);
20103
+ const content = await readFile15(candidate);
19890
20104
  hash3.update(String(content.length)).update("\0").update(content);
19891
20105
  }
19892
20106
  }
@@ -19935,7 +20149,7 @@ __export(transaction_exports, {
19935
20149
  });
19936
20150
  import { createHash as createHash11 } from "crypto";
19937
20151
  import { cp as cp2, lstat as lstat5, mkdir as mkdir7, open as open4, rm as rm5, stat as stat4 } from "fs/promises";
19938
- import { dirname as dirname12, join as join15, relative as relative10, resolve as resolve19, sep as sep7 } from "path";
20152
+ import { dirname as dirname13, join as join16, relative as relative10, resolve as resolve19, sep as sep7 } from "path";
19939
20153
  async function assertNoSymlinkPath2(path) {
19940
20154
  const absolute = resolve19(path);
19941
20155
  let current = absolute;
@@ -19945,7 +20159,7 @@ async function assertNoSymlinkPath2(path) {
19945
20159
  } catch (error46) {
19946
20160
  if (error46.code !== "ENOENT") throw error46;
19947
20161
  }
19948
- const parent = dirname12(current);
20162
+ const parent = dirname13(current);
19949
20163
  if (parent === current) break;
19950
20164
  current = parent;
19951
20165
  }
@@ -19998,7 +20212,7 @@ function metadataAuditPath(audit, path) {
19998
20212
  if (resolve19(audit.workspaceRoot) !== audit.workspaceRoot || path !== `.agentwheel/${audit.kind === "ownership-handoff" ? "ownership-handoffs" : "ownership-releases"}/${audit.operationId}.json`) {
19999
20213
  throw new Error("Invalid ownership release audit path.");
20000
20214
  }
20001
- return join15(audit.workspaceRoot, ...path.split("/"));
20215
+ return join16(audit.workspaceRoot, ...path.split("/"));
20002
20216
  }
20003
20217
  function metadataRuntimePath(root, path) {
20004
20218
  const result = resolve19(root, path);
@@ -20016,7 +20230,7 @@ async function syncMetadataPath(path, directoryOnly = false) {
20016
20230
  await file2.close();
20017
20231
  }
20018
20232
  }
20019
- const directory = await open4(directoryOnly ? path : dirname12(path), "r");
20233
+ const directory = await open4(directoryOnly ? path : dirname13(path), "r");
20020
20234
  try {
20021
20235
  await directory.sync();
20022
20236
  } finally {
@@ -20025,19 +20239,19 @@ async function syncMetadataPath(path, directoryOnly = false) {
20025
20239
  }
20026
20240
  function applyLockPath(targetRoot, adapter, scope = {}) {
20027
20241
  const installationType = scope.installationType ?? "local";
20028
- return join15(metadataDir(targetRoot), `${stateKeyFor(adapter, { installationType })}.runtime-apply-lock`);
20242
+ return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, { installationType })}.runtime-apply-lock`);
20029
20243
  }
20030
20244
  function applyJournalPath(targetRoot, adapter, scope = {}) {
20031
- return join15(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-journal.json`);
20245
+ return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-journal.json`);
20032
20246
  }
20033
20247
  function applyBackupDir(targetRoot, adapter, scope = {}) {
20034
- return join15(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-backups`);
20248
+ return join16(metadataDir(targetRoot), `${stateKeyFor(adapter, scope)}.apply-backups`);
20035
20249
  }
20036
20250
  async function acquireApplyLock(targetRoot, adapter, transport = localTransport, options = {}, scope = {}) {
20037
20251
  assertGovernedRuntimeTransportSupported(transport);
20038
20252
  if (transport.kind === "local-run-as") await transport.prepareApply();
20039
20253
  const lockPath = applyLockPath(targetRoot, adapter, scope);
20040
- const ownerPath = join15(lockPath, "owner.json");
20254
+ const ownerPath = join16(lockPath, "owner.json");
20041
20255
  const metadata = {
20042
20256
  pid: process.pid,
20043
20257
  adapter,
@@ -20106,7 +20320,7 @@ async function listApplyJournals(targetRoot, adapter, transport = localTransport
20106
20320
  const found = [];
20107
20321
  for (const fileName of await transport.listDir(metadataDir(targetRoot))) {
20108
20322
  if (!fileName.endsWith(suffix)) continue;
20109
- const path = join15(metadataDir(targetRoot), fileName);
20323
+ const path = join16(metadataDir(targetRoot), fileName);
20110
20324
  const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
20111
20325
  if (journal.adapter !== adapter || (journal.installationType ?? "local") !== installationType) continue;
20112
20326
  found.push({ path, journal });
@@ -20118,7 +20332,7 @@ async function listAllApplyJournals(targetRoot, adapter, transport = localTransp
20118
20332
  const found = [];
20119
20333
  for (const fileName of await transport.listDir(metadataDir(targetRoot))) {
20120
20334
  if (!fileName.endsWith(suffix)) continue;
20121
- const path = join15(metadataDir(targetRoot), fileName);
20335
+ const path = join16(metadataDir(targetRoot), fileName);
20122
20336
  const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
20123
20337
  if (adapter === void 0 || journal.adapter === adapter) found.push({ path, journal });
20124
20338
  }
@@ -20166,7 +20380,7 @@ async function removeApplyJournal(targetRoot, adapter, transport = localTranspor
20166
20380
  if (existing?.mutation) await beginResolveMutationRuntimeJournal(existing.mutation.operationId, path);
20167
20381
  await transport.rm(applyJournalPath(targetRoot, adapter, scope));
20168
20382
  await transport.rm(applyBackupDir(targetRoot, adapter, scope));
20169
- if ((existing?.metadataAudit || existing?.metadataGuards) && transport.kind === "local") await syncMetadataPath(dirname12(path), true);
20383
+ if ((existing?.metadataAudit || existing?.metadataGuards) && transport.kind === "local") await syncMetadataPath(dirname13(path), true);
20170
20384
  if (existing?.mutation) await resolveMutationRuntimeJournal(existing.mutation.operationId, path);
20171
20385
  }
20172
20386
  async function abortApplyJournal(targetRoot, adapter, transport = localTransport, scope = {}) {
@@ -20176,7 +20390,7 @@ async function abortApplyJournal(targetRoot, adapter, transport = localTransport
20176
20390
  const journalPath = applyJournalPath(targetRoot, adapter, scope);
20177
20391
  if (!await transport.pathExists(journalPath)) return void 0;
20178
20392
  const stateKey = stateKeyFor(adapter, scope);
20179
- const archivePath = join15(metadataDir(targetRoot), "archive", `${stateKey}.apply-journal.failed-${journalTimestamp(/* @__PURE__ */ new Date())}.json`);
20393
+ const archivePath = join16(metadataDir(targetRoot), "archive", `${stateKey}.apply-journal.failed-${journalTimestamp(/* @__PURE__ */ new Date())}.json`);
20180
20394
  const content = await transport.readFile(journalPath);
20181
20395
  const journal = parseApplyJournal(JSON.parse(content));
20182
20396
  if (journal.metadataAudit || journal.metadataGuards) {
@@ -20309,7 +20523,7 @@ async function recordBackup(operation, index, targetRoot, adapter, transport = l
20309
20523
  hadExisting
20310
20524
  };
20311
20525
  }
20312
- const backupPath = join15(applyBackupDir(targetRoot, adapter, scope), String(index));
20526
+ const backupPath = join16(applyBackupDir(targetRoot, adapter, scope), String(index));
20313
20527
  if (transport.kind === "local-run-as") {
20314
20528
  assertGovernedRuntimeTransportSupported(transport);
20315
20529
  await transport.rm(backupPath);
@@ -20317,7 +20531,7 @@ async function recordBackup(operation, index, targetRoot, adapter, transport = l
20317
20531
  await transport.copyWithin(operation.destPath, backupPath, operation.kind);
20318
20532
  } else {
20319
20533
  await rm5(backupPath, { recursive: true, force: true });
20320
- await mkdir7(dirname12(backupPath), { recursive: true });
20534
+ await mkdir7(dirname13(backupPath), { recursive: true });
20321
20535
  await cp2(operation.destPath, backupPath, { recursive: operation.kind === "dir", dereference: true });
20322
20536
  }
20323
20537
  return {
@@ -20388,7 +20602,7 @@ function assertApplyJournalCompletedOperations(journal) {
20388
20602
  if (!operation || !["create", "update", "remove"].includes(operation.action) || item.destPath !== operation.destPath || item.kind !== operation.kind || typeof item.hadExisting !== "boolean" || item.completed !== void 0 && typeof item.completed !== "boolean") {
20389
20603
  throw new Error("Apply journal completion does not match its immutable operation.");
20390
20604
  }
20391
- const expectedBackup = join15(applyBackupDir(journal.targetRoot, journal.adapter, {
20605
+ const expectedBackup = join16(applyBackupDir(journal.targetRoot, journal.adapter, {
20392
20606
  installationType: journal.installationType,
20393
20607
  stateKey: journal.stateKey
20394
20608
  }), String(item.index));
@@ -20414,16 +20628,25 @@ var init_transaction = __esm({
20414
20628
  });
20415
20629
 
20416
20630
  // src/install/toml-merge.ts
20417
- import { mkdir as mkdir8, readFile as readFile16, writeFile as writeFile8 } from "fs/promises";
20418
- import { parse as parseToml } from "smol-toml";
20419
- import { dirname as dirname13 } from "path";
20631
+ import { mkdir as mkdir8, readFile as readFile17, writeFile as writeFile8 } from "fs/promises";
20632
+ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
20633
+ import { dirname as dirname14 } from "path";
20420
20634
  async function mergeCodexTomlMcp(sourcePath, destPath) {
20421
- const source = JSON.parse(await readFile16(sourcePath, "utf8"));
20635
+ const source = JSON.parse(await readFile17(sourcePath, "utf8"));
20422
20636
  const servers = extractMcpServers(source);
20423
- const current = await pathExists(destPath) ? await readFile16(destPath, "utf8") : "";
20424
- const withoutManaged = removeManagedMcpSections(current, Object.keys(servers));
20425
- const merged = appendMcpServers(withoutManaged, servers);
20426
- await mkdir8(dirname13(destPath), { recursive: true });
20637
+ const current = await pathExists(destPath) ? await readFile17(destPath, "utf8") : "";
20638
+ const parsed = parseToml(current, { integersAsBigInt: "asNeeded" });
20639
+ const currentServers = isPlainRecord(parsed.mcp_servers) ? parsed.mcp_servers : {};
20640
+ const blocks = [];
20641
+ for (const [name, server] of Object.entries(servers).sort(([a], [b]) => a.localeCompare(b))) {
20642
+ const rendered = parseToml(formatMcpServer(name, server), { integersAsBigInt: "asNeeded" });
20643
+ const declared = rendered.mcp_servers[name];
20644
+ const mergedServer = mergeManagedFields(currentServers[name], declared);
20645
+ blocks.push(managedValueMatches(declared, mergedServer) ? formatMcpServer(name, server) : stringifyToml({ mcp_servers: { [name]: mergedServer } }).trimEnd());
20646
+ }
20647
+ const merged = appendMcpServers(removeManagedMcpSections(current, Object.keys(servers)), blocks);
20648
+ parseToml(merged, { integersAsBigInt: "asNeeded" });
20649
+ await mkdir8(dirname14(destPath), { recursive: true });
20427
20650
  await writeFile8(destPath, merged, "utf8");
20428
20651
  }
20429
20652
  function mismatchedCodexTomlMcpServers(source, currentContent) {
@@ -20465,7 +20688,7 @@ function isPlainRecord(value) {
20465
20688
  }
20466
20689
  function extractMcpServers(source) {
20467
20690
  const raw = isRecord2(source.mcpServers) ? source.mcpServers : source;
20468
- const servers = {};
20691
+ const servers = /* @__PURE__ */ Object.create(null);
20469
20692
  for (const [name, value] of Object.entries(raw)) {
20470
20693
  if (!isRecord2(value)) continue;
20471
20694
  servers[name] = value;
@@ -20476,23 +20699,39 @@ function extractMcpServers(source) {
20476
20699
  return servers;
20477
20700
  }
20478
20701
  function removeManagedMcpSections(content, serverNames) {
20479
- if (serverNames.length === 0 || content.trim() === "") return content;
20480
20702
  const names = new Set(serverNames);
20481
- const lines = content.split(/\r?\n/);
20482
20703
  const kept = [];
20483
20704
  let skipping = false;
20484
- for (const line of lines) {
20485
- const section = line.match(/^\s*\[([^\]]+)]\s*$/)?.[1];
20486
- if (section) {
20487
- const match = section.match(/^mcp_servers\.([^.\]]+)(?:\.|$)/);
20488
- skipping = match ? names.has(unquoteTomlKey(match[1] ?? "")) : false;
20705
+ let offset = 0;
20706
+ for (const line of content.split(/(?<=\n)/)) {
20707
+ if (line.trimStart().startsWith("[")) {
20708
+ try {
20709
+ parseToml(content.slice(0, offset), { integersAsBigInt: "asNeeded" });
20710
+ const header = parseToml(line, { integersAsBigInt: "asNeeded" });
20711
+ const servers = isPlainRecord(header.mcp_servers) ? header.mcp_servers : {};
20712
+ skipping = Object.keys(servers).some((name) => names.has(name));
20713
+ } catch {
20714
+ }
20489
20715
  }
20490
20716
  if (!skipping) kept.push(line);
20717
+ offset += line.length;
20491
20718
  }
20492
- return kept.join("\n").replace(/\n{3,}$/g, "\n\n");
20719
+ return kept.join("");
20720
+ }
20721
+ function mergeManagedFields(current, declared) {
20722
+ if (!isPlainRecord(declared)) return declared;
20723
+ const merged = isPlainRecord(current) ? { ...current } : {};
20724
+ for (const [key, value] of Object.entries(declared)) {
20725
+ Object.defineProperty(merged, key, {
20726
+ value: mergeManagedFields(Object.hasOwn(merged, key) ? merged[key] : void 0, value),
20727
+ enumerable: true,
20728
+ configurable: true,
20729
+ writable: true
20730
+ });
20731
+ }
20732
+ return merged;
20493
20733
  }
20494
- function appendMcpServers(content, servers) {
20495
- const blocks = Object.entries(servers).sort(([a], [b]) => a.localeCompare(b)).map(([name, server]) => formatMcpServer(name, server));
20734
+ function appendMcpServers(content, blocks) {
20496
20735
  const prefix = content.trimEnd();
20497
20736
  return `${prefix ? `${prefix}
20498
20737
 
@@ -20572,14 +20811,14 @@ var init_toml_merge = __esm({
20572
20811
  });
20573
20812
 
20574
20813
  // src/install/yaml-merge.ts
20575
- import { mkdir as mkdir9, readFile as readFile17, writeFile as writeFile9 } from "fs/promises";
20576
- import { dirname as dirname14 } from "path";
20814
+ import { mkdir as mkdir9, readFile as readFile18, writeFile as writeFile9 } from "fs/promises";
20815
+ import { dirname as dirname15 } from "path";
20577
20816
  import { parse as parse7, stringify } from "yaml";
20578
20817
  async function mergeYamlFile(sourcePath, destPath) {
20579
- const source = parseYamlValue(await readFile17(sourcePath, "utf8"));
20580
- const current = await pathExists(destPath) ? parseYamlValue(await readFile17(destPath, "utf8")) : {};
20818
+ const source = parseYamlValue(await readFile18(sourcePath, "utf8"));
20819
+ const current = await pathExists(destPath) ? parseYamlValue(await readFile18(destPath, "utf8")) : {};
20581
20820
  const merged = deepMerge2(current, source);
20582
- await mkdir9(dirname14(destPath), { recursive: true });
20821
+ await mkdir9(dirname15(destPath), { recursive: true });
20583
20822
  await writeFile9(destPath, stringify(merged), "utf8");
20584
20823
  }
20585
20824
  function parseYamlValue(content) {
@@ -20637,8 +20876,8 @@ var init_yaml_merge = __esm({
20637
20876
  });
20638
20877
 
20639
20878
  // src/install/merge-removal.ts
20640
- import { mkdir as mkdir10, readFile as readFile18, writeFile as writeFile10 } from "fs/promises";
20641
- import { dirname as dirname15 } from "path";
20879
+ import { mkdir as mkdir10, readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
20880
+ import { dirname as dirname16 } from "path";
20642
20881
  import { parse as parse8, stringify as stringify2 } from "yaml";
20643
20882
  function assertExactMergeContribution(contribution, strategy, currentContent) {
20644
20883
  if (strategy === "codex-toml-mcp") {
@@ -20715,7 +20954,7 @@ async function mergeRemovalForInstall(sourcePath, strategy, currentContent, opti
20715
20954
  return introducedMergeContent(parseMergeDestination(currentContent, strategy), source);
20716
20955
  }
20717
20956
  async function removeMergeContribution(destPath, strategy, removal) {
20718
- const content = await readFile18(destPath, "utf8");
20957
+ const content = await readFile19(destPath, "utf8");
20719
20958
  if (strategy === "codex-toml-mcp") {
20720
20959
  const servers = isRecord4(removal.mcpServers) ? removal.mcpServers : removal;
20721
20960
  await writeFile10(destPath, removeCodexTomlMcpSections(content, Object.keys(servers)), "utf8");
@@ -20723,7 +20962,7 @@ async function removeMergeContribution(destPath, strategy, removal) {
20723
20962
  }
20724
20963
  const current = parseMergeDestination(content, strategy);
20725
20964
  removeIntroducedContent(current, removal);
20726
- await mkdir10(dirname15(destPath), { recursive: true });
20965
+ await mkdir10(dirname16(destPath), { recursive: true });
20727
20966
  await writeFile10(destPath, strategy === "yaml-deep" ? stringify2(current) : `${JSON.stringify(current, null, 2)}
20728
20967
  `, "utf8");
20729
20968
  }
@@ -20739,7 +20978,7 @@ async function readMergeSource(sourcePath, strategy) {
20739
20978
  if (strategy === "openclaw-json-deep") {
20740
20979
  return requireRecord(await renderOpenClawJsonMergeSource(sourcePath), "OpenClaw JSON merge source");
20741
20980
  }
20742
- const content = await readFile18(sourcePath, "utf8");
20981
+ const content = await readFile19(sourcePath, "utf8");
20743
20982
  if (strategy === "yaml-deep") return requireRecord(normalizeYamlValue2(parse8(content)), "YAML merge source");
20744
20983
  return requireRecord(JSON.parse(content), "JSON merge source");
20745
20984
  }
@@ -20991,9 +21230,9 @@ var init_desired = __esm({
20991
21230
 
20992
21231
  // src/install/instructions-block.ts
20993
21232
  import { createHash as createHash12 } from "crypto";
20994
- import { mkdtemp as mkdtemp2, readFile as readFile19, realpath as realpath2, rm as rm6, writeFile as writeFile11 } from "fs/promises";
21233
+ import { mkdtemp as mkdtemp2, readFile as readFile20, realpath as realpath2, rm as rm6, writeFile as writeFile11 } from "fs/promises";
20995
21234
  import { tmpdir as tmpdir3 } from "os";
20996
- import { basename as basename2, dirname as dirname16, join as join16, relative as relative11 } from "path";
21235
+ import { basename as basename2, dirname as dirname17, join as join17, relative as relative11 } from "path";
20997
21236
  function exactManagedInstructionBlockSnapshot(content, selector) {
20998
21237
  const beginCount = [...content.matchAll(new RegExp(`<!-- BEGIN openpack:include ${escapeRegex2(selector)}(?=\\s|-->)`, "gu"))].length;
20999
21238
  const endCount = [...content.matchAll(new RegExp(`<!-- END openpack:include ${escapeRegex2(selector)}(?=\\s|-->)`, "gu"))].length;
@@ -21044,7 +21283,7 @@ function exactManagedInstructionBlockSnapshot(content, selector) {
21044
21283
  };
21045
21284
  }
21046
21285
  async function desiredManagedInstructionBlockHash(sourcePath) {
21047
- const source = await readFile19(sourcePath, "utf8");
21286
+ const source = await readFile20(sourcePath, "utf8");
21048
21287
  return hashText(managedBlockBody(source));
21049
21288
  }
21050
21289
  async function readManagedInstructionBlockState(destPath, selector, transport) {
@@ -21064,7 +21303,7 @@ async function readManagedInstructionBlockState(destPath, selector, transport) {
21064
21303
  };
21065
21304
  }
21066
21305
  async function writeManagedInstructionBlock(sourcePath, destPath, selector, transport, options = {}) {
21067
- const source = await readFile19(sourcePath, "utf8");
21306
+ const source = await readFile20(sourcePath, "utf8");
21068
21307
  const desired = renderManagedInstructionBlock(selector, source);
21069
21308
  const existing = await readOptionalText(destPath, transport);
21070
21309
  const merged = upsertManagedInstructionBlock(existing ?? "", selector, desired.block, options);
@@ -21176,7 +21415,7 @@ function assertCleanBlock(block, selector) {
21176
21415
  }
21177
21416
  }
21178
21417
  function referencesAgentsMd(content, claudePath, agentsPath) {
21179
- const claudeDir = dirname16(claudePath);
21418
+ const claudeDir = dirname17(claudePath);
21180
21419
  for (const rawLine of content.split(/\r?\n/)) {
21181
21420
  const line = rawLine.trim();
21182
21421
  const atImport = /^@import\s+(.+)$/i.exec(line);
@@ -21185,8 +21424,8 @@ function referencesAgentsMd(content, claudePath, agentsPath) {
21185
21424
  if (!referenced) continue;
21186
21425
  const cleaned = referenced.trim().replace(/^["']|["']$/g, "");
21187
21426
  if (!/AGENTS\.md$/i.test(cleaned)) continue;
21188
- const candidate = cleaned.startsWith("/") ? cleaned : join16(claudeDir, cleaned);
21189
- if (relative11(dirname16(agentsPath), candidate).replaceAll("\\", "/") === "AGENTS.md") return true;
21427
+ const candidate = cleaned.startsWith("/") ? cleaned : join17(claudeDir, cleaned);
21428
+ if (relative11(dirname17(agentsPath), candidate).replaceAll("\\", "/") === "AGENTS.md") return true;
21190
21429
  if (candidate === agentsPath) return true;
21191
21430
  }
21192
21431
  return false;
@@ -21205,8 +21444,8 @@ async function writeTextWithTransport(path, content, transport) {
21205
21444
  await transport.writeFileAtomic(path, content);
21206
21445
  return;
21207
21446
  }
21208
- const tempRoot = await mkdtemp2(join16(tmpdir3(), "agentwheel-instructions-"));
21209
- const localPath = join16(tempRoot, basename2(path) || "instructions.md");
21447
+ const tempRoot = await mkdtemp2(join17(tmpdir3(), "agentwheel-instructions-"));
21448
+ const localPath = join17(tempRoot, basename2(path) || "instructions.md");
21210
21449
  try {
21211
21450
  await writeFile11(localPath, content, "utf8");
21212
21451
  await transport.atomicCopy(localPath, path, "file");
@@ -21244,9 +21483,9 @@ __export(apply_exports, {
21244
21483
  });
21245
21484
  import { execFile as execFile5 } from "child_process";
21246
21485
  import { createHash as createHash13, randomUUID as randomUUID3 } from "crypto";
21247
- import { chmod as chmod3, link as link2, lstat as lstat6, mkdir as mkdir11, mkdtemp as mkdtemp3, open as open5, readFile as readFile20, rm as rm7, writeFile as writeFile12 } from "fs/promises";
21486
+ import { chmod as chmod3, link as link2, lstat as lstat6, mkdir as mkdir11, mkdtemp as mkdtemp3, open as open5, readFile as readFile21, rm as rm7, writeFile as writeFile12 } from "fs/promises";
21248
21487
  import { tmpdir as tmpdir4 } from "os";
21249
- import { basename as basename3, dirname as dirname17, join as join17, resolve as resolve20 } from "path";
21488
+ import { basename as basename3, dirname as dirname18, join as join18, resolve as resolve20 } from "path";
21250
21489
  import { promisify as promisify5 } from "util";
21251
21490
  async function applyInstallPlan(plan, sourceLock, options = {}) {
21252
21491
  return applyPlanTransactionally(plan, { ...options, sourceLock });
@@ -21346,6 +21585,10 @@ async function assertRuntimeStateRevision(plan, transport) {
21346
21585
  async function applyPlanTransactionally(plan, options = {}) {
21347
21586
  const transport = options.transport ?? localTransport;
21348
21587
  const scope = { installationType: plan.installationType, stateKey: plan.stateKey };
21588
+ const openClawAcceptCapabilities = createOpenClawCapabilityDetector(async (args) => {
21589
+ if (transport.kind === "local") return (await execFileAsync4("openclaw", args, { timeout: 1e4 })).stdout;
21590
+ return transport.execFile?.("openclaw", args, { cwd: plan.targetRoot });
21591
+ });
21349
21592
  if (plan.hasBlockingChanges) {
21350
21593
  const blockers = plan.operations.filter((operation) => operation.action === "drift" || operation.action === "conflict");
21351
21594
  throw new Error(`Refusing to apply with blocking changes: ${blockers.map((item) => item.relativeDestPath).join(", ")}`);
@@ -21406,6 +21649,7 @@ async function applyPlanTransactionally(plan, options = {}) {
21406
21649
  transport,
21407
21650
  now,
21408
21651
  executePlugins: options.executePlugins,
21652
+ openClawAcceptCapabilities,
21409
21653
  graphLockDigest,
21410
21654
  plan
21411
21655
  });
@@ -21641,7 +21885,7 @@ async function assertCommittedJournalState(journal, expectedManifest, transport)
21641
21885
  }
21642
21886
  }
21643
21887
  if (journal.workspaceConfigPath && journal.workspaceConfig) {
21644
- const actual = JSON.parse(await readFile20(journal.workspaceConfigPath, "utf8"));
21888
+ const actual = JSON.parse(await readFile21(journal.workspaceConfigPath, "utf8"));
21645
21889
  if (canonicalJson5(actual) !== canonicalJson5(journal.workspaceConfig)) {
21646
21890
  throw new Error(`Workspace config postcheck failed for ${journal.workspaceConfigPath}.`);
21647
21891
  }
@@ -21663,7 +21907,7 @@ async function assertMetadataAuditGuards(journal, after, transport, requireAfter
21663
21907
  throw new Error("Metadata-audit content digest is invalid.");
21664
21908
  }
21665
21909
  try {
21666
- if (await readFile20(path, "utf8") !== file2.content) throw new Error(`Metadata-audit file changed: ${path}`);
21910
+ if (await readFile21(path, "utf8") !== file2.content) throw new Error(`Metadata-audit file changed: ${path}`);
21667
21911
  } catch (error46) {
21668
21912
  if (error46.code !== "ENOENT" || requireAfter) throw error46;
21669
21913
  }
@@ -21714,7 +21958,7 @@ async function createPrivateAuditDirectory(path) {
21714
21958
  } catch (error46) {
21715
21959
  if (error46.code !== "ENOENT") throw error46;
21716
21960
  }
21717
- await createPrivateAuditDirectory(dirname17(path));
21961
+ await createPrivateAuditDirectory(dirname18(path));
21718
21962
  try {
21719
21963
  await mkdir11(path, { mode: 448 });
21720
21964
  } catch (error46) {
@@ -21725,14 +21969,14 @@ async function createPrivateAuditDirectory(path) {
21725
21969
  }
21726
21970
  await chmod3(path, 448);
21727
21971
  await syncMetadataPath(path, true);
21728
- await syncMetadataPath(dirname17(path), true);
21972
+ await syncMetadataPath(dirname18(path), true);
21729
21973
  }
21730
21974
  async function writeAuditFileExclusive(path, content, validateCallerPath) {
21731
21975
  await assertNoSymlinkPath2(path);
21732
- await createPrivateAuditDirectory(dirname17(path));
21976
+ await createPrivateAuditDirectory(dirname18(path));
21733
21977
  await assertNoSymlinkPath2(path);
21734
21978
  await validateCallerPath();
21735
- await syncMetadataPath(dirname17(dirname17(path)), true);
21979
+ await syncMetadataPath(dirname18(dirname18(path)), true);
21736
21980
  const temporary = `${path}.pending-${randomUUID3()}`;
21737
21981
  try {
21738
21982
  const handle = await open5(temporary, "wx", 384);
@@ -21746,9 +21990,9 @@ async function writeAuditFileExclusive(path, content, validateCallerPath) {
21746
21990
  try {
21747
21991
  await link2(temporary, path);
21748
21992
  } catch (error46) {
21749
- if (error46.code !== "EEXIST" || await readFile20(path, "utf8") !== content) throw error46;
21993
+ if (error46.code !== "EEXIST" || await readFile21(path, "utf8") !== content) throw error46;
21750
21994
  }
21751
- const directory = await open5(dirname17(path), "r");
21995
+ const directory = await open5(dirname18(path), "r");
21752
21996
  try {
21753
21997
  await directory.sync();
21754
21998
  } finally {
@@ -21771,7 +22015,7 @@ async function applyOperation(operation, context) {
21771
22015
  throw new Error(`Invalid plugin operation missing hash: ${operation.relativeDestPath}`);
21772
22016
  }
21773
22017
  if (context.executePlugins) {
21774
- await executePluginInstall(operation, transport);
22018
+ await executePluginInstall(operation, transport, context.openClawAcceptCapabilities);
21775
22019
  }
21776
22020
  return manifestEntryForOperation(operation, {
21777
22021
  now,
@@ -21931,8 +22175,15 @@ async function applyOperation(operation, context) {
21931
22175
  }
21932
22176
  return void 0;
21933
22177
  }
21934
- async function executePluginInstall(operation, transport) {
21935
- const commands = semanticInstallCommands(operation);
22178
+ async function executePluginInstall(operation, transport, openClawAcceptCapabilities) {
22179
+ const commands = await Promise.all(semanticInstallCommands(operation).map(async (command) => {
22180
+ if (command.length !== 5 || command.slice(0, 4).join(" ") !== "openclaw plugins install --force") return command;
22181
+ return openClawPluginInstallCommand({
22182
+ path: command[4],
22183
+ dryRun: false,
22184
+ acceptCapabilities: await openClawAcceptCapabilities?.() ?? false
22185
+ });
22186
+ }));
21936
22187
  if (commands.length === 0) throw new Error(`Invalid plugin operation missing command: ${operation.relativeDestPath}`);
21937
22188
  if (!operation.sourcePath) {
21938
22189
  throw new Error(`Invalid plugin operation missing source path: ${operation.relativeDestPath}`);
@@ -21980,10 +22231,10 @@ async function prepareSemanticPluginState(operation, transport) {
21980
22231
  async function prepareClaudeMarketplace(operation, transport) {
21981
22232
  const spec = requireSemanticPluginState(operation);
21982
22233
  const marketplaceName = requireMarketplaceName(operation);
21983
- const marketplaceRoot = join17(spec.stateRoot, "marketplace");
22234
+ const marketplaceRoot = join18(spec.stateRoot, "marketplace");
21984
22235
  await transport.rm(spec.stateRoot);
21985
- await transport.atomicCopy(requireSourcePath(operation), join17(marketplaceRoot, "plugins", spec.pluginName), operation.kind);
21986
- await transport.writeJsonAtomic(join17(marketplaceRoot, ".claude-plugin", "marketplace.json"), {
22236
+ await transport.atomicCopy(requireSourcePath(operation), join18(marketplaceRoot, "plugins", spec.pluginName), operation.kind);
22237
+ await transport.writeJsonAtomic(join18(marketplaceRoot, ".claude-plugin", "marketplace.json"), {
21987
22238
  name: marketplaceName,
21988
22239
  owner: { name: "Agentwheel" },
21989
22240
  plugins: [
@@ -21998,10 +22249,10 @@ async function prepareClaudeMarketplace(operation, transport) {
21998
22249
  async function prepareCodexMarketplace(operation, transport) {
21999
22250
  const spec = requireSemanticPluginState(operation);
22000
22251
  const marketplaceName = requireMarketplaceName(operation);
22001
- const marketplaceRoot = join17(spec.stateRoot, "marketplace");
22252
+ const marketplaceRoot = join18(spec.stateRoot, "marketplace");
22002
22253
  await transport.rm(spec.stateRoot);
22003
- await transport.atomicCopy(requireSourcePath(operation), join17(marketplaceRoot, "plugins", spec.pluginName), operation.kind);
22004
- await transport.writeJsonAtomic(join17(marketplaceRoot, ".agents", "plugins", "marketplace.json"), {
22254
+ await transport.atomicCopy(requireSourcePath(operation), join18(marketplaceRoot, "plugins", spec.pluginName), operation.kind);
22255
+ await transport.writeJsonAtomic(join18(marketplaceRoot, ".agents", "plugins", "marketplace.json"), {
22005
22256
  name: marketplaceName,
22006
22257
  interface: {
22007
22258
  displayName: "Agentwheel"
@@ -22025,11 +22276,11 @@ async function prepareCodexMarketplace(operation, transport) {
22025
22276
  async function prepareCopilotPlugin(operation, transport) {
22026
22277
  const spec = requireSemanticPluginState(operation);
22027
22278
  await transport.rm(spec.stateRoot);
22028
- await transport.atomicCopy(requireSourcePath(operation), join17(spec.stateRoot, "plugin"), operation.kind);
22279
+ await transport.atomicCopy(requireSourcePath(operation), join18(spec.stateRoot, "plugin"), operation.kind);
22029
22280
  }
22030
22281
  async function prepareHermesGitShim(operation, transport) {
22031
22282
  const spec = requireSemanticPluginState(operation);
22032
- const repoRoot = join17(spec.stateRoot, "repo");
22283
+ const repoRoot = join18(spec.stateRoot, "repo");
22033
22284
  await transport.rm(spec.stateRoot);
22034
22285
  await transport.atomicCopy(requireSourcePath(operation), repoRoot, operation.kind);
22035
22286
  if (!transport.execFile) {
@@ -22084,8 +22335,8 @@ async function executeSemanticCommands(operation, commands, transport, options =
22084
22335
  if (!operation.sourcePath) {
22085
22336
  throw new Error(`Invalid semantic plugin operation missing source path: ${operation.relativeDestPath}`);
22086
22337
  }
22087
- const stagingRoot = join17(operation.destPath, ".agentwheel", "plugin-staging", `${process.pid}-${Date.now()}`);
22088
- const remoteSourcePath = join17(stagingRoot, basename3(operation.sourcePath));
22338
+ const stagingRoot = join18(operation.destPath, ".agentwheel", "plugin-staging", `${process.pid}-${Date.now()}`);
22339
+ const remoteSourcePath = join18(stagingRoot, basename3(operation.sourcePath));
22089
22340
  try {
22090
22341
  await transport.atomicCopy(operation.sourcePath, remoteSourcePath, operation.kind);
22091
22342
  for (const [command, ...args] of commands) {
@@ -22352,8 +22603,8 @@ async function mergeWithTransport(sourcePath, destPath, transport, merge2) {
22352
22603
  await merge2(sourcePath, destPath);
22353
22604
  return;
22354
22605
  }
22355
- const tempRoot = await mkdtemp3(join17(tmpdir4(), "agentwheel-merge-"));
22356
- const localDest = join17(tempRoot, basename3(destPath) || "merged");
22606
+ const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-merge-"));
22607
+ const localDest = join18(tempRoot, basename3(destPath) || "merged");
22357
22608
  try {
22358
22609
  if (await transport.pathExists(destPath)) {
22359
22610
  await writeFile12(localDest, await transport.readFile(destPath), "utf8");
@@ -22369,8 +22620,8 @@ async function removeMergeWithTransport(destPath, strategy, removal, transport)
22369
22620
  await removeMergeContribution(destPath, strategy, removal);
22370
22621
  return;
22371
22622
  }
22372
- const tempRoot = await mkdtemp3(join17(tmpdir4(), "agentwheel-merge-remove-"));
22373
- const localDest = join17(tempRoot, basename3(destPath) || "merged");
22623
+ const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-merge-remove-"));
22624
+ const localDest = join18(tempRoot, basename3(destPath) || "merged");
22374
22625
  try {
22375
22626
  await writeFile12(localDest, await transport.readFile(destPath), "utf8");
22376
22627
  await removeMergeContribution(localDest, strategy, removal);
@@ -22380,8 +22631,8 @@ async function removeMergeWithTransport(destPath, strategy, removal, transport)
22380
22631
  }
22381
22632
  }
22382
22633
  async function mergeOpenClawJsonWithTransport(sourcePath, destPath, transport) {
22383
- const tempRoot = await mkdtemp3(join17(tmpdir4(), "agentwheel-openclaw-merge-"));
22384
- const localDest = join17(tempRoot, basename3(destPath) || "openclaw.json");
22634
+ const tempRoot = await mkdtemp3(join18(tmpdir4(), "agentwheel-openclaw-merge-"));
22635
+ const localDest = join18(tempRoot, basename3(destPath) || "openclaw.json");
22385
22636
  const validationPath = transport.kind === "local" ? localDest : `${destPath}.validate-agentwheel-${process.pid}-${Date.now()}`;
22386
22637
  try {
22387
22638
  if (await transport.pathExists(destPath)) {
@@ -22407,8 +22658,8 @@ async function validateOpenClawConfig(configPath, destPath, transport) {
22407
22658
  if (!transport.execFile) {
22408
22659
  throw new Error(`Cannot validate OpenClaw config over ${transport.description}: transport does not support command execution.`);
22409
22660
  }
22410
- const openClawHome = dirname17(destPath);
22411
- const bundledBin = join17(openClawHome, "npm", "node_modules", ".bin", "openclaw");
22661
+ const openClawHome = dirname18(destPath);
22662
+ const bundledBin = join18(openClawHome, "npm", "node_modules", ".bin", "openclaw");
22412
22663
  const script = String.raw`
22413
22664
  set -euo pipefail
22414
22665
  cfg=$1
@@ -22436,6 +22687,7 @@ var init_apply = __esm({
22436
22687
  init_declarations();
22437
22688
  init_graph_lock();
22438
22689
  init_transport();
22690
+ init_openclaw2();
22439
22691
  init_run_as_policy();
22440
22692
  init_json_merge();
22441
22693
  init_openclaw_json_merge();
@@ -22494,7 +22746,7 @@ import { createHash as createHash32 } from "crypto";
22494
22746
  import { existsSync } from "fs";
22495
22747
  import { mkdir as mkdir28, mkdtemp as mkdtemp6, readFile as readFile45, realpath as realpath4, rm as rm16, writeFile as writeFile24 } from "fs/promises";
22496
22748
  import { homedir as homedir18, tmpdir as tmpdir7 } from "os";
22497
- import { basename as basename24, dirname as dirname41, isAbsolute as isAbsolute17, join as join66, relative as relative22, resolve as resolve48, sep as sep12 } from "path";
22749
+ import { basename as basename24, dirname as dirname42, isAbsolute as isAbsolute17, join as join66, relative as relative22, resolve as resolve48, sep as sep12 } from "path";
22498
22750
  import { fileURLToPath as fileURLToPath4 } from "url";
22499
22751
  import { Command } from "commander";
22500
22752
 
@@ -22586,8 +22838,8 @@ import { basename as basename8, join as join28, relative as relative12 } from "p
22586
22838
 
22587
22839
  // src/staging/codex-subagents.ts
22588
22840
  init_fs();
22589
- import { mkdir as mkdir12, readFile as readFile21, writeFile as writeFile13 } from "fs/promises";
22590
- import { basename as basename4, dirname as dirname18, join as join18 } from "path";
22841
+ import { mkdir as mkdir12, readFile as readFile22, writeFile as writeFile13 } from "fs/promises";
22842
+ import { basename as basename4, dirname as dirname19, join as join19 } from "path";
22591
22843
  import { parse as parseYaml } from "yaml";
22592
22844
  var requiredCodexAgentFields = ["name", "description", "developer_instructions"];
22593
22845
  async function renderCodexSubagents(artifacts, stageRoot, adapter) {
@@ -22611,36 +22863,36 @@ async function renderCodexSubagents(artifacts, stageRoot, adapter) {
22611
22863
  async function renderCodexSubagent(artifact, stageRoot) {
22612
22864
  const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
22613
22865
  const agentName = codexAgentName(artifact);
22614
- const renderedPath = join18(stageRoot, ".agentwheel-rendered", "codex-subagents", `${agentName}.toml`);
22866
+ const renderedPath = join19(stageRoot, ".agentwheel-rendered", "codex-subagents", `${agentName}.toml`);
22615
22867
  const lowerSourcePath = sourcePath.toLowerCase();
22616
22868
  if (artifact.kind === "file" && (artifact.name.toLowerCase().endsWith(".toml") || lowerSourcePath.endsWith(".toml"))) {
22617
- const content = await readFile21(sourcePath, "utf8");
22869
+ const content = await readFile22(sourcePath, "utf8");
22618
22870
  validateCodexAgentToml(content, sourcePath);
22619
22871
  return {
22620
22872
  ...artifact,
22621
22873
  name: agentName,
22622
- relativePath: join18("subagents", `${agentName}.toml`),
22874
+ relativePath: join19("subagents", `${agentName}.toml`),
22623
22875
  kind: "file",
22624
22876
  hash: await hashPath(sourcePath)
22625
22877
  };
22626
22878
  }
22627
- const markdownPath = artifact.kind === "dir" ? join18(sourcePath, "AGENTS.md") : sourcePath;
22879
+ const markdownPath = artifact.kind === "dir" ? join19(sourcePath, "AGENTS.md") : sourcePath;
22628
22880
  if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
22629
22881
  throw new Error(`Codex subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
22630
22882
  }
22631
22883
  if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !lowerSourcePath.endsWith(".md")) {
22632
22884
  throw new Error(`Codex subagent ${artifact.relativePath} must be a .toml file, .md file, or directory containing AGENTS.md.`);
22633
22885
  }
22634
- const markdown = await readFile21(markdownPath, "utf8");
22886
+ const markdown = await readFile22(markdownPath, "utf8");
22635
22887
  const toml = markdownToCodexAgentToml(agentName, markdown);
22636
- await mkdir12(dirname18(renderedPath), { recursive: true });
22888
+ await mkdir12(dirname19(renderedPath), { recursive: true });
22637
22889
  await writeFile13(renderedPath, toml, "utf8");
22638
22890
  return {
22639
22891
  ...artifact,
22640
22892
  name: agentName,
22641
22893
  sourcePath: renderedPath,
22642
22894
  stagedPath: renderedPath,
22643
- relativePath: join18("subagents", `${agentName}.toml`),
22895
+ relativePath: join19("subagents", `${agentName}.toml`),
22644
22896
  kind: "file",
22645
22897
  hash: await hashPath(renderedPath)
22646
22898
  };
@@ -22715,8 +22967,8 @@ function escapeRegExp2(value) {
22715
22967
 
22716
22968
  // src/staging/copilot-artifacts.ts
22717
22969
  init_fs();
22718
- import { mkdir as mkdir13, readFile as readFile22, writeFile as writeFile14 } from "fs/promises";
22719
- import { basename as basename5, dirname as dirname19, join as join19 } from "path";
22970
+ import { mkdir as mkdir13, readFile as readFile23, writeFile as writeFile14 } from "fs/promises";
22971
+ import { basename as basename5, dirname as dirname20, join as join20 } from "path";
22720
22972
  async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
22721
22973
  if (adapter?.name !== "copilot") return artifacts;
22722
22974
  const names = /* @__PURE__ */ new Set();
@@ -22738,23 +22990,23 @@ async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
22738
22990
  async function renderCopilotSubagent(artifact, stageRoot) {
22739
22991
  const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
22740
22992
  const agentName = copilotAgentName(artifact);
22741
- const renderedPath = join19(stageRoot, ".agentwheel-rendered", "copilot-subagents", `${agentName}.agent.md`);
22742
- const markdownPath = artifact.kind === "dir" ? join19(sourcePath, "AGENTS.md") : sourcePath;
22993
+ const renderedPath = join20(stageRoot, ".agentwheel-rendered", "copilot-subagents", `${agentName}.agent.md`);
22994
+ const markdownPath = artifact.kind === "dir" ? join20(sourcePath, "AGENTS.md") : sourcePath;
22743
22995
  if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
22744
22996
  throw new Error(`Copilot subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
22745
22997
  }
22746
22998
  if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md")) {
22747
22999
  throw new Error(`Copilot subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
22748
23000
  }
22749
- const markdown = await readFile22(markdownPath, "utf8");
22750
- await mkdir13(dirname19(renderedPath), { recursive: true });
23001
+ const markdown = await readFile23(markdownPath, "utf8");
23002
+ await mkdir13(dirname20(renderedPath), { recursive: true });
22751
23003
  await writeFile14(renderedPath, ensureCopilotAgentDescription(agentName, markdown), "utf8");
22752
23004
  return {
22753
23005
  ...artifact,
22754
23006
  name: `${agentName}.agent.md`,
22755
23007
  sourcePath: renderedPath,
22756
23008
  stagedPath: renderedPath,
22757
- relativePath: join19("subagents", `${agentName}.agent.md`),
23009
+ relativePath: join20("subagents", `${agentName}.agent.md`),
22758
23010
  kind: "file",
22759
23011
  hash: await hashPath(renderedPath)
22760
23012
  };
@@ -22802,8 +23054,8 @@ function yamlString(value) {
22802
23054
 
22803
23055
  // src/staging/openclaw-subagents.ts
22804
23056
  init_fs();
22805
- import { mkdir as mkdir14, readFile as readFile23, writeFile as writeFile15 } from "fs/promises";
22806
- import { basename as basename6, dirname as dirname20, join as join20 } from "path";
23057
+ import { mkdir as mkdir14, readFile as readFile24, writeFile as writeFile15 } from "fs/promises";
23058
+ import { basename as basename6, dirname as dirname21, join as join21 } from "path";
22807
23059
  async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
22808
23060
  if (adapter?.name !== "openclaw") return artifacts;
22809
23061
  const names = /* @__PURE__ */ new Set();
@@ -22825,28 +23077,28 @@ async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
22825
23077
  async function renderOpenClawSubagent(artifact, stageRoot) {
22826
23078
  const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
22827
23079
  const agentId = openClawAgentId(artifact);
22828
- const markdownPath = artifact.kind === "dir" ? join20(sourcePath, "AGENTS.md") : sourcePath;
23080
+ const markdownPath = artifact.kind === "dir" ? join21(sourcePath, "AGENTS.md") : sourcePath;
22829
23081
  if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
22830
23082
  throw new Error(`OpenClaw subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
22831
23083
  }
22832
23084
  if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !sourcePath.toLowerCase().endsWith(".md")) {
22833
23085
  throw new Error(`OpenClaw subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
22834
23086
  }
22835
- const parsed = splitFrontmatter3(await readFile23(markdownPath, "utf8"));
23087
+ const parsed = splitFrontmatter3(await readFile24(markdownPath, "utf8"));
22836
23088
  const body = parsed.body.trim().length > 0 ? parsed.body.trim() : `# ${titleFromAgentId(agentId)}
22837
23089
 
22838
23090
  ${parsed.description ?? `OpenClaw subagent ${agentId}.`}`;
22839
- const renderedPath = join20(stageRoot, ".agentwheel-rendered", "openclaw-subagents", agentId, "AGENTS.md");
22840
- await mkdir14(dirname20(renderedPath), { recursive: true });
23091
+ const renderedPath = join21(stageRoot, ".agentwheel-rendered", "openclaw-subagents", agentId, "AGENTS.md");
23092
+ await mkdir14(dirname21(renderedPath), { recursive: true });
22841
23093
  await writeFile15(renderedPath, `${body}
22842
23094
  `, "utf8");
22843
- const renderedDir = dirname20(renderedPath);
23095
+ const renderedDir = dirname21(renderedPath);
22844
23096
  return {
22845
23097
  ...artifact,
22846
23098
  name: agentId,
22847
23099
  sourcePath: renderedDir,
22848
23100
  stagedPath: renderedDir,
22849
- relativePath: join20("subagents", agentId),
23101
+ relativePath: join21("subagents", agentId),
22850
23102
  kind: "dir",
22851
23103
  hash: await hashPath(renderedDir)
22852
23104
  };
@@ -22871,15 +23123,15 @@ function titleFromAgentId(agentId) {
22871
23123
  }
22872
23124
 
22873
23125
  // src/targets/plugins/claude.ts
22874
- import { join as join22 } from "path";
23126
+ import { join as join23 } from "path";
22875
23127
 
22876
23128
  // src/targets/plugins/common.ts
22877
23129
  init_fs();
22878
- import { readFile as readFile24 } from "fs/promises";
22879
- import { join as join21 } from "path";
23130
+ import { readFile as readFile25 } from "fs/promises";
23131
+ import { join as join22 } from "path";
22880
23132
  import { parseDocument } from "yaml";
22881
23133
  function pluginStateRoot(request) {
22882
- return join21(
23134
+ return join22(
22883
23135
  request.targetRoot,
22884
23136
  ".agentwheel",
22885
23137
  "plugins",
@@ -22897,16 +23149,16 @@ function safeNameSegment(value) {
22897
23149
  return normalized.length > 0 ? normalized : "unnamed";
22898
23150
  }
22899
23151
  async function jsonPluginName(root, relativeManifestPath, fallback) {
22900
- const manifestPath = join21(root, relativeManifestPath);
23152
+ const manifestPath = join22(root, relativeManifestPath);
22901
23153
  if (!await pathExists(manifestPath)) return fallback;
22902
- const parsed = JSON.parse(await readFile24(manifestPath, "utf8"));
23154
+ const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
22903
23155
  return typeof parsed.name === "string" && parsed.name.trim().length > 0 ? parsed.name.trim() : fallback;
22904
23156
  }
22905
23157
  async function yamlPluginName(root, relativeManifestPaths, fallback) {
22906
23158
  for (const relativeManifestPath of relativeManifestPaths) {
22907
- const manifestPath = join21(root, relativeManifestPath);
23159
+ const manifestPath = join22(root, relativeManifestPath);
22908
23160
  if (!await pathExists(manifestPath)) continue;
22909
- const document = parseDocument(await readFile24(manifestPath, "utf8"));
23161
+ const document = parseDocument(await readFile25(manifestPath, "utf8"));
22910
23162
  const parsed = document.toJSON();
22911
23163
  if (!isRecord5(parsed)) continue;
22912
23164
  for (const key of ["name", "module", "package"]) {
@@ -22935,7 +23187,7 @@ async function claudePluginSpec(request) {
22935
23187
  packageName: request.artifact.packageName,
22936
23188
  installName: request.installName
22937
23189
  });
22938
- const marketplaceRoot = join22(stateRoot, "marketplace");
23190
+ const marketplaceRoot = join23(stateRoot, "marketplace");
22939
23191
  const scope = claudeScope(request.installationType);
22940
23192
  const selector = `${pluginName}@${marketplaceName}`;
22941
23193
  return {
@@ -22960,7 +23212,7 @@ function claudeScope(installationType) {
22960
23212
  }
22961
23213
 
22962
23214
  // src/targets/plugins/codex.ts
22963
- import { join as join23 } from "path";
23215
+ import { join as join24 } from "path";
22964
23216
  async function codexPluginSpec(request) {
22965
23217
  const pluginName = await jsonPluginName(request.sourcePath, ".codex-plugin/plugin.json", request.installName);
22966
23218
  const marketplaceName = agentwheelMarketplaceName(request.artifact.packageName, pluginName);
@@ -22971,7 +23223,7 @@ async function codexPluginSpec(request) {
22971
23223
  packageName: request.artifact.packageName,
22972
23224
  installName: request.installName
22973
23225
  });
22974
- const marketplaceRoot = join23(stateRoot, "marketplace");
23226
+ const marketplaceRoot = join24(stateRoot, "marketplace");
22975
23227
  const selector = `${pluginName}@${marketplaceName}`;
22976
23228
  return {
22977
23229
  runtime: "codex",
@@ -22990,7 +23242,7 @@ async function codexPluginSpec(request) {
22990
23242
  }
22991
23243
 
22992
23244
  // src/targets/plugins/copilot.ts
22993
- import { join as join24 } from "path";
23245
+ import { join as join25 } from "path";
22994
23246
  async function copilotPluginSpec(request) {
22995
23247
  if (request.installationType !== "user") {
22996
23248
  throw new Error("Copilot plugins are persistent user-level installs only; pass --installation-type user.");
@@ -23003,7 +23255,7 @@ async function copilotPluginSpec(request) {
23003
23255
  packageName: request.artifact.packageName,
23004
23256
  installName: request.installName
23005
23257
  });
23006
- const pluginRoot = join24(stateRoot, "plugin");
23258
+ const pluginRoot = join25(stateRoot, "plugin");
23007
23259
  return {
23008
23260
  runtime: "copilot",
23009
23261
  pluginName,
@@ -23014,7 +23266,7 @@ async function copilotPluginSpec(request) {
23014
23266
  }
23015
23267
 
23016
23268
  // src/targets/plugins/hermes.ts
23017
- import { join as join25 } from "path";
23269
+ import { join as join26 } from "path";
23018
23270
  async function hermesPluginSpec(request) {
23019
23271
  if (request.installationType !== "user") {
23020
23272
  throw new Error("Hermes plugins are user-level installs only; pass --installation-type user.");
@@ -23027,7 +23279,7 @@ async function hermesPluginSpec(request) {
23027
23279
  packageName: request.artifact.packageName,
23028
23280
  installName: request.installName
23029
23281
  });
23030
- const repoRoot = join25(stateRoot, "repo");
23282
+ const repoRoot = join26(stateRoot, "repo");
23031
23283
  return {
23032
23284
  runtime: "hermes",
23033
23285
  pluginName,
@@ -23037,64 +23289,8 @@ async function hermesPluginSpec(request) {
23037
23289
  };
23038
23290
  }
23039
23291
 
23040
- // src/targets/plugins/openclaw.ts
23041
- init_fs();
23042
- import { readFile as readFile25 } from "fs/promises";
23043
- import { join as join26 } from "path";
23044
- function openClawPluginInstallCommand(request) {
23045
- return ["openclaw", "plugins", "install", "--force", request.path];
23046
- }
23047
- function openClawPluginUninstallCommand(pluginName) {
23048
- return ["openclaw", "plugins", "uninstall", pluginName, "--force"];
23049
- }
23050
- async function openClawPluginSpec(request) {
23051
- if (request.format === "openclaw-clawhub-plugin") {
23052
- const metadata = await openClawClawHubPluginMetadata(request.path, request.fallbackPluginName);
23053
- return {
23054
- runtime: "openclaw",
23055
- pluginName: metadata.pluginName,
23056
- installCommands: [openClawPluginInstallCommand({ path: metadata.installSpec, dryRun: true })],
23057
- uninstallCommands: [openClawPluginUninstallCommand(metadata.pluginName)]
23058
- };
23059
- }
23060
- const pluginName = await openClawPluginName(request.path, request.fallbackPluginName);
23061
- return {
23062
- runtime: "openclaw",
23063
- pluginName,
23064
- installCommands: [openClawPluginInstallCommand({ path: request.path, dryRun: true })],
23065
- uninstallCommands: [openClawPluginUninstallCommand(pluginName)]
23066
- };
23067
- }
23068
- async function openClawPluginName(root, fallback) {
23069
- for (const manifestName of ["plugin.json", "openclaw.plugin.json"]) {
23070
- const manifestPath = join26(root, manifestName);
23071
- if (!await pathExists(manifestPath)) continue;
23072
- const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
23073
- if (typeof parsed.name === "string" && parsed.name.trim().length > 0) return parsed.name.trim();
23074
- }
23075
- return fallback;
23076
- }
23077
- async function openClawClawHubPluginMetadata(root, fallback) {
23078
- const metadataPath = join26(root, "clawhub.json");
23079
- if (!await pathExists(metadataPath)) {
23080
- throw new Error("OpenClaw ClawHub plugins must contain clawhub.json");
23081
- }
23082
- const parsed = JSON.parse(await readFile25(metadataPath, "utf8"));
23083
- const installSpec = stringField(parsed.installSpec);
23084
- if (!installSpec?.startsWith("clawhub:")) {
23085
- throw new Error("OpenClaw ClawHub plugin metadata must declare installSpec starting with clawhub:");
23086
- }
23087
- const pluginName = stringField(parsed.runtimeId) ?? installNameFor(stringField(parsed.name) ?? fallback);
23088
- return { installSpec, pluginName };
23089
- }
23090
- function stringField(value) {
23091
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
23092
- }
23093
- function installNameFor(value) {
23094
- return value.split("/").at(-1).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
23095
- }
23096
-
23097
23292
  // src/targets/plugins/index.ts
23293
+ init_openclaw2();
23098
23294
  async function semanticPluginSpecForArtifact(request) {
23099
23295
  if (request.semantic === "openclaw-plugin") {
23100
23296
  return openClawPluginSpec({
@@ -25391,7 +25587,7 @@ function errorMessage2(error46) {
25391
25587
 
25392
25588
  // src/source/clawhub.ts
25393
25589
  import { mkdir as mkdir15, rm as rm8, writeFile as writeFile16 } from "fs/promises";
25394
- import { basename as basename10, dirname as dirname21, join as join32, resolve as resolve22 } from "path";
25590
+ import { basename as basename10, dirname as dirname22, join as join32, resolve as resolve22 } from "path";
25395
25591
 
25396
25592
  // src/model/package.ts
25397
25593
  init_main();
@@ -25964,7 +26160,7 @@ async function writeGeneratedPackage(root, packageInfo) {
25964
26160
  };
25965
26161
  const pluginPath = join32(root, "plugins", pluginId, "clawhub.json");
25966
26162
  await rm8(root, { recursive: true, force: true });
25967
- await mkdir15(dirname21(pluginPath), { recursive: true });
26163
+ await mkdir15(dirname22(pluginPath), { recursive: true });
25968
26164
  await writeFile16(join32(root, "openpack.json"), `${JSON.stringify({
25969
26165
  schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
25970
26166
  name: `clawhub/${name}`,
@@ -25997,7 +26193,7 @@ function cachePathFor(packageName, cacheRoot) {
25997
26193
  import { execFile as execFile6 } from "child_process";
25998
26194
  import { mkdir as mkdir17, rename as rename6, rm as rm10, stat as stat7 } from "fs/promises";
25999
26195
  import { homedir as homedir8 } from "os";
26000
- import { basename as basename11, dirname as dirname23, join as join35, resolve as resolve23, sep as sep8 } from "path";
26196
+ import { basename as basename11, dirname as dirname24, join as join35, resolve as resolve23, sep as sep8 } from "path";
26001
26197
  import { promisify as promisify6 } from "util";
26002
26198
  init_fs();
26003
26199
 
@@ -26080,7 +26276,7 @@ function isMissingFile(error46) {
26080
26276
  init_fs();
26081
26277
  import { randomUUID as randomUUID4 } from "crypto";
26082
26278
  import { mkdir as mkdir16, readdir as readdir9, readFile as readFile29, rm as rm9, stat as stat6, writeFile as writeFile17 } from "fs/promises";
26083
- import { dirname as dirname22, join as join34 } from "path";
26279
+ import { dirname as dirname23, join as join34 } from "path";
26084
26280
  var snapshotNamePattern = /^(.*)-([0-9a-f]{12})$/i;
26085
26281
  var leaseMarker = ".agentwheel-lease-";
26086
26282
  async function pruneGitCache(cacheRoot, options = {}) {
@@ -26148,7 +26344,7 @@ async function removeGeneratedEntries(root, preserveGit) {
26148
26344
  }
26149
26345
  }
26150
26346
  async function pruneGitCacheUnlocked(cacheRoot, options) {
26151
- const referencedCommits = await referencedGraphLockCommits(join34(dirname22(cacheRoot), "locks"));
26347
+ const referencedCommits = await referencedGraphLockCommits(join34(dirname23(cacheRoot), "locks"));
26152
26348
  const entries = await readdir9(cacheRoot, { withFileTypes: true });
26153
26349
  const groups = /* @__PURE__ */ new Map();
26154
26350
  for (const entry of entries) {
@@ -26215,7 +26411,7 @@ async function walkGraphLocks(root, visit2) {
26215
26411
  }
26216
26412
  }
26217
26413
  async function hasLiveSnapshotLease(snapshotPath, dryRun) {
26218
- const directory = dirname22(snapshotPath);
26414
+ const directory = dirname23(snapshotPath);
26219
26415
  const prefix = `${snapshotPath.slice(directory.length + 1)}${leaseMarker}`;
26220
26416
  const entries = await readdir9(directory, { withFileTypes: true });
26221
26417
  let live = false;
@@ -26354,7 +26550,7 @@ var GitSourceDriver = class {
26354
26550
  async fetch(resolved) {
26355
26551
  return withFilesystemLock(`${resolved.resolvedPath}.lock`, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
26356
26552
  const parsed = parseGitSource(resolved.source);
26357
- const cacheRoot = dirname23(resolved.resolvedPath);
26553
+ const cacheRoot = dirname24(resolved.resolvedPath);
26358
26554
  await mkdir17(cacheRoot, { recursive: true });
26359
26555
  await assertOwnedByCurrentUser(cacheRoot);
26360
26556
  if (await pathExists(resolved.resolvedPath)) await assertOwnedByCurrentUser(resolved.resolvedPath);
@@ -26449,9 +26645,9 @@ async function resolveCommit(checkoutPath, ref) {
26449
26645
  throw lastError;
26450
26646
  }
26451
26647
  async function snapshotCommit(checkoutPath, commit) {
26452
- const snapshotPath = join35(dirname23(checkoutPath), `${basename11(checkoutPath)}-${commit.slice(0, 12)}`);
26648
+ const snapshotPath = join35(dirname24(checkoutPath), `${basename11(checkoutPath)}-${commit.slice(0, 12)}`);
26453
26649
  if (await pathExists(snapshotPath)) return snapshotPath;
26454
- const tempPath = join35(dirname23(checkoutPath), `${basename11(snapshotPath)}.tmp-${process.pid}-${Date.now()}`);
26650
+ const tempPath = join35(dirname24(checkoutPath), `${basename11(snapshotPath)}.tmp-${process.pid}-${Date.now()}`);
26455
26651
  const tempIndexPath = `${tempPath}.index`;
26456
26652
  await rm10(tempPath, { recursive: true, force: true });
26457
26653
  await rm10(tempIndexPath, { force: true });
@@ -26489,7 +26685,7 @@ async function assertOwnedByCurrentUser(path) {
26489
26685
 
26490
26686
  // src/source/mcp-registry.ts
26491
26687
  import { mkdir as mkdir18, writeFile as writeFile18 } from "fs/promises";
26492
- import { basename as basename12, dirname as dirname24, join as join36, resolve as resolve24 } from "path";
26688
+ import { basename as basename12, dirname as dirname25, join as join36, resolve as resolve24 } from "path";
26493
26689
  init_fs();
26494
26690
  var registryBaseUrl = "https://registry.modelcontextprotocol.io/v0.1";
26495
26691
  var sourcePrefix2 = "mcp-registry:";
@@ -26597,7 +26793,7 @@ function isSafeHttpUrl(value) {
26597
26793
  async function writeGeneratedPackage2(root, server) {
26598
26794
  const serverId = installNameFor3(server.serverName);
26599
26795
  const mcpPath = join36(root, "mcp", `${serverId}.json`);
26600
- await mkdir18(dirname24(mcpPath), { recursive: true });
26796
+ await mkdir18(dirname25(mcpPath), { recursive: true });
26601
26797
  await writeFile18(join36(root, "openpack.json"), `${JSON.stringify({
26602
26798
  schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
26603
26799
  name: `mcp-registry/${server.serverName}`,
@@ -26631,14 +26827,14 @@ import { createHash as createHash16, randomUUID as randomUUID5 } from "crypto";
26631
26827
  import { execFile as execFile7 } from "child_process";
26632
26828
  import { cp as cp3, mkdir as mkdir19, readFile as readFile30, rename as rename7, rm as rm11 } from "fs/promises";
26633
26829
  import { homedir as homedir9 } from "os";
26634
- import { basename as basename14, dirname as dirname26, join as join38, resolve as resolve25 } from "path";
26830
+ import { basename as basename14, dirname as dirname27, join as join38, resolve as resolve25 } from "path";
26635
26831
  import { promisify as promisify7 } from "util";
26636
26832
  import * as defaultSkillKit from "@skillkit/core";
26637
26833
 
26638
26834
  // src/source/skill-artifacts.ts
26639
26835
  init_fs();
26640
26836
  import { readdir as readdir10, stat as stat8 } from "fs/promises";
26641
- import { basename as basename13, dirname as dirname25, extname as extname2, join as join37 } from "path";
26837
+ import { basename as basename13, dirname as dirname26, extname as extname2, join as join37 } from "path";
26642
26838
  async function artifactsFromSkillPaths(paths, packageName) {
26643
26839
  const artifacts = [];
26644
26840
  const seen = /* @__PURE__ */ new Set();
@@ -26675,7 +26871,7 @@ async function artifactFromSkillPath(item, packageName) {
26675
26871
  };
26676
26872
  }
26677
26873
  if (stats.isFile() && basename13(item.path).toLowerCase() === "skill.md") {
26678
- const dir = dirname25(item.path);
26874
+ const dir = dirname26(item.path);
26679
26875
  const name = sanitizeSkillName(item.name ?? basename13(dir));
26680
26876
  return {
26681
26877
  type: "skills",
@@ -26783,7 +26979,7 @@ var SkillKitSourceDriver = class {
26783
26979
  sourceHash: await hashPath(resolved.resolvedPath)
26784
26980
  };
26785
26981
  }
26786
- const specCachePath = cachePathFor4(spec, dirname26(dirname26(resolved.resolvedPath)));
26982
+ const specCachePath = cachePathFor4(spec, dirname27(dirname27(resolved.resolvedPath)));
26787
26983
  const refIdentity = resolved.requestedRef ?? "default";
26788
26984
  const lockPath = `${specCachePath}.ref-${createHash16("sha256").update(refIdentity).digest("hex")}.lock`;
26789
26985
  const inflightKey = `${lockPath}\0${requestedCommit ?? "movable"}`;
@@ -26804,11 +27000,11 @@ var SkillKitSourceDriver = class {
26804
27000
  throw new Error("SkillKit provider API unavailable or cannot resolve source. Expected @skillkit/core detectProvider().clone().");
26805
27001
  }
26806
27002
  const materialized = await withFilesystemLock(lockPath, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
26807
- const immutablePath = requestedCommit ? cachePathFor4(spec, dirname26(dirname26(specCachePath)), requestedCommit) : void 0;
27003
+ const immutablePath = requestedCommit ? cachePathFor4(spec, dirname27(dirname27(specCachePath)), requestedCommit) : void 0;
26808
27004
  if (immutablePath && await pathExists(immutablePath)) {
26809
27005
  return { path: immutablePath, commit: requestedCommit, cacheIdentity: requestedCommit };
26810
27006
  }
26811
- await mkdir19(dirname26(specCachePath), { recursive: true });
27007
+ await mkdir19(dirname27(specCachePath), { recursive: true });
26812
27008
  const candidatePath = `${specCachePath}.agentwheel-tmp-${process.pid}-${randomUUID5()}`;
26813
27009
  const publishPath = `${candidatePath}.publish`;
26814
27010
  let result;
@@ -26830,7 +27026,7 @@ var SkillKitSourceDriver = class {
26830
27026
  `SkillKit provider resolved ${resolvedIdentity.commit ?? "non-Git content"} instead of requested commit ${requestedCommit}`
26831
27027
  );
26832
27028
  }
26833
- const cachePath = cachePathFor4(spec, dirname26(dirname26(specCachePath)), resolvedIdentity.cacheKey);
27029
+ const cachePath = cachePathFor4(spec, dirname27(dirname27(specCachePath)), resolvedIdentity.cacheKey);
26834
27030
  if (await pathExists(cachePath)) {
26835
27031
  return { path: cachePath, commit: resolvedIdentity.commit, cacheIdentity: resolvedIdentity.cacheKey };
26836
27032
  }
@@ -27101,7 +27297,7 @@ init_identify();
27101
27297
 
27102
27298
  // src/staging/staging.ts
27103
27299
  import { chmod as chmod4, cp as cp5, mkdir as mkdir22, mkdtemp as mkdtemp4, readdir as readdir13, stat as stat12 } from "fs/promises";
27104
- import { basename as basename19, dirname as dirname30, join as join43, relative as relative16, resolve as resolve29, sep as sep10 } from "path";
27300
+ import { basename as basename19, dirname as dirname31, join as join43, relative as relative16, resolve as resolve29, sep as sep10 } from "path";
27105
27301
  import { tmpdir as tmpdir5 } from "os";
27106
27302
  init_fs();
27107
27303
 
@@ -27110,7 +27306,7 @@ init_artifact();
27110
27306
  init_fs();
27111
27307
  import { createHash as createHash17 } from "crypto";
27112
27308
  import { readdir as readdir11, readFile as readFile31, stat as stat10, writeFile as writeFile19 } from "fs/promises";
27113
- import { basename as basename16, dirname as dirname27, extname as extname3, join as join40, relative as relative15, resolve as resolve28, sep as sep9 } from "path";
27309
+ import { basename as basename16, dirname as dirname28, extname as extname3, join as join40, relative as relative15, resolve as resolve28, sep as sep9 } from "path";
27114
27310
  var includePattern = /<!--\s*openpack:include(\?)?\s+([^>]+?)\s*-->/g;
27115
27311
  var escapedIncludePattern = /<!--\s*openpack\\:include(\?)?\s+([^>]+?)\s*-->/g;
27116
27312
  var generatedPattern = /<!--\s*(?:BEGIN|END)\s+openpack:include\b/;
@@ -27365,11 +27561,11 @@ async function listMarkdownFiles(root) {
27365
27561
  function composeEntriesForFile(artifact, file2) {
27366
27562
  if (!artifact.compose?.length) return [];
27367
27563
  if (artifact.kind === "file") return [resolve28(artifact.stagedPath ?? artifact.sourcePath), resolve28(file2)].every(Boolean) && resolve28(artifact.stagedPath ?? artifact.sourcePath) === resolve28(file2) ? artifact.compose : [];
27368
- return basename16(file2) === "SKILL.md" && dirname27(file2) === resolve28(artifact.stagedPath ?? artifact.sourcePath) ? artifact.compose : [];
27564
+ return basename16(file2) === "SKILL.md" && dirname28(file2) === resolve28(artifact.stagedPath ?? artifact.sourcePath) ? artifact.compose : [];
27369
27565
  }
27370
27566
  function isPrimaryMarkdownFile(artifact, file2) {
27371
27567
  if (artifact.kind === "file") return resolve28(artifact.stagedPath ?? artifact.sourcePath) === resolve28(file2);
27372
- return basename16(file2) === "SKILL.md" && dirname27(file2) === resolve28(artifact.stagedPath ?? artifact.sourcePath);
27568
+ return basename16(file2) === "SKILL.md" && dirname28(file2) === resolve28(artifact.stagedPath ?? artifact.sourcePath);
27373
27569
  }
27374
27570
  function orderedForExpansion(artifacts) {
27375
27571
  return [...artifacts].sort((a, b) => Number(a.type === "fragments") - Number(b.type === "fragments"));
@@ -27417,7 +27613,7 @@ function artifactPathMap(artifacts) {
27417
27613
  // src/staging/customize.ts
27418
27614
  init_fs();
27419
27615
  import { cp as cp4, mkdir as mkdir20, readdir as readdir12, readFile as readFile32, writeFile as writeFile20 } from "fs/promises";
27420
- import { dirname as dirname28, join as join41 } from "path";
27616
+ import { dirname as dirname29, join as join41 } from "path";
27421
27617
  async function applyCustomizations(artifacts, options) {
27422
27618
  let next = [...artifacts];
27423
27619
  next = await applyReplacements2(next, options, "override", installableArtifactTypes());
@@ -27441,7 +27637,7 @@ async function applyInstructionOverlay(artifacts, options) {
27441
27637
  const managed = await readFile32(artifact.stagedPath ?? artifact.sourcePath, "utf8");
27442
27638
  const local = await readFile32(overlayPath, "utf8");
27443
27639
  const composedPath = join41(options.stageRoot, ".agentwheel-composed", "instructions", "AGENTS.md");
27444
- await mkdir20(dirname28(composedPath), { recursive: true });
27640
+ await mkdir20(dirname29(composedPath), { recursive: true });
27445
27641
  await writeFile20(
27446
27642
  composedPath,
27447
27643
  [
@@ -27514,7 +27710,7 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
27514
27710
  const artifactKind = entry.isDirectory() ? "dir" : "file";
27515
27711
  const existing = byKey.get(artifactMapKey);
27516
27712
  const stagedPath = join41(options.stageRoot, ".agentwheel-composed", channel, type, entry.name);
27517
- await mkdir20(dirname28(stagedPath), { recursive: true });
27713
+ await mkdir20(dirname29(stagedPath), { recursive: true });
27518
27714
  await cp4(full, stagedPath, { recursive: artifactKind === "dir", dereference: true });
27519
27715
  byKey.set(artifactMapKey, {
27520
27716
  ...existing,
@@ -27560,7 +27756,7 @@ async function sortedDirEntries2(path) {
27560
27756
  // src/staging/claude-subagents.ts
27561
27757
  init_fs();
27562
27758
  import { mkdir as mkdir21, readFile as readFile33, writeFile as writeFile21 } from "fs/promises";
27563
- import { basename as basename18, dirname as dirname29, join as join42 } from "path";
27759
+ import { basename as basename18, dirname as dirname30, join as join42 } from "path";
27564
27760
  async function renderClaudeSubagents(artifacts, stageRoot, adapter) {
27565
27761
  if (adapter?.name !== "claude") return artifacts;
27566
27762
  const names = /* @__PURE__ */ new Set();
@@ -27591,7 +27787,7 @@ async function renderClaudeSubagent(artifact, stageRoot) {
27591
27787
  }
27592
27788
  const content = await readFile33(markdownPath, "utf8");
27593
27789
  const renderedPath = join42(stageRoot, ".agentwheel-rendered", "claude-subagents", `${agentName}.md`);
27594
- await mkdir21(dirname29(renderedPath), { recursive: true });
27790
+ await mkdir21(dirname30(renderedPath), { recursive: true });
27595
27791
  await writeFile21(renderedPath, content.endsWith("\n") ? content : `${content}
27596
27792
  `, "utf8");
27597
27793
  return {
@@ -27634,7 +27830,7 @@ async function stageResolvedArtifactsRaw(resolved, artifacts, parentDir = tmpdir
27634
27830
  await removeOnFailure(root, async () => {
27635
27831
  for (const artifact of artifacts) {
27636
27832
  const stagedPath = join43(root, artifact.relativePath);
27637
- await mkdir22(dirname30(stagedPath), { recursive: true });
27833
+ await mkdir22(dirname31(stagedPath), { recursive: true });
27638
27834
  await cp5(artifact.sourcePath, stagedPath, {
27639
27835
  recursive: artifact.kind === "dir",
27640
27836
  dereference: true,
@@ -27740,7 +27936,7 @@ async function copyAsset(asset, source, dest) {
27740
27936
  throw new Error(`Asset include source is not a file or directory: ${source}`);
27741
27937
  }
27742
27938
  if (!asset.include?.length) {
27743
- await mkdir22(dirname30(dest), { recursive: true });
27939
+ await mkdir22(dirname31(dest), { recursive: true });
27744
27940
  await cp5(source, dest, { recursive: true, dereference: true });
27745
27941
  if (asset.mode === "copy") await normalizeCopiedModes(dest);
27746
27942
  return;
@@ -27752,7 +27948,7 @@ async function copyAsset(asset, source, dest) {
27752
27948
  }
27753
27949
  }
27754
27950
  async function copyAssetFile(source, dest, asset) {
27755
- await mkdir22(dirname30(dest), { recursive: true });
27951
+ await mkdir22(dirname31(dest), { recursive: true });
27756
27952
  await cp5(source, dest, { dereference: true });
27757
27953
  if (asset.mode === "copy") await chmod4(dest, 420);
27758
27954
  }
@@ -27808,7 +28004,7 @@ init_adapter();
27808
28004
  init_artifact();
27809
28005
  init_workspace();
27810
28006
  import { appendFile, cp as cp6, lstat as lstat7, mkdir as mkdir23, readdir as readdir15, rm as rm13 } from "fs/promises";
27811
- import { dirname as dirname32, join as join46, relative as relative17 } from "path";
28007
+ import { dirname as dirname33, join as join46, relative as relative17 } from "path";
27812
28008
 
27813
28009
  // src/resolve/graph.ts
27814
28010
  import { createHash as createHash19 } from "crypto";
@@ -27946,7 +28142,7 @@ import { resolve as resolve31 } from "path";
27946
28142
  // src/registry/client.ts
27947
28143
  import { readFile as readFile35, rm as rm12, stat as stat13 } from "fs/promises";
27948
28144
  import { homedir as homedir11 } from "os";
27949
- import { dirname as dirname31, join as join44, resolve as resolve30 } from "path";
28145
+ import { dirname as dirname32, join as join44, resolve as resolve30 } from "path";
27950
28146
  import { fileURLToPath as fileURLToPath2 } from "url";
27951
28147
 
27952
28148
  // src/model/registry.ts
@@ -28067,7 +28263,7 @@ var RegistryClient = class {
28067
28263
  const stats = await stat13(fullPath);
28068
28264
  return readFile35(stats.isDirectory() ? join44(fullPath, "index.json") : fullPath, "utf8");
28069
28265
  }
28070
- const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join44(dirname31(this.cachePath), "registry-repos") }));
28266
+ const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join44(dirname32(this.cachePath), "registry-repos") }));
28071
28267
  return readFile35(join44(resolved.resolvedPath, "index.json"), "utf8");
28072
28268
  }
28073
28269
  warnCompatibility(entries) {
@@ -28438,6 +28634,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
28438
28634
  if (!satisfiesVersionRange(fetched.version, requirement.version)) {
28439
28635
  throw new Error(`Package ${fetched.name}@${fetched.version} does not satisfy requested version ${requirement.version}`);
28440
28636
  }
28637
+ const requestedRef = frozen ? frozen.node.requestedRef : fetched.resolved.requestedRef;
28441
28638
  const nodeKey = `${normalized.normalizedSource}\0${fetched.name}`;
28442
28639
  let selectionImport = requirement.selection ? await resolveSelectionImport(fetched.resolved.resolvedPath, fetched.resolved.driver, requirement.selection) : void 0;
28443
28640
  const selected = computeSelectedSelectors(
@@ -28464,7 +28661,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
28464
28661
  source: fetched.resolved.source,
28465
28662
  normalizedSource: normalized.normalizedSource,
28466
28663
  driver: fetched.resolved.driver,
28467
- requestedRef: fetched.resolved.requestedRef,
28664
+ requestedRef,
28468
28665
  resolvedCommit: fetched.resolved.resolvedCommit,
28469
28666
  cacheIdentity: fetched.resolved.cacheIdentity,
28470
28667
  sourceHash: fetched.sourceHash,
@@ -28522,7 +28719,7 @@ Run without ${lockLabel === "Offline" ? "--offline" : "--frozen-lock"} first.`
28522
28719
  alias: requirement.alias,
28523
28720
  source: requirement.source,
28524
28721
  normalizedSource: normalized.normalizedSource,
28525
- requestedRef: fetched.resolved.requestedRef,
28722
+ requestedRef,
28526
28723
  version: requirement.version,
28527
28724
  mode: requirement.mode,
28528
28725
  optional: requirement.optional,
@@ -29194,7 +29391,7 @@ init_declarations();
29194
29391
  async function remember(workspaceRoot, runtime, text) {
29195
29392
  const overlayPath = join46(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
29196
29393
  declareMutationPath(overlayPath);
29197
- await mkdir23(dirname32(overlayPath), { recursive: true });
29394
+ await mkdir23(dirname33(overlayPath), { recursive: true });
29198
29395
  await appendFile(overlayPath, `${text.trim()}
29199
29396
  `, "utf8");
29200
29397
  return { overlayPath };
@@ -29227,7 +29424,7 @@ async function ejectArtifact(workspaceRoot, item) {
29227
29424
  } else {
29228
29425
  declareMutationPath(ejectedPath);
29229
29426
  }
29230
- await mkdir23(dirname32(ejectedPath), { recursive: true });
29427
+ await mkdir23(dirname33(ejectedPath), { recursive: true });
29231
29428
  await rm13(ejectedPath, { recursive: true, force: true });
29232
29429
  await cp6(sourcePath, ejectedPath, { recursive: artifact.kind === "dir", dereference: true });
29233
29430
  return {
@@ -29346,7 +29543,7 @@ init_adapter();
29346
29543
  init_graph_lock();
29347
29544
  import { createHash as createHash21 } from "crypto";
29348
29545
  import { mkdir as mkdir25, readdir as readdir16 } from "fs/promises";
29349
- import { basename as basename21, dirname as dirname34, join as join49, posix as posix7, resolve as resolve34 } from "path";
29546
+ import { basename as basename21, dirname as dirname35, join as join49, posix as posix7, resolve as resolve34 } from "path";
29350
29547
  init_paths();
29351
29548
  init_merge_removal();
29352
29549
  init_transaction();
@@ -30034,7 +30231,7 @@ init_zod();
30034
30231
  init_fs();
30035
30232
  import { mkdir as mkdir24, readFile as readFile38 } from "fs/promises";
30036
30233
  import { homedir as homedir13 } from "os";
30037
- import { dirname as dirname33, join as join48 } from "path";
30234
+ import { dirname as dirname34, join as join48 } from "path";
30038
30235
  var trustStoreSchema = external_exports.object({
30039
30236
  version: external_exports.literal(1),
30040
30237
  acceptedSources: external_exports.array(external_exports.string().min(1)).default([])
@@ -30110,7 +30307,7 @@ async function readTrustStore(path) {
30110
30307
  return trustStoreSchema.parse(JSON.parse(await readFile38(path, "utf8")));
30111
30308
  }
30112
30309
  async function writeTrustStore(path, store) {
30113
- await mkdir24(dirname33(path), { recursive: true });
30310
+ await mkdir24(dirname34(path), { recursive: true });
30114
30311
  await writeJsonAtomic(path, trustStoreSchema.parse(store));
30115
30312
  }
30116
30313
  function defaultTrustStorePath() {
@@ -30610,7 +30807,7 @@ async function discoverTargetApplyJournal(options) {
30610
30807
  continue;
30611
30808
  }
30612
30809
  if (!journal.graphLockPath || !journal.graphLock || !journal.graphLockDigest) continue;
30613
- if (resolve34(dirname34(journal.graphLockPath)) !== resolve34(dirname34(options.graphLockPath))) continue;
30810
+ if (resolve34(dirname35(journal.graphLockPath)) !== resolve34(dirname35(options.graphLockPath))) continue;
30614
30811
  if (options.transport.kind === "ssh") {
30615
30812
  throw new Error(
30616
30813
  `Legacy SSH apply journal at ${item.path} does not record its original endpoint; Agentwheel cannot prove endpoint identity, so the journal was preserved.`
@@ -30752,7 +30949,7 @@ async function resolvePriorTargetState(options) {
30752
30949
  return {};
30753
30950
  }
30754
30951
  async function discoverLegacyStateCandidates(options) {
30755
- const directory = dirname34(options.graphLockPath);
30952
+ const directory = dirname35(options.graphLockPath);
30756
30953
  let names;
30757
30954
  try {
30758
30955
  names = await readdir16(directory);
@@ -31040,7 +31237,7 @@ function mcpServerNames(strategy, removal) {
31040
31237
  return new Set(Object.keys(servers));
31041
31238
  }
31042
31239
  function globalConfigRoot(globalRoot) {
31043
- return dirname34(dirname34(globalWorkspaceConfigPath(globalRoot)));
31240
+ return dirname35(dirname35(globalWorkspaceConfigPath(globalRoot)));
31044
31241
  }
31045
31242
  function ownedByWorkspace(owner, desiredOwner, workspaceRoot, ownsSubWorkspaces) {
31046
31243
  if (owner === desiredOwner) return true;
@@ -31188,7 +31385,7 @@ function targetLabel(target) {
31188
31385
  init_workspace();
31189
31386
  init_run_as_identity();
31190
31387
  init_fs();
31191
- import { basename as basename22, dirname as dirname35, join as join50, resolve as resolve35 } from "path";
31388
+ import { basename as basename22, dirname as dirname36, join as join50, resolve as resolve35 } from "path";
31192
31389
  var runtimeMarkers = [
31193
31390
  { adapter: "openclaw", dirs: [".openclaw", ".clawdbot", ".moltbot"] },
31194
31391
  { adapter: "claude", dirs: [".claude"] },
@@ -31314,7 +31511,7 @@ async function detectRuntimeTargets(cwd = process.cwd(), adapterFilter) {
31314
31511
  if (adapterFilter && marker.adapter !== adapterFilter) continue;
31315
31512
  for (const dir of marker.dirs) {
31316
31513
  if (basename22(root) === dir) {
31317
- matches.push({ adapter: marker.adapter, targetRoot: dirname35(root) });
31514
+ matches.push({ adapter: marker.adapter, targetRoot: dirname36(root) });
31318
31515
  } else if (await pathExists(join50(root, dir))) {
31319
31516
  matches.push({ adapter: marker.adapter, targetRoot: root });
31320
31517
  }
@@ -31361,7 +31558,7 @@ function dedupeTargets(matches) {
31361
31558
  function runtimeScanRoot(request) {
31362
31559
  const root = resolve35(request.targetRoot ?? request.cwd ?? process.cwd());
31363
31560
  if (request.targetRoot) return root;
31364
- return runtimeMarkers.some((marker) => marker.dirs.includes(basename22(root))) ? dirname35(root) : root;
31561
+ return runtimeMarkers.some((marker) => marker.dirs.includes(basename22(root))) ? dirname36(root) : root;
31365
31562
  }
31366
31563
 
31367
31564
  // src/lifecycle/profile.ts
@@ -31695,7 +31892,7 @@ init_selection();
31695
31892
  // src/cli/update-check.ts
31696
31893
  import { mkdir as mkdir26, readFile as readFile39, writeFile as writeFile22 } from "fs/promises";
31697
31894
  import { homedir as homedir14 } from "os";
31698
- import { dirname as dirname36, join as join51 } from "path";
31895
+ import { dirname as dirname37, join as join51 } from "path";
31699
31896
  var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
31700
31897
  var DEFAULT_TIMEOUT_MS = 300;
31701
31898
  var REGISTRY_URL = "https://registry.npmjs.org/agentwheel";
@@ -31748,7 +31945,7 @@ async function readCache(path) {
31748
31945
  }
31749
31946
  }
31750
31947
  async function writeCache(path, cache) {
31751
- await mkdir26(dirname36(path), { recursive: true });
31948
+ await mkdir26(dirname37(path), { recursive: true });
31752
31949
  await writeFile22(path, `${JSON.stringify(cache, null, 2)}
31753
31950
  `, "utf8");
31754
31951
  }
@@ -31984,11 +32181,11 @@ init_graph_lock();
31984
32181
 
31985
32182
  // src/cli/version.ts
31986
32183
  import { readFileSync as readFileSync2 } from "fs";
31987
- import { dirname as dirname37, join as join54 } from "path";
32184
+ import { dirname as dirname38, join as join54 } from "path";
31988
32185
  import { fileURLToPath as fileURLToPath3 } from "url";
31989
32186
  var FALLBACK_VERSION = "0.0.0";
31990
32187
  function resolveCliVersion() {
31991
- let dir = dirname37(fileURLToPath3(import.meta.url));
32188
+ let dir = dirname38(fileURLToPath3(import.meta.url));
31992
32189
  while (true) {
31993
32190
  try {
31994
32191
  const pkg = JSON.parse(readFileSync2(join54(dir, "package.json"), "utf8"));
@@ -31997,7 +32194,7 @@ function resolveCliVersion() {
31997
32194
  }
31998
32195
  } catch {
31999
32196
  }
32000
- const parent = dirname37(dir);
32197
+ const parent = dirname38(dir);
32001
32198
  if (parent === dir) return FALLBACK_VERSION;
32002
32199
  dir = parent;
32003
32200
  }
@@ -32906,7 +33103,7 @@ init_graph_lock();
32906
33103
  init_manifest();
32907
33104
  import { createHash as createHash26 } from "crypto";
32908
33105
  import { lstat as lstat8, readdir as readdir17 } from "fs/promises";
32909
- import { basename as basename23, dirname as dirname38, join as join57, posix as posix8, relative as relative18, resolve as resolve42 } from "path";
33106
+ import { basename as basename23, dirname as dirname39, join as join57, posix as posix8, relative as relative18, resolve as resolve42 } from "path";
32910
33107
  async function inventoryHistoricalLocks(fleetRoot) {
32911
33108
  const root = join57(fleetRoot, ".agentwheel", "locks");
32912
33109
  const found = [];
@@ -32953,7 +33150,7 @@ async function planLegacyRecovery(input) {
32953
33150
  const { graphPlan, installRoot, targetKey: targetKey2, adapter, installationType, historicalLocks, transport } = input;
32954
33151
  assertCompleteGraphPlan(graphPlan);
32955
33152
  const binding = {
32956
- targetLockDir: dirname38(graphPlan.graphLockPath),
33153
+ targetLockDir: dirname39(graphPlan.graphLockPath),
32957
33154
  stableLockPath: graphPlan.graphLockPath,
32958
33155
  stableStateKey: graphPlan.plan.stateKey,
32959
33156
  currentFingerprint: graphPlan.targetFingerprint,
@@ -33065,7 +33262,7 @@ function claimFor(item, entry, locks, binding) {
33065
33262
  const evidence = [];
33066
33263
  const owner = "workspaceOwner" in entry ? entry.workspaceOwner : legacyUnownedWorkspaceOwner;
33067
33264
  const sameRoot = binding.transportKind === "ssh" ? posix8.normalize(item.manifest.targetRoot) === posix8.normalize(binding.installRoot) : resolve42(item.manifest.targetRoot) === resolve42(binding.installRoot);
33068
- const inTargetDir = matches.filter((candidate) => resolve42(dirname38(candidate.path)) === resolve42(binding.targetLockDir));
33265
+ const inTargetDir = matches.filter((candidate) => resolve42(dirname39(candidate.path)) === resolve42(binding.targetLockDir));
33069
33266
  const boundLocks = inTargetDir.filter((candidate) => lockBindsState(candidate, item, binding));
33070
33267
  if (owner !== binding.expectedOwner) evidence.push("workspace owner differs from selected Fleet target");
33071
33268
  if (item.manifest.version !== 2 || item.manifest.installationType !== binding.installationType) evidence.push("installation type differs or manifest is legacy v1");
@@ -35114,7 +35311,7 @@ init_fleet();
35114
35311
  // src/lifecycle/fleet-normalize.ts
35115
35312
  import { createHash as createHash31 } from "crypto";
35116
35313
  import { homedir as homedir17 } from "os";
35117
- import { dirname as dirname40, isAbsolute as isAbsolute16, join as join65, relative as relative21, resolve as resolve47 } from "path";
35314
+ import { dirname as dirname41, isAbsolute as isAbsolute16, join as join65, relative as relative21, resolve as resolve47 } from "path";
35118
35315
  init_manifest2();
35119
35316
  init_paths();
35120
35317
  init_merge_removal();
@@ -35140,7 +35337,7 @@ init_caller_write_trust();
35140
35337
  import { AsyncLocalStorage } from "async_hooks";
35141
35338
  import { readFile as readLocalFile, readdir as readLocalDir, rm as removeLocal, mkdir as mkdir27, open as open6, rename as rename9 } from "fs/promises";
35142
35339
  import { randomUUID as randomUUID8 } from "crypto";
35143
- import { dirname as dirname39, isAbsolute as isAbsolute15, relative as relative20, resolve as resolve46, sep as sep11 } from "path";
35340
+ import { dirname as dirname40, isAbsolute as isAbsolute15, relative as relative20, resolve as resolve46, sep as sep11 } from "path";
35144
35341
  var contexts = new AsyncLocalStorage();
35145
35342
  var inside = (root, path) => {
35146
35343
  const rel = relative20(root, resolve46(path));
@@ -35202,7 +35399,7 @@ async function normalizationRemove(path, options) {
35202
35399
  }
35203
35400
  await assertNormalizationCallerWrite(path);
35204
35401
  await removeLocal(path, options);
35205
- if (normalizationIdentities().length) await syncMetadataPath(dirname39(path), true);
35402
+ if (normalizationIdentities().length) await syncMetadataPath(dirname40(path), true);
35206
35403
  }
35207
35404
  async function normalizationWriteJson(path, data) {
35208
35405
  const transport = normalizationTransport(path);
@@ -35216,7 +35413,7 @@ async function normalizationWriteJson(path, data) {
35216
35413
  }
35217
35414
  await assertNormalizationCallerWrite(path);
35218
35415
  await assertNoSymlinkPath2(path);
35219
- await mkdir27(dirname39(path), { recursive: true, mode: 448 });
35416
+ await mkdir27(dirname40(path), { recursive: true, mode: 448 });
35220
35417
  await assertNormalizationCallerWrite(path);
35221
35418
  const temporary = `${path}.pending-${randomUUID8()}`;
35222
35419
  try {
@@ -35230,8 +35427,8 @@ async function normalizationWriteJson(path, data) {
35230
35427
  await file2.close();
35231
35428
  }
35232
35429
  await rename9(temporary, path);
35233
- await syncMetadataPath(dirname39(path), true);
35234
- await syncMetadataPath(dirname39(dirname39(path)), true);
35430
+ await syncMetadataPath(dirname40(path), true);
35431
+ await syncMetadataPath(dirname40(dirname40(path)), true);
35235
35432
  } finally {
35236
35433
  await removeLocal(temporary, { force: true });
35237
35434
  }
@@ -36282,7 +36479,7 @@ async function releasedTargetStateForGraph(scope, graph, identityFleetId = scope
36282
36479
  ...current,
36283
36480
  stateKey,
36284
36481
  targetFingerprint,
36285
- graphLockPath: join65(dirname40(graph.path), `${targetFingerprint}.graph-lock.json`),
36482
+ graphLockPath: join65(dirname41(graph.path), `${targetFingerprint}.graph-lock.json`),
36286
36483
  manifestPath: installManifestPath(current.installRoot, current.adapter, {
36287
36484
  installationType: current.installationType,
36288
36485
  stateKey
@@ -37536,7 +37733,7 @@ ownershipCommand.command("recovery-plan").description("write a read-only per-pat
37536
37733
  const adapter = await resolveAdapterForTarget(target, {});
37537
37734
  const transport = transportForTarget(target);
37538
37735
  const requestedReport = normalizeCliPath(options.report);
37539
- const reportPath = join66(await realpath4(dirname41(requestedReport)), basename24(requestedReport));
37736
+ const reportPath = join66(await realpath4(dirname42(requestedReport)), basename24(requestedReport));
37540
37737
  const reportInsideTarget = relative22(resolve48(target.targetRoot), reportPath);
37541
37738
  if (reportInsideTarget === "" || !reportInsideTarget.startsWith("..") && !isAbsolute17(reportInsideTarget)) {
37542
37739
  throw new Error("Recovery report must be outside the runtime target root.");
@@ -40559,7 +40756,7 @@ async function initPackage(root) {
40559
40756
  await writeFile24(instructionsPath, "# Agent Instructions\n", "utf8");
40560
40757
  }
40561
40758
  async function defaultBootstrapPackage(_root) {
40562
- const packageRoot = await findAgentwheelPackageRoot(dirname41(fileURLToPath4(import.meta.url)));
40759
+ const packageRoot = await findAgentwheelPackageRoot(dirname42(fileURLToPath4(import.meta.url)));
40563
40760
  if (!packageRoot) return void 0;
40564
40761
  return {
40565
40762
  name: "agentwheel",
@@ -40606,7 +40803,7 @@ async function findAgentwheelPackageRoot(start) {
40606
40803
  let current = resolve48(start);
40607
40804
  while (true) {
40608
40805
  if (await findPackageManifestPath(current, { warnLegacy: false })) return current;
40609
- const parent = dirname41(current);
40806
+ const parent = dirname42(current);
40610
40807
  if (parent === current) return void 0;
40611
40808
  current = parent;
40612
40809
  }