agentwheel 0.21.0 → 0.21.2

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
@@ -522,13 +522,13 @@ async function hashPath(path) {
522
522
  if (!stats.isDirectory()) {
523
523
  throw new Error(`Unsupported path kind: ${path}`);
524
524
  }
525
- const hash = createHash("sha256").update("dir\0");
525
+ const hash2 = createHash("sha256").update("dir\0");
526
526
  const files = await listFiles(path);
527
527
  for (const file of files) {
528
- hash.update(relative(path, file).replaceAll("\\", "/")).update("\0");
529
- hash.update(await hashPath(file)).update("\0");
528
+ hash2.update(relative(path, file).replaceAll("\\", "/")).update("\0");
529
+ hash2.update(await hashPath(file)).update("\0");
530
530
  }
531
- return hash.digest("hex");
531
+ return hash2.digest("hex");
532
532
  }
533
533
  async function listFiles(root) {
534
534
  const out = [];
@@ -583,7 +583,7 @@ async function withFilesystemLock(lockPath, timeoutMs, fn, description = "cache"
583
583
  if (Date.now() - started > timeoutMs) {
584
584
  throw new Error(`Timed out waiting for ${description} lock at ${lockPath}`);
585
585
  }
586
- await new Promise((resolve44) => setTimeout(resolve44, 50));
586
+ await new Promise((resolve45) => setTimeout(resolve45, 50));
587
587
  }
588
588
  }
589
589
  try {
@@ -853,7 +853,7 @@ var init_protocol = __esm({
853
853
  // src/mutation/process.ts
854
854
  import { spawn } from "child_process";
855
855
  async function runProcess(command, args, options = {}) {
856
- return new Promise((resolve44, reject) => {
856
+ return new Promise((resolve45, reject) => {
857
857
  const useProcessGroup = options.killProcessGroup === true && process.platform !== "win32";
858
858
  const child = spawn(command, args, {
859
859
  cwd: options.cwd,
@@ -913,7 +913,7 @@ async function runProcess(command, args, options = {}) {
913
913
  reject(new Error(`${command} exited ${exitCode}${detail ? `: ${detail}` : ""}`));
914
914
  return;
915
915
  }
916
- resolve44(result);
916
+ resolve45(result);
917
917
  });
918
918
  if (options.input !== void 0) child.stdin.end(options.input);
919
919
  else child.stdin.end();
@@ -939,8 +939,8 @@ function agentMeshGraphPath() {
939
939
  function agentwheelResourceRef(gitCommonDir, repositoryRelativePath) {
940
940
  const commonDir = resolve5(gitCommonDir);
941
941
  const normalizedPath = normalizeRepositoryRelativePath(repositoryRelativePath);
942
- const digest2 = createHash3("sha256").update(commonDir).update("\0").update(normalizedPath).digest("hex");
943
- return `agentwheel-resource:${digest2}`;
942
+ const digest3 = createHash3("sha256").update(commonDir).update("\0").update(normalizedPath).digest("hex");
943
+ return `agentwheel-resource:${digest3}`;
944
944
  }
945
945
  async function resourceRefsForRepositoryPaths(repositoryRoot, paths) {
946
946
  const result = await runProcess("git", [
@@ -1213,8 +1213,8 @@ async function listMutationReceipts() {
1213
1213
  }
1214
1214
  async function acquireMutationLock(repositoryRoot, operationId) {
1215
1215
  const root = mutationStateRoot();
1216
- const digest2 = createHash4("sha256").update(resolve6(repositoryRoot)).digest("hex");
1217
- const lockPath = join4(root, "locks", `${digest2}.lock`);
1216
+ const digest3 = createHash4("sha256").update(resolve6(repositoryRoot)).digest("hex");
1217
+ const lockPath = join4(root, "locks", `${digest3}.lock`);
1218
1218
  await mkdir2(join4(root, "locks"), { recursive: true, mode: 448 });
1219
1219
  await chmod(join4(root, "locks"), 448);
1220
1220
  try {
@@ -1961,13 +1961,13 @@ async function spawnWithInput(command, args, input) {
1961
1961
  if (result.stderr) throw new Error(result.stderr);
1962
1962
  }
1963
1963
  function waitForProcess(child, label) {
1964
- return new Promise((resolve44, reject) => {
1964
+ return new Promise((resolve45, reject) => {
1965
1965
  const stderr = [];
1966
1966
  child.stderr?.on("data", (chunk) => stderr.push(chunk));
1967
1967
  child.on("error", reject);
1968
1968
  child.on("close", (code) => {
1969
1969
  const message = Buffer.concat(stderr).toString("utf8");
1970
- if (code === 0) resolve44({ stderr: "" });
1970
+ if (code === 0) resolve45({ stderr: "" });
1971
1971
  else reject(new Error(`${label} exited ${code}${message ? `: ${message}` : ""}`));
1972
1972
  });
1973
1973
  });
@@ -2582,7 +2582,7 @@ async function listInstallManifests(targetRoot, adapter, transport = localTransp
2582
2582
  try {
2583
2583
  const raw = JSON.parse(await transport.readFile(path));
2584
2584
  const parsed = installManifestSchema.parse(raw);
2585
- if (parsed.adapter !== adapter) continue;
2585
+ if (adapter !== void 0 && parsed.adapter !== adapter) continue;
2586
2586
  found.push({ path, fileName, stateKey, manifest: { ...parsed, revision: computeManifestRevision(raw) } });
2587
2587
  } catch (error) {
2588
2588
  throw new Error(`Unreadable install manifest at ${path}: ${error instanceof Error ? error.message : String(error)}`);
@@ -3236,15 +3236,15 @@ async function snapshotRepository(repositoryRoot) {
3236
3236
  async function collectIntroducedPaths(repositoryRoot, expectedHead, before, declaredPaths) {
3237
3237
  const after = await snapshotRepository(repositoryRoot);
3238
3238
  const touchedPreexisting = /* @__PURE__ */ new Set();
3239
- for (const [path, hash] of before.changed) {
3239
+ for (const [path, hash2] of before.changed) {
3240
3240
  if (declaredPaths.includes(path)) touchedPreexisting.add(path);
3241
3241
  else if (!after.changed.has(path)) {
3242
3242
  const head = await currentHead(repositoryRoot);
3243
3243
  const ancestor = await runProcess("git", ["-C", repositoryRoot, "merge-base", "--is-ancestor", expectedHead, head], {
3244
3244
  allowExitCodes: [0, 1]
3245
3245
  });
3246
- if (head === expectedHead || ancestor.exitCode !== 0 || await hashWorkingPath(repositoryRoot, path) !== hash || await hashHeadPath(repositoryRoot, head, path) !== hash) touchedPreexisting.add(path);
3247
- } else if (after.changed.get(path) !== hash) touchedPreexisting.add(path);
3246
+ if (head === expectedHead || ancestor.exitCode !== 0 || await hashWorkingPath(repositoryRoot, path) !== hash2 || await hashHeadPath(repositoryRoot, head, path) !== hash2) touchedPreexisting.add(path);
3247
+ } else if (after.changed.get(path) !== hash2) touchedPreexisting.add(path);
3248
3248
  }
3249
3249
  if (touchedPreexisting.size > 0) {
3250
3250
  throw new Error(`Mutation touched pre-existing dirty paths: ${[...touchedPreexisting].sort().join(", ")}.`);
@@ -3310,19 +3310,19 @@ async function hashWorkingPath(repositoryRoot, path) {
3310
3310
  throw new Error(`Unsupported repository path kind: ${path}`);
3311
3311
  }
3312
3312
  async function hashDirectory(root) {
3313
- const hash = createHash7("sha256");
3313
+ const hash2 = createHash7("sha256");
3314
3314
  async function walk2(dir) {
3315
3315
  for (const entry of (await readdir4(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
3316
3316
  if (entry.name === ".git" || entry.name === "node_modules") continue;
3317
3317
  const absolute = resolve12(dir, entry.name);
3318
3318
  const relativePath = normalizeRepoPath(relative5(root, absolute));
3319
3319
  if (entry.isDirectory()) await walk2(absolute);
3320
- else if (entry.isSymbolicLink()) hash.update(relativePath).update("\0").update(await readlink(absolute)).update("\0");
3321
- else if (entry.isFile()) hash.update(relativePath).update("\0").update(await readFile11(absolute)).update("\0");
3320
+ else if (entry.isSymbolicLink()) hash2.update(relativePath).update("\0").update(await readlink(absolute)).update("\0");
3321
+ else if (entry.isFile()) hash2.update(relativePath).update("\0").update(await readFile11(absolute)).update("\0");
3322
3322
  }
3323
3323
  }
3324
3324
  await walk2(root);
3325
- return hash.digest("hex");
3325
+ return hash2.digest("hex");
3326
3326
  }
3327
3327
  function splitNull(value) {
3328
3328
  return value.toString("utf8").split("\0").filter(Boolean);
@@ -3938,11 +3938,11 @@ function dirtyRepositoryPaths(repositoryRoot, baseline, paths) {
3938
3938
  function activeMutationMetadata() {
3939
3939
  return activeMutation?.metadata();
3940
3940
  }
3941
- async function reserveActiveRuntimeJournal(link2) {
3942
- await activeMutation?.transitionRuntimeJournal(link2, "reserved");
3941
+ async function reserveActiveRuntimeJournal(link3) {
3942
+ await activeMutation?.transitionRuntimeJournal(link3, "reserved");
3943
3943
  }
3944
- async function activateActiveRuntimeJournal(link2) {
3945
- await activeMutation?.transitionRuntimeJournal(link2, "pending");
3944
+ async function activateActiveRuntimeJournal(link3) {
3945
+ await activeMutation?.transitionRuntimeJournal(link3, "pending");
3946
3946
  }
3947
3947
  async function beginResolveMutationRuntimeJournal(operationId, path) {
3948
3948
  await transitionMutationRuntimeJournal(operationId, path, "resolving");
@@ -4208,14 +4208,14 @@ function receiptStatusForProvider(status) {
4208
4208
  if (status === "no-repository-delta") return "no-repository-delta";
4209
4209
  return "succeeded";
4210
4210
  }
4211
- function upsertRuntimeJournal(entries, link2, status) {
4212
- const existing = entries.find((entry) => entry.path === link2.path);
4213
- if (existing && (existing.transport !== link2.transport || existing.transportDescription !== link2.transportDescription || existing.journalDigest !== link2.journalDigest)) {
4214
- throw new Error(`Runtime journal link collision for ${link2.path}.`);
4211
+ function upsertRuntimeJournal(entries, link3, status) {
4212
+ const existing = entries.find((entry) => entry.path === link3.path);
4213
+ if (existing && (existing.transport !== link3.transport || existing.transportDescription !== link3.transportDescription || existing.journalDigest !== link3.journalDigest)) {
4214
+ throw new Error(`Runtime journal link collision for ${link3.path}.`);
4215
4215
  }
4216
4216
  return [
4217
- ...entries.filter((entry) => entry.path !== link2.path),
4218
- { ...link2, status }
4217
+ ...entries.filter((entry) => entry.path !== link3.path),
4218
+ { ...link3, status }
4219
4219
  ].sort((a, b) => a.path.localeCompare(b.path));
4220
4220
  }
4221
4221
  var GovernedMutation, activeMutation;
@@ -4416,11 +4416,12 @@ var init_coordinator = __esm({
4416
4416
  operationId: this.receipt.operationId,
4417
4417
  reason: this.receipt.reason,
4418
4418
  noCommit: this.receipt.noCommit,
4419
- revisionMode: this.receipt.revisionMode
4419
+ revisionMode: this.receipt.revisionMode,
4420
+ workspaceRoot: this.receipt.workspaceRoot
4420
4421
  };
4421
4422
  }
4422
- async transitionRuntimeJournal(link2, status) {
4423
- const runtimeJournals = upsertRuntimeJournal(this.receipt.runtimeJournals, link2, status);
4423
+ async transitionRuntimeJournal(link3, status) {
4424
+ const runtimeJournals = upsertRuntimeJournal(this.receipt.runtimeJournals, link3, status);
4424
4425
  this.receipt = await updateMutationReceipt(this.receipt, { runtimeJournals });
4425
4426
  }
4426
4427
  async transitionExistingRuntimeJournal(path, status) {
@@ -4488,20 +4489,88 @@ __export(transaction_exports, {
4488
4489
  applyLockPath: () => applyLockPath,
4489
4490
  assertApplyJournalRecoveryAllowed: () => assertApplyJournalRecoveryAllowed,
4490
4491
  assertGovernedRuntimeTransportSupported: () => assertGovernedRuntimeTransportSupported,
4492
+ assertNoSymlinkPath: () => assertNoSymlinkPath,
4491
4493
  listAllApplyJournals: () => listAllApplyJournals,
4492
4494
  listApplyJournals: () => listApplyJournals,
4493
4495
  localPathExists: () => localPathExists,
4496
+ metadataAuditPath: () => metadataAuditPath,
4497
+ metadataRuntimePath: () => metadataRuntimePath,
4494
4498
  mutationMetadataForApplyJournal: () => mutationMetadataForApplyJournal,
4499
+ ownershipRuntimeSnapshot: () => ownershipRuntimeSnapshot,
4495
4500
  readApplyJournal: () => readApplyJournal,
4496
4501
  readLinkedLocalApplyJournal: () => readLinkedLocalApplyJournal,
4497
4502
  recordBackup: () => recordBackup,
4498
4503
  removeApplyJournal: () => removeApplyJournal,
4499
4504
  rollbackCompletedOperations: () => rollbackCompletedOperations,
4505
+ syncMetadataPath: () => syncMetadataPath,
4500
4506
  writeApplyJournal: () => writeApplyJournal
4501
4507
  });
4502
4508
  import { createHash as createHash9 } from "crypto";
4503
- import { cp as cp2, mkdir as mkdir7, readFile as readFile13, rm as rm5, stat as stat4 } from "fs/promises";
4504
- import { dirname as dirname9, join as join11, resolve as resolve15 } from "path";
4509
+ import { cp as cp2, lstat as lstat2, mkdir as mkdir7, open as open3, readFile as readFile13, readdir as readdir5, rm as rm5, stat as stat4 } from "fs/promises";
4510
+ import { dirname as dirname9, join as join11, relative as relative7, resolve as resolve15, sep as sep5 } from "path";
4511
+ async function assertNoSymlinkPath(path) {
4512
+ const absolute = resolve15(path);
4513
+ let current = absolute;
4514
+ while (true) {
4515
+ try {
4516
+ if ((await lstat2(current)).isSymbolicLink()) throw new Error(`Symlink path is unsupported: ${current}`);
4517
+ } catch (error) {
4518
+ if (error.code !== "ENOENT") throw error;
4519
+ }
4520
+ const parent = dirname9(current);
4521
+ if (parent === current) break;
4522
+ current = parent;
4523
+ }
4524
+ }
4525
+ async function ownershipRuntimeSnapshot(path) {
4526
+ await assertNoSymlinkPath(path);
4527
+ const hash2 = createHash9("sha256");
4528
+ async function visit(candidate) {
4529
+ const info = await lstat2(candidate);
4530
+ if (info.isSymbolicLink() || !info.isDirectory() && !info.isFile()) {
4531
+ throw new Error(`Unsupported ownership runtime path: ${candidate}`);
4532
+ }
4533
+ hash2.update(JSON.stringify([relative7(path, candidate), info.isDirectory() ? "dir" : "file", info.mode & 4095]));
4534
+ if (info.isDirectory()) {
4535
+ for (const name of (await readdir5(candidate)).sort()) await visit(join11(candidate, name));
4536
+ } else {
4537
+ const content = await readFile13(candidate);
4538
+ hash2.update(String(content.length)).update("\0").update(content);
4539
+ }
4540
+ }
4541
+ await visit(path);
4542
+ return hash2.digest("hex");
4543
+ }
4544
+ function metadataAuditPath(audit, path) {
4545
+ mutationOperationIdSchema.parse(audit.operationId);
4546
+ if (resolve15(audit.workspaceRoot) !== audit.workspaceRoot || path !== `.agentwheel/ownership-releases/${audit.operationId}.json`) {
4547
+ throw new Error("Invalid ownership release audit path.");
4548
+ }
4549
+ return join11(audit.workspaceRoot, ...path.split("/"));
4550
+ }
4551
+ function metadataRuntimePath(root, path) {
4552
+ const result = resolve15(root, path);
4553
+ if (!path || relative7(resolve15(root), result).split(sep5).join("/") !== path || path === ".agentwheel" || path.startsWith(".agentwheel/") || result === resolve15(root) || !result.startsWith(`${resolve15(root)}${sep5}`)) {
4554
+ throw new Error(`Unsafe ownership release path: ${path}`);
4555
+ }
4556
+ return result;
4557
+ }
4558
+ async function syncMetadataPath(path, directoryOnly = false) {
4559
+ if (!directoryOnly) {
4560
+ const file = await open3(path, "r");
4561
+ try {
4562
+ await file.sync();
4563
+ } finally {
4564
+ await file.close();
4565
+ }
4566
+ }
4567
+ const directory = await open3(directoryOnly ? path : dirname9(path), "r");
4568
+ try {
4569
+ await directory.sync();
4570
+ } finally {
4571
+ await directory.close();
4572
+ }
4573
+ }
4505
4574
  function applyLockPath(targetRoot, adapter, scope = {}) {
4506
4575
  const installationType = scope.installationType ?? "local";
4507
4576
  return join11(metadataDir(targetRoot), `${stateKeyFor(adapter, { installationType })}.runtime-apply-lock`);
@@ -4543,30 +4612,31 @@ async function writeApplyJournal(journal, transport = localTransport) {
4543
4612
  installationType: journal.installationType,
4544
4613
  stateKey: journal.stateKey
4545
4614
  });
4546
- let link2;
4615
+ let link3;
4547
4616
  if (journal.mutation) {
4548
- const digest2 = applyJournalLinkDigest(journal, transport);
4549
- if (journal.mutation.journalDigest && journal.mutation.journalDigest !== digest2) {
4617
+ const digest3 = applyJournalLinkDigest(journal, transport);
4618
+ if (journal.mutation.journalDigest && journal.mutation.journalDigest !== digest3) {
4550
4619
  throw new Error(`Runtime apply journal identity changed for ${path}.`);
4551
4620
  }
4552
4621
  if (journal.mutation.transport && (journal.mutation.transport.kind !== transport.kind || journal.mutation.transport.description !== transport.description)) {
4553
4622
  throw new Error(`Runtime apply journal transport changed for ${path}.`);
4554
4623
  }
4555
- journal.mutation.journalDigest = digest2;
4624
+ journal.mutation.journalDigest = digest3;
4556
4625
  journal.mutation.transport = { kind: transport.kind, description: transport.description };
4557
- link2 = {
4626
+ link3 = {
4558
4627
  path,
4559
4628
  transport: transport.kind,
4560
4629
  transportDescription: transport.description,
4561
- journalDigest: digest2
4630
+ journalDigest: digest3
4562
4631
  };
4563
- await reserveActiveRuntimeJournal(link2);
4632
+ await reserveActiveRuntimeJournal(link3);
4564
4633
  }
4565
4634
  await transport.writeJsonAtomic(path, {
4566
4635
  ...journal,
4567
4636
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4568
4637
  });
4569
- if (link2) await activateActiveRuntimeJournal(link2);
4638
+ if ((journal.metadataAudit || journal.metadataGuards) && transport.kind === "local") await syncMetadataPath(path);
4639
+ if (link3) await activateActiveRuntimeJournal(link3);
4570
4640
  }
4571
4641
  async function readApplyJournal(targetRoot, adapter, transport = localTransport, scope = {}) {
4572
4642
  const path = applyJournalPath(targetRoot, adapter, scope);
@@ -4593,7 +4663,7 @@ async function listAllApplyJournals(targetRoot, adapter, transport = localTransp
4593
4663
  if (!fileName.endsWith(suffix)) continue;
4594
4664
  const path = join11(metadataDir(targetRoot), fileName);
4595
4665
  const journal = parseApplyJournal(JSON.parse(await transport.readFile(path)));
4596
- if (journal.adapter === adapter) found.push({ path, journal });
4666
+ if (adapter === void 0 || journal.adapter === adapter) found.push({ path, journal });
4597
4667
  }
4598
4668
  return found.sort((a, b) => a.path.localeCompare(b.path));
4599
4669
  }
@@ -4632,6 +4702,7 @@ async function removeApplyJournal(targetRoot, adapter, transport = localTranspor
4632
4702
  if (existing?.mutation) await beginResolveMutationRuntimeJournal(existing.mutation.operationId, path);
4633
4703
  await transport.rm(applyJournalPath(targetRoot, adapter, scope));
4634
4704
  await transport.rm(applyBackupDir(targetRoot, adapter, scope));
4705
+ if ((existing?.metadataAudit || existing?.metadataGuards) && transport.kind === "local") await syncMetadataPath(dirname9(path), true);
4635
4706
  if (existing?.mutation) await resolveMutationRuntimeJournal(existing.mutation.operationId, path);
4636
4707
  }
4637
4708
  async function abortApplyJournal(targetRoot, adapter, transport = localTransport, scope = {}) {
@@ -4644,6 +4715,9 @@ async function abortApplyJournal(targetRoot, adapter, transport = localTransport
4644
4715
  const archivePath = join11(metadataDir(targetRoot), "archive", `${stateKey}.apply-journal.failed-${journalTimestamp(/* @__PURE__ */ new Date())}.json`);
4645
4716
  const content = await transport.readFile(journalPath);
4646
4717
  const journal = parseApplyJournal(JSON.parse(content));
4718
+ if (journal.metadataAudit || journal.metadataGuards) {
4719
+ throw new Error("A guarded metadata transaction must be recovered and verified; abort cannot discard its partial state.");
4720
+ }
4647
4721
  await transport.writeFileAtomic(archivePath, content.endsWith("\n") ? content : `${content}
4648
4722
  `);
4649
4723
  if (journal.mutation) await beginResolveMutationRuntimeJournal(journal.mutation.operationId, journalPath);
@@ -4695,7 +4769,9 @@ function applyJournalLinkDigest(journal, transport) {
4695
4769
  graphLockRemovePath: journal.graphLockRemovePath ?? null,
4696
4770
  stateRemoveKey: journal.stateRemoveKey ?? null,
4697
4771
  workspaceConfigPath: journal.workspaceConfigPath ?? null,
4698
- operations: journal.operations
4772
+ operations: journal.operations,
4773
+ ...journal.metadataAudit ? { metadataAudit: journal.metadataAudit, manifest: journal.manifest } : {},
4774
+ ...journal.metadataGuards ? { metadataGuards: journal.metadataGuards, manifest: journal.manifest } : {}
4699
4775
  })).digest("hex");
4700
4776
  }
4701
4777
  function assertApplyJournalRecoveryAllowed(journal) {
@@ -5363,7 +5439,56 @@ var init_desired = __esm({
5363
5439
  import { createHash as createHash10 } from "crypto";
5364
5440
  import { mkdtemp as mkdtemp2, readFile as readFile17, realpath, rm as rm6, writeFile as writeFile11 } from "fs/promises";
5365
5441
  import { tmpdir as tmpdir3 } from "os";
5366
- import { basename as basename2, dirname as dirname13, join as join12, relative as relative7 } from "path";
5442
+ import { basename as basename2, dirname as dirname13, join as join12, relative as relative8 } from "path";
5443
+ function exactManagedInstructionBlockSnapshot(content, selector) {
5444
+ const beginCount = [...content.matchAll(new RegExp(`<!-- BEGIN openpack:include ${escapeRegex(selector)}(?=\\s|-->)`, "gu"))].length;
5445
+ const endCount = [...content.matchAll(new RegExp(`<!-- END openpack:include ${escapeRegex(selector)}(?=\\s|-->)`, "gu"))].length;
5446
+ if (beginCount !== 1 || endCount !== 1) throw new Error("Duplicate or missing managed instruction markers; adoption is refused.");
5447
+ const stack = [];
5448
+ let selectedBegin;
5449
+ let selectedEnd;
5450
+ let begins = 0;
5451
+ let ends = 0;
5452
+ for (const token of content.matchAll(/<!-- (BEGIN|END) openpack:include ([^\r\n]*?) -->/gu)) {
5453
+ const at = token.index;
5454
+ if (token[1] === "BEGIN") {
5455
+ const begin = /^(.*?) sha256:([a-f0-9]{64})$/u.exec(token[2]);
5456
+ if (!begin) throw new Error("Malformed managed instruction begin marker; adoption is refused.");
5457
+ const name = begin[1];
5458
+ if (name === selector) {
5459
+ if (++begins !== 1 || stack.length !== 0) throw new Error("Duplicate or overlapping managed instruction block; adoption is refused.");
5460
+ let bodyStart = at + token[0].length;
5461
+ if (content.slice(bodyStart, bodyStart + 2) === "\r\n") bodyStart += 2;
5462
+ else if (content[bodyStart] === "\n") bodyStart++;
5463
+ selectedBegin = { start: at, bodyStart, hash: begin[2] };
5464
+ }
5465
+ stack.push(name);
5466
+ } else {
5467
+ const name = token[2];
5468
+ if (stack.pop() !== name) throw new Error("Overlapping or unmatched managed instruction markers; adoption is refused.");
5469
+ if (name === selector) {
5470
+ if (++ends !== 1 || !selectedBegin) throw new Error("Duplicate or missing managed instruction marker; adoption is refused.");
5471
+ let end = at + token[0].length;
5472
+ if (content.slice(end, end + 2) === "\r\n") end += 2;
5473
+ else if (content[end] === "\n") end++;
5474
+ selectedEnd = { bodyEnd: at, end };
5475
+ }
5476
+ }
5477
+ }
5478
+ if (stack.length || begins !== 1 || ends !== 1 || !selectedBegin || !selectedEnd) {
5479
+ throw new Error(`Missing or incomplete managed instruction block for ${selector}; adoption is refused.`);
5480
+ }
5481
+ const hash2 = hashText(content.slice(selectedBegin.bodyStart, selectedEnd.bodyEnd));
5482
+ if (hash2 !== selectedBegin.hash) throw new Error(`Managed instruction block drift detected for ${selector}; adoption is refused.`);
5483
+ return {
5484
+ selector,
5485
+ hash: hash2,
5486
+ markerHash: selectedBegin.hash,
5487
+ prefixHash: hashText(content.slice(0, selectedBegin.start)),
5488
+ suffixHash: hashText(content.slice(selectedEnd.end)),
5489
+ blockBytesHash: hashText(content.slice(selectedBegin.start, selectedEnd.end))
5490
+ };
5491
+ }
5367
5492
  async function desiredManagedInstructionBlockHash(sourcePath) {
5368
5493
  const source = await readFile17(sourcePath, "utf8");
5369
5494
  return hashText(managedBlockBody(source));
@@ -5375,13 +5500,13 @@ async function readManagedInstructionBlockState(destPath, selector, transport) {
5375
5500
  const content = await transport.readFile(destPath);
5376
5501
  const block = findManagedInstructionBlock(content, selector);
5377
5502
  if (!block) return { exists: true, hasBlock: false, drifted: false };
5378
- const hash = hashText(block.body);
5503
+ const hash2 = hashText(block.body);
5379
5504
  return {
5380
5505
  exists: true,
5381
5506
  hasBlock: true,
5382
- hash,
5507
+ hash: hash2,
5383
5508
  markerHash: block.markerHash,
5384
- drifted: hash !== block.markerHash
5509
+ drifted: hash2 !== block.markerHash
5385
5510
  };
5386
5511
  }
5387
5512
  async function writeManagedInstructionBlock(sourcePath, destPath, selector, transport, options = {}) {
@@ -5420,12 +5545,12 @@ function managedInstructionSelector(selector, artifactType, artifactName) {
5420
5545
  }
5421
5546
  function renderManagedInstructionBlock(selector, source) {
5422
5547
  const body = managedBlockBody(source);
5423
- const hash = hashText(body);
5548
+ const hash2 = hashText(body);
5424
5549
  return {
5425
- block: `<!-- BEGIN openpack:include ${selector} sha256:${hash} -->
5550
+ block: `<!-- BEGIN openpack:include ${selector} sha256:${hash2} -->
5426
5551
  ${body}<!-- END openpack:include ${selector} -->
5427
5552
  `,
5428
- hash
5553
+ hash: hash2
5429
5554
  };
5430
5555
  }
5431
5556
  function upsertManagedInstructionBlock(content, selector, block, options) {
@@ -5507,7 +5632,7 @@ function referencesAgentsMd(content, claudePath, agentsPath) {
5507
5632
  const cleaned = referenced.trim().replace(/^["']|["']$/g, "");
5508
5633
  if (!/AGENTS\.md$/i.test(cleaned)) continue;
5509
5634
  const candidate = cleaned.startsWith("/") ? cleaned : join12(claudeDir, cleaned);
5510
- if (relative7(dirname13(agentsPath), candidate).replaceAll("\\", "/") === "AGENTS.md") return true;
5635
+ if (relative8(dirname13(agentsPath), candidate).replaceAll("\\", "/") === "AGENTS.md") return true;
5511
5636
  if (candidate === agentsPath) return true;
5512
5637
  }
5513
5638
  return false;
@@ -5564,8 +5689,8 @@ __export(apply_exports, {
5564
5689
  uninstall: () => uninstall
5565
5690
  });
5566
5691
  import { execFile as execFile4 } from "child_process";
5567
- import { createHash as createHash11 } from "crypto";
5568
- import { mkdtemp as mkdtemp3, readFile as readFile18, rm as rm7, writeFile as writeFile12 } from "fs/promises";
5692
+ import { createHash as createHash11, randomUUID as randomUUID3 } from "crypto";
5693
+ import { link as link2, mkdir as mkdir11, mkdtemp as mkdtemp3, open as open4, readFile as readFile18, rm as rm7, writeFile as writeFile12 } from "fs/promises";
5569
5694
  import { tmpdir as tmpdir4 } from "os";
5570
5695
  import { basename as basename3, dirname as dirname14, join as join13, resolve as resolve16 } from "path";
5571
5696
  import { promisify as promisify4 } from "util";
@@ -5838,20 +5963,35 @@ async function commitManifestMetadataJournal(journal, transport = localTransport
5838
5963
  async function commitJournalState(journal, transport, entries, now) {
5839
5964
  const manifest = withManifestRevision({
5840
5965
  ...journal.manifest,
5841
- generatedAt: now,
5966
+ generatedAt: journal.metadataAudit || journal.metadataGuards ? journal.createdAt : now,
5842
5967
  entries: entries ? entries.sort((a, b) => a.path.localeCompare(b.path)) : journal.manifest.entries
5843
5968
  });
5844
- if (journal.mode === "uninstall" && manifest.entries.length === 0) {
5969
+ if (journal.metadataGuards) await assertMetadataStateGuards(journal, manifest, journal.metadataGuards, transport);
5970
+ if (journal.metadataAudit) {
5971
+ await assertMetadataAuditGuards(journal, manifest, transport);
5972
+ for (const file of journal.metadataAudit.auditFiles) {
5973
+ const path = metadataAuditPath(journal.metadataAudit, file.path);
5974
+ declareMutationPath(path);
5975
+ await writeAuditFileExclusive(path, file.content);
5976
+ }
5977
+ await assertMetadataAuditGuards(journal, manifest, transport);
5978
+ }
5979
+ if (journal.mode === "uninstall" && manifest.entries.length === 0 && !journal.metadataAudit) {
5845
5980
  await removeStateFiles(journal.targetRoot, journal.adapter, transport, {
5846
5981
  installationType: journal.installationType,
5847
5982
  stateKey: journal.stateKey
5848
5983
  });
5984
+ if (journal.metadataGuards) await syncMetadataPath(metadataDir(journal.targetRoot), true);
5849
5985
  } else {
5850
5986
  if (journal.sourceLock) await writeSourceLock(journal.targetRoot, journal.adapter, journal.sourceLock, transport, {
5851
5987
  installationType: journal.installationType,
5852
5988
  stateKey: journal.stateKey
5853
5989
  });
5854
5990
  await writeInstallManifest(manifest, transport);
5991
+ if (journal.metadataAudit || journal.metadataGuards) await syncMetadataPath(installManifestPath(journal.targetRoot, journal.adapter, {
5992
+ installationType: journal.installationType,
5993
+ stateKey: journal.stateKey
5994
+ }));
5855
5995
  }
5856
5996
  if (journal.graphLockPath && journal.graphLock) await writeGraphLock(journal.graphLockPath, journal.graphLock);
5857
5997
  if (journal.stateRemoveKey && journal.stateRemoveKey !== journal.stateKey) {
@@ -5869,6 +6009,8 @@ async function commitJournalState(journal, transport, entries, now) {
5869
6009
  await writeJsonAtomic(journal.workspaceConfigPath, journal.workspaceConfig);
5870
6010
  }
5871
6011
  const verifiedManifest = await assertCommittedJournalState(journal, manifest, transport);
6012
+ if (journal.metadataAudit) await assertMetadataAuditGuards(journal, manifest, transport, true);
6013
+ if (journal.metadataGuards) await assertMetadataStateGuards(journal, manifest, journal.metadataGuards, transport, true);
5872
6014
  await removeApplyJournal(journal.targetRoot, journal.adapter, transport, {
5873
6015
  installationType: journal.installationType,
5874
6016
  stateKey: journal.stateKey
@@ -5884,7 +6026,7 @@ async function commitJournalState(journal, transport, entries, now) {
5884
6026
  async function assertCommittedJournalState(journal, expectedManifest, transport) {
5885
6027
  const scope = { installationType: journal.installationType, stateKey: journal.stateKey };
5886
6028
  const actualManifest = await readInstallManifest(journal.targetRoot, journal.adapter, transport, scope);
5887
- if (journal.mode === "uninstall" && expectedManifest.entries.length === 0) {
6029
+ if (journal.mode === "uninstall" && expectedManifest.entries.length === 0 && !journal.metadataAudit) {
5888
6030
  if (actualManifest) throw new Error("Uninstall postcheck found an install manifest that should have been removed.");
5889
6031
  } else if (!actualManifest) {
5890
6032
  throw new Error(
@@ -5924,6 +6066,88 @@ async function assertCommittedJournalState(journal, expectedManifest, transport)
5924
6066
  }
5925
6067
  return actualManifest;
5926
6068
  }
6069
+ async function assertMetadataAuditGuards(journal, after, transport, requireAfter = false) {
6070
+ const audit = journal.metadataAudit;
6071
+ const sha = /^[a-f0-9]{64}$/;
6072
+ if (transport.kind !== "local" || audit.kind !== "ownership-release" || after.adapter !== journal.adapter || after.targetRoot !== journal.targetRoot || after.installationType !== journal.installationType || after.stateKey !== journal.stateKey || journal.mode !== "uninstall" || journal.operations.length || journal.completed.length || journal.sourceLock || journal.graphLock || journal.graphLockPath || journal.graphLockRemovePath || journal.stateRemoveKey || journal.workspaceConfigPath || journal.workspaceConfig || !sha.test(audit.planDigest) || !sha.test(journal.baseRevision ?? "") || audit.auditFiles.length !== 1 || audit.runtime.length !== 1 || !audit.inventory.length) {
6073
+ throw new Error("Invalid metadata-audit transaction; no state was committed.");
6074
+ }
6075
+ await assertMetadataStateGuards(journal, after, audit, transport, requireAfter);
6076
+ for (const file of audit.auditFiles) {
6077
+ const path = metadataAuditPath(audit, file.path);
6078
+ await assertNoSymlinkPath(path);
6079
+ if (!sha.test(file.sha256) || createHash11("sha256").update(file.content).digest("hex") !== file.sha256) {
6080
+ throw new Error("Metadata-audit content digest is invalid.");
6081
+ }
6082
+ try {
6083
+ if (await readFile18(path, "utf8") !== file.content) throw new Error(`Metadata-audit file changed: ${path}`);
6084
+ } catch (error) {
6085
+ if (error.code !== "ENOENT" || requireAfter) throw error;
6086
+ }
6087
+ }
6088
+ }
6089
+ async function assertMetadataStateGuards(journal, after, guards, transport, requireAfter = false) {
6090
+ const sha = /^[a-f0-9]{64}$/;
6091
+ if (transport.kind !== "local" || journal.metadataAudit && journal.metadataGuards || after.adapter !== journal.adapter || after.targetRoot !== journal.targetRoot || after.installationType !== journal.installationType || after.stateKey !== journal.stateKey || journal.mode !== "uninstall" || journal.operations.length || journal.completed.length || journal.sourceLock || journal.graphLock || journal.graphLockPath || journal.graphLockRemovePath || journal.stateRemoveKey || journal.workspaceConfigPath || journal.workspaceConfig || journal.baseRevision !== null && !sha.test(journal.baseRevision) || !guards.inventory.length || !guards.runtime.length) {
6092
+ throw new Error("Invalid guarded metadata transaction; no state was committed.");
6093
+ }
6094
+ await assertNoSymlinkPath(journal.targetRoot);
6095
+ await assertNoSymlinkPath(metadataDir(journal.targetRoot));
6096
+ const inventory = await listInstallManifests(journal.targetRoot, void 0, transport);
6097
+ for (const item of inventory) await assertNoSymlinkPath(item.path);
6098
+ const before = new Map(guards.inventory.map((item) => [item.stateKey, item.revision]));
6099
+ if (before.size !== guards.inventory.length || [...before.values()].some((revision) => !sha.test(revision)) || (before.get(journal.stateKey) ?? null) !== journal.baseRevision) {
6100
+ throw new Error("Invalid guarded metadata inventory baseline.");
6101
+ }
6102
+ const next = new Map(before);
6103
+ if (after.entries.length === 0 && !journal.metadataAudit) next.delete(journal.stateKey);
6104
+ else next.set(journal.stateKey, after.revision);
6105
+ const actual = new Map(inventory.map((item) => [item.stateKey, item.manifest.revision]));
6106
+ const equals = (expected) => actual.size === expected.size && [...expected].every(([key, revision]) => actual.get(key) === revision);
6107
+ if (!equals(next) && (requireAfter || !equals(before))) {
6108
+ throw new Error("Metadata inventory/manifest CAS failed; concurrent state was preserved.");
6109
+ }
6110
+ for (const guard of guards.runtime) {
6111
+ const path = metadataRuntimePath(journal.targetRoot, guard.path);
6112
+ if (!sha.test(guard.hash) || !sha.test(guard.snapshotDigest) || await ownershipRuntimeSnapshot(path) !== guard.snapshotDigest || await transport.hashPath(path) !== guard.hash) {
6113
+ throw new Error(`Metadata runtime CAS failed at ${guard.path}; runtime was preserved.`);
6114
+ }
6115
+ if (guard.managedBlock) {
6116
+ const current = exactManagedInstructionBlockSnapshot(await transport.readFile(path), guard.managedBlock.selector);
6117
+ if (canonicalJson5(current) !== canonicalJson5(guard.managedBlock)) {
6118
+ throw new Error(`Managed instruction snapshot CAS failed at ${guard.path}.`);
6119
+ }
6120
+ }
6121
+ }
6122
+ }
6123
+ async function writeAuditFileExclusive(path, content) {
6124
+ await assertNoSymlinkPath(path);
6125
+ await mkdir11(dirname14(path), { recursive: true });
6126
+ await syncMetadataPath(dirname14(dirname14(path)), true);
6127
+ const temporary = `${path}.pending-${randomUUID3()}`;
6128
+ try {
6129
+ const handle = await open4(temporary, "wx", 384);
6130
+ try {
6131
+ await handle.writeFile(content, "utf8");
6132
+ await handle.sync();
6133
+ } finally {
6134
+ await handle.close();
6135
+ }
6136
+ try {
6137
+ await link2(temporary, path);
6138
+ } catch (error) {
6139
+ if (error.code !== "EEXIST" || await readFile18(path, "utf8") !== content) throw error;
6140
+ }
6141
+ const directory = await open4(dirname14(path), "r");
6142
+ try {
6143
+ await directory.sync();
6144
+ } finally {
6145
+ await directory.close();
6146
+ }
6147
+ } finally {
6148
+ await rm7(temporary, { force: true });
6149
+ }
6150
+ }
5927
6151
  function canonicalJson5(value) {
5928
6152
  if (Array.isArray(value)) return `[${value.map((item) => canonicalJson5(item === void 0 ? null : item)).join(",")}]`;
5929
6153
  if (value === null || typeof value !== "object") return JSON.stringify(value);
@@ -5973,13 +6197,13 @@ async function applyOperation(operation, context) {
5973
6197
  }
5974
6198
  if (operation.mode === managedInstructionBlockMode) {
5975
6199
  const selector = managedInstructionSelector(operation.logicalSelector, operation.artifactType, operation.artifactName);
5976
- const hash2 = await writeManagedInstructionBlock(operation.sourcePath, operation.destPath, selector, transport, managedBlockMutationOptions(operation));
5977
- if (hash2 !== operation.desiredHash) {
5978
- throw new Error(`Managed block hash verification failed for ${operation.relativeDestPath}: expected ${operation.desiredHash}, got ${hash2}`);
6200
+ const hash3 = await writeManagedInstructionBlock(operation.sourcePath, operation.destPath, selector, transport, managedBlockMutationOptions(operation));
6201
+ if (hash3 !== operation.desiredHash) {
6202
+ throw new Error(`Managed block hash verification failed for ${operation.relativeDestPath}: expected ${operation.desiredHash}, got ${hash3}`);
5979
6203
  }
5980
6204
  return manifestEntryForOperation(operation, {
5981
6205
  now,
5982
- hash: hash2,
6206
+ hash: hash3,
5983
6207
  sourceHash: operation.desiredHash,
5984
6208
  graphLockDigest: context.graphLockDigest
5985
6209
  });
@@ -5997,13 +6221,13 @@ async function applyOperation(operation, context) {
5997
6221
  } else {
5998
6222
  await transport.atomicCopy(operation.sourcePath, operation.destPath, operation.kind);
5999
6223
  }
6000
- const hash = await transport.hashPath(operation.destPath);
6001
- if (!operation.mergeStrategy && hash !== operation.desiredHash) {
6002
- throw new Error(`Hash verification failed for ${operation.relativeDestPath}: expected ${operation.desiredHash}, got ${hash}`);
6224
+ const hash2 = await transport.hashPath(operation.destPath);
6225
+ if (!operation.mergeStrategy && hash2 !== operation.desiredHash) {
6226
+ throw new Error(`Hash verification failed for ${operation.relativeDestPath}: expected ${operation.desiredHash}, got ${hash2}`);
6003
6227
  }
6004
6228
  return manifestEntryForOperation(operation, {
6005
6229
  now,
6006
- hash,
6230
+ hash: hash2,
6007
6231
  sourceHash: operation.desiredHash,
6008
6232
  graphLockDigest: context.graphLockDigest
6009
6233
  });
@@ -6599,6 +6823,7 @@ var init_apply = __esm({
6599
6823
  init_openclaw_json_merge();
6600
6824
  init_manifest2();
6601
6825
  init_path_safety();
6826
+ init_paths();
6602
6827
  init_transaction();
6603
6828
  init_toml_merge();
6604
6829
  init_yaml_merge();
@@ -6647,11 +6872,11 @@ var init_identify = __esm({
6647
6872
  });
6648
6873
 
6649
6874
  // src/cli/index.ts
6650
- import { createHash as createHash27 } from "crypto";
6875
+ import { createHash as createHash28 } from "crypto";
6651
6876
  import { existsSync } from "fs";
6652
- import { mkdir as mkdir26, mkdtemp as mkdtemp6, realpath as realpath4, rm as rm17, writeFile as writeFile24 } from "fs/promises";
6877
+ import { mkdir as mkdir27, mkdtemp as mkdtemp6, realpath as realpath4, rm as rm17, writeFile as writeFile24 } from "fs/promises";
6653
6878
  import { homedir as homedir18, tmpdir as tmpdir7 } from "os";
6654
- import { basename as basename24, dirname as dirname37, isAbsolute as isAbsolute14, join as join59, relative as relative18, resolve as resolve43 } from "path";
6879
+ import { basename as basename24, dirname as dirname37, isAbsolute as isAbsolute14, join as join61, relative as relative19, resolve as resolve44 } from "path";
6655
6880
  import { fileURLToPath as fileURLToPath4 } from "url";
6656
6881
  import { Command } from "commander";
6657
6882
 
@@ -6680,8 +6905,8 @@ async function loadProgrammaticAdapter(modulePath, options) {
6680
6905
  if (!stats.isFile()) {
6681
6906
  throw new Error(`Programmatic adapter module is not a file: ${resolvedPath}`);
6682
6907
  }
6683
- const hash = await hashPath(resolvedPath);
6684
- const importPath = extname(resolvedPath) === ".ts" ? await transpileTypeScriptAdapter(resolvedPath, hash) : resolvedPath;
6908
+ const hash2 = await hashPath(resolvedPath);
6909
+ const importPath = extname(resolvedPath) === ".ts" ? await transpileTypeScriptAdapter(resolvedPath, hash2) : resolvedPath;
6685
6910
  const imported = await import(`${pathToFileURL(importPath).href}?agentwheel=${Date.now()}`);
6686
6911
  const candidate = imported.adapter;
6687
6912
  if (!candidate || typeof candidate !== "object") {
@@ -6690,7 +6915,7 @@ async function loadProgrammaticAdapter(modulePath, options) {
6690
6915
  const parsed = adapterSchema.parse(candidate);
6691
6916
  const runtime = {
6692
6917
  modulePath: resolvedPath,
6693
- hash,
6918
+ hash: hash2,
6694
6919
  capabilities: Array.isArray(candidate.capabilities) ? candidate.capabilities.filter((item) => typeof item === "string") : [],
6695
6920
  plan: typeof candidate.plan === "function" ? candidate.plan.bind(candidate) : void 0,
6696
6921
  apply: typeof candidate.apply === "function" ? candidate.apply.bind(candidate) : void 0,
@@ -6698,7 +6923,7 @@ async function loadProgrammaticAdapter(modulePath, options) {
6698
6923
  };
6699
6924
  return { ...parsed, programmatic: runtime };
6700
6925
  }
6701
- async function transpileTypeScriptAdapter(modulePath, hash) {
6926
+ async function transpileTypeScriptAdapter(modulePath, hash2) {
6702
6927
  const source = await readFile3(modulePath, "utf8");
6703
6928
  const output = ts.transpileModule(source, {
6704
6929
  compilerOptions: {
@@ -6710,7 +6935,7 @@ async function transpileTypeScriptAdapter(modulePath, hash) {
6710
6935
  },
6711
6936
  fileName: modulePath
6712
6937
  });
6713
- const outPath = join2(tmpdir(), `agentwheel-adapter-${hash}.mjs`);
6938
+ const outPath = join2(tmpdir(), `agentwheel-adapter-${hash2}.mjs`);
6714
6939
  await writeFile2(outPath, output.outputText, "utf8");
6715
6940
  return outPath;
6716
6941
  }
@@ -6739,11 +6964,11 @@ init_manifest2();
6739
6964
  // src/install/plan.ts
6740
6965
  init_adapter();
6741
6966
  init_manifest();
6742
- import { basename as basename8, join as join24, relative as relative8 } from "path";
6967
+ import { basename as basename8, join as join24, relative as relative9 } from "path";
6743
6968
 
6744
6969
  // src/staging/codex-subagents.ts
6745
6970
  init_fs();
6746
- import { mkdir as mkdir11, readFile as readFile19, writeFile as writeFile13 } from "fs/promises";
6971
+ import { mkdir as mkdir12, readFile as readFile19, writeFile as writeFile13 } from "fs/promises";
6747
6972
  import { basename as basename4, dirname as dirname15, join as join14 } from "path";
6748
6973
  import { parse as parseYaml } from "yaml";
6749
6974
  var requiredCodexAgentFields = ["name", "description", "developer_instructions"];
@@ -6790,7 +7015,7 @@ async function renderCodexSubagent(artifact, stageRoot) {
6790
7015
  }
6791
7016
  const markdown = await readFile19(markdownPath, "utf8");
6792
7017
  const toml = markdownToCodexAgentToml(agentName, markdown);
6793
- await mkdir11(dirname15(renderedPath), { recursive: true });
7018
+ await mkdir12(dirname15(renderedPath), { recursive: true });
6794
7019
  await writeFile13(renderedPath, toml, "utf8");
6795
7020
  return {
6796
7021
  ...artifact,
@@ -6872,7 +7097,7 @@ function escapeRegExp2(value) {
6872
7097
 
6873
7098
  // src/staging/copilot-artifacts.ts
6874
7099
  init_fs();
6875
- import { mkdir as mkdir12, readFile as readFile20, writeFile as writeFile14 } from "fs/promises";
7100
+ import { mkdir as mkdir13, readFile as readFile20, writeFile as writeFile14 } from "fs/promises";
6876
7101
  import { basename as basename5, dirname as dirname16, join as join15 } from "path";
6877
7102
  async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
6878
7103
  if (adapter?.name !== "copilot") return artifacts;
@@ -6904,7 +7129,7 @@ async function renderCopilotSubagent(artifact, stageRoot) {
6904
7129
  throw new Error(`Copilot subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
6905
7130
  }
6906
7131
  const markdown = await readFile20(markdownPath, "utf8");
6907
- await mkdir12(dirname16(renderedPath), { recursive: true });
7132
+ await mkdir13(dirname16(renderedPath), { recursive: true });
6908
7133
  await writeFile14(renderedPath, ensureCopilotAgentDescription(agentName, markdown), "utf8");
6909
7134
  return {
6910
7135
  ...artifact,
@@ -6959,7 +7184,7 @@ function yamlString(value) {
6959
7184
 
6960
7185
  // src/staging/openclaw-subagents.ts
6961
7186
  init_fs();
6962
- import { mkdir as mkdir13, readFile as readFile21, writeFile as writeFile15 } from "fs/promises";
7187
+ import { mkdir as mkdir14, readFile as readFile21, writeFile as writeFile15 } from "fs/promises";
6963
7188
  import { basename as basename6, dirname as dirname17, join as join16 } from "path";
6964
7189
  async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
6965
7190
  if (adapter?.name !== "openclaw") return artifacts;
@@ -6994,7 +7219,7 @@ async function renderOpenClawSubagent(artifact, stageRoot) {
6994
7219
 
6995
7220
  ${parsed.description ?? `OpenClaw subagent ${agentId}.`}`;
6996
7221
  const renderedPath = join16(stageRoot, ".agentwheel-rendered", "openclaw-subagents", agentId, "AGENTS.md");
6997
- await mkdir13(dirname17(renderedPath), { recursive: true });
7222
+ await mkdir14(dirname17(renderedPath), { recursive: true });
6998
7223
  await writeFile15(renderedPath, `${body}
6999
7224
  `, "utf8");
7000
7225
  const renderedDir = dirname17(renderedPath);
@@ -8497,7 +8722,7 @@ async function operationForArtifact(artifact, adapter, targetRoot, installationT
8497
8722
  kind: "file",
8498
8723
  sourcePath: artifact.stagedPath ?? artifact.sourcePath,
8499
8724
  destPath: destPath2,
8500
- relativeDestPath: relative8(targetRoot, destPath2).replaceAll("\\", "/"),
8725
+ relativeDestPath: relative9(targetRoot, destPath2).replaceAll("\\", "/"),
8501
8726
  desiredHash: artifact.hash,
8502
8727
  reason: "destination missing",
8503
8728
  channel: artifact.channel ?? "managed",
@@ -8515,7 +8740,7 @@ async function operationForArtifact(artifact, adapter, targetRoot, installationT
8515
8740
  kind: artifact.kind,
8516
8741
  sourcePath: artifact.stagedPath ?? artifact.sourcePath,
8517
8742
  destPath,
8518
- relativeDestPath: relative8(targetRoot, destPath).replaceAll("\\", "/"),
8743
+ relativeDestPath: relative9(targetRoot, destPath).replaceAll("\\", "/"),
8519
8744
  desiredHash: artifact.hash,
8520
8745
  reason: "destination missing",
8521
8746
  channel: artifact.channel ?? "managed",
@@ -9512,14 +9737,14 @@ async function writeMermaidAsset(response) {
9512
9737
  "content-type": "application/javascript; charset=utf-8",
9513
9738
  "cache-control": "public, max-age=3600"
9514
9739
  });
9515
- await new Promise((resolve44) => {
9740
+ await new Promise((resolve45) => {
9516
9741
  const stream = createReadStream(assetPath);
9517
9742
  stream.on("error", () => {
9518
9743
  if (!response.headersSent) writeText(response, 404, "Mermaid asset unavailable.\n");
9519
9744
  else response.destroy();
9520
- resolve44();
9745
+ resolve45();
9521
9746
  });
9522
- stream.on("end", resolve44);
9747
+ stream.on("end", resolve45);
9523
9748
  stream.pipe(response);
9524
9749
  });
9525
9750
  }
@@ -9546,14 +9771,14 @@ function escapeHtml2(value) {
9546
9771
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
9547
9772
  }
9548
9773
  function listen(server, port, bind) {
9549
- return new Promise((resolve44, reject) => {
9774
+ return new Promise((resolve45, reject) => {
9550
9775
  const onError = (error) => {
9551
9776
  server.off("listening", onListening);
9552
9777
  reject(error);
9553
9778
  };
9554
9779
  const onListening = () => {
9555
9780
  server.off("error", onError);
9556
- resolve44();
9781
+ resolve45();
9557
9782
  };
9558
9783
  server.once("error", onError);
9559
9784
  server.once("listening", onListening);
@@ -9561,7 +9786,7 @@ function listen(server, port, bind) {
9561
9786
  });
9562
9787
  }
9563
9788
  function waitForShutdown(server, beforeClose) {
9564
- return new Promise((resolve44) => {
9789
+ return new Promise((resolve45) => {
9565
9790
  let closing = false;
9566
9791
  const shutdown = () => {
9567
9792
  if (closing) return;
@@ -9569,7 +9794,7 @@ function waitForShutdown(server, beforeClose) {
9569
9794
  process.off("SIGINT", shutdown);
9570
9795
  process.off("SIGTERM", shutdown);
9571
9796
  beforeClose();
9572
- server.close(() => resolve44());
9797
+ server.close(() => resolve45());
9573
9798
  };
9574
9799
  process.once("SIGINT", shutdown);
9575
9800
  process.once("SIGTERM", shutdown);
@@ -9579,7 +9804,7 @@ function waitForShutdown(server, beforeClose) {
9579
9804
  process.off("SIGINT", shutdown);
9580
9805
  process.off("SIGTERM", shutdown);
9581
9806
  beforeClose();
9582
- resolve44();
9807
+ resolve45();
9583
9808
  });
9584
9809
  });
9585
9810
  }
@@ -9597,7 +9822,7 @@ function errorMessage2(error) {
9597
9822
  }
9598
9823
 
9599
9824
  // src/source/clawhub.ts
9600
- import { mkdir as mkdir14, rm as rm8, writeFile as writeFile16 } from "fs/promises";
9825
+ import { mkdir as mkdir15, rm as rm8, writeFile as writeFile16 } from "fs/promises";
9601
9826
  import { basename as basename10, dirname as dirname18, join as join28, resolve as resolve18 } from "path";
9602
9827
 
9603
9828
  // src/model/package.ts
@@ -9791,8 +10016,8 @@ init_fs();
9791
10016
 
9792
10017
  // src/source/local.ts
9793
10018
  import { createHash as createHash13 } from "crypto";
9794
- import { readdir as readdir5, stat as stat5 } from "fs/promises";
9795
- import { basename as basename9, join as join27, relative as relative9, resolve as resolve17 } from "path";
10019
+ import { readdir as readdir6, stat as stat5 } from "fs/promises";
10020
+ import { basename as basename9, join as join27, relative as relative10, resolve as resolve17 } from "path";
9796
10021
  init_fs();
9797
10022
  var LocalSourceDriver = class {
9798
10023
  name = "local";
@@ -9933,23 +10158,23 @@ var LocalSourceDriver = class {
9933
10158
  };
9934
10159
  async function hashLocalSource(root, manifest) {
9935
10160
  if (!manifest) return hashPath(root);
9936
- const hash = createHash13("sha256").update("local-openpack\0");
10161
+ const hash2 = createHash13("sha256").update("local-openpack\0");
9937
10162
  const manifestPath = await findPackageManifestPath(root, { warnLegacy: false });
9938
10163
  if (manifestPath) {
9939
- hash.update("manifest\0");
9940
- hash.update(relative9(root, manifestPath).replaceAll("\\", "/")).update("\0");
9941
- hash.update(await hashPath(manifestPath)).update("\0");
10164
+ hash2.update("manifest\0");
10165
+ hash2.update(relative10(root, manifestPath).replaceAll("\\", "/")).update("\0");
10166
+ hash2.update(await hashPath(manifestPath)).update("\0");
9942
10167
  }
9943
10168
  const provides = [...manifest.provides].sort((a, b) => `${a.type}\0${a.path}`.localeCompare(`${b.type}\0${b.path}`));
9944
10169
  for (const provide of provides) {
9945
10170
  const full = join27(root, provide.path);
9946
10171
  if (!await pathExists(full)) continue;
9947
- hash.update("provide\0");
9948
- hash.update(provide.type).update("\0");
9949
- hash.update(provide.path.replaceAll("\\", "/")).update("\0");
9950
- hash.update(await hashPath(full)).update("\0");
10172
+ hash2.update("provide\0");
10173
+ hash2.update(provide.type).update("\0");
10174
+ hash2.update(provide.path.replaceAll("\\", "/")).update("\0");
10175
+ hash2.update(await hashPath(full)).update("\0");
9951
10176
  }
9952
- return hash.digest("hex");
10177
+ return hash2.digest("hex");
9953
10178
  }
9954
10179
  async function firstExisting(paths) {
9955
10180
  for (const path of paths) {
@@ -9958,7 +10183,7 @@ async function firstExisting(paths) {
9958
10183
  return void 0;
9959
10184
  }
9960
10185
  async function sortedDirEntries(path) {
9961
- return (await readdir5(path, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
10186
+ return (await readdir6(path, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
9962
10187
  }
9963
10188
  async function listFromManifest(root, packageName) {
9964
10189
  const manifest = await readPackageManifest(root);
@@ -10139,7 +10364,7 @@ async function fetchClawHubPackage(fetchImpl, packageName) {
10139
10364
  throw new Error(`ClawHub lookup failed for ${packageName}`);
10140
10365
  }
10141
10366
  async function delay(ms) {
10142
- await new Promise((resolve44) => setTimeout(resolve44, ms));
10367
+ await new Promise((resolve45) => setTimeout(resolve45, ms));
10143
10368
  }
10144
10369
  function parseClawHubSource(source) {
10145
10370
  if (!source.startsWith(sourcePrefix)) {
@@ -10171,7 +10396,7 @@ async function writeGeneratedPackage(root, packageInfo) {
10171
10396
  };
10172
10397
  const pluginPath = join28(root, "plugins", pluginId, "clawhub.json");
10173
10398
  await rm8(root, { recursive: true, force: true });
10174
- await mkdir14(dirname18(pluginPath), { recursive: true });
10399
+ await mkdir15(dirname18(pluginPath), { recursive: true });
10175
10400
  await writeFile16(join28(root, "openpack.json"), `${JSON.stringify({
10176
10401
  schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
10177
10402
  name: `clawhub/${name}`,
@@ -10202,9 +10427,9 @@ function cachePathFor(packageName, cacheRoot) {
10202
10427
 
10203
10428
  // src/source/git.ts
10204
10429
  import { execFile as execFile5 } from "child_process";
10205
- import { mkdir as mkdir16, rename as rename6, rm as rm10, stat as stat7 } from "fs/promises";
10430
+ import { mkdir as mkdir17, rename as rename6, rm as rm10, stat as stat7 } from "fs/promises";
10206
10431
  import { homedir as homedir7 } from "os";
10207
- import { basename as basename11, dirname as dirname20, join as join31, resolve as resolve19, sep as sep5 } from "path";
10432
+ import { basename as basename11, dirname as dirname20, join as join31, resolve as resolve19, sep as sep6 } from "path";
10208
10433
  import { promisify as promisify5 } from "util";
10209
10434
  init_fs();
10210
10435
 
@@ -10285,8 +10510,8 @@ function isMissingFile(error) {
10285
10510
 
10286
10511
  // src/source/cache.ts
10287
10512
  init_fs();
10288
- import { randomUUID as randomUUID3 } from "crypto";
10289
- import { mkdir as mkdir15, readdir as readdir6, readFile as readFile27, rm as rm9, stat as stat6, writeFile as writeFile17 } from "fs/promises";
10513
+ import { randomUUID as randomUUID4 } from "crypto";
10514
+ import { mkdir as mkdir16, readdir as readdir7, readFile as readFile27, rm as rm9, stat as stat6, writeFile as writeFile17 } from "fs/promises";
10290
10515
  import { dirname as dirname19, join as join30 } from "path";
10291
10516
  var snapshotNamePattern = /^(.*)-([0-9a-f]{12})$/i;
10292
10517
  var leaseMarker = ".agentwheel-lease-";
@@ -10301,11 +10526,11 @@ async function pruneGitCache(cacheRoot, options = {}) {
10301
10526
  }
10302
10527
  async function withGitCacheMaintenanceLock(cacheRoot, timeoutMs, fn) {
10303
10528
  const lockPath = join30(cacheRoot, ".maintenance.lock");
10304
- await mkdir15(cacheRoot, { recursive: true });
10529
+ await mkdir16(cacheRoot, { recursive: true });
10305
10530
  const started = Date.now();
10306
10531
  while (true) {
10307
10532
  try {
10308
- await mkdir15(lockPath);
10533
+ await mkdir16(lockPath);
10309
10534
  await writeFile17(
10310
10535
  join30(lockPath, "owner.json"),
10311
10536
  JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }),
@@ -10318,7 +10543,7 @@ async function withGitCacheMaintenanceLock(cacheRoot, timeoutMs, fn) {
10318
10543
  if (Date.now() - started > timeoutMs) {
10319
10544
  throw new Error(`Timed out waiting for git cache maintenance lock at ${lockPath}`);
10320
10545
  }
10321
- await new Promise((resolve44) => setTimeout(resolve44, 50));
10546
+ await new Promise((resolve45) => setTimeout(resolve45, 50));
10322
10547
  }
10323
10548
  }
10324
10549
  try {
@@ -10328,7 +10553,7 @@ async function withGitCacheMaintenanceLock(cacheRoot, timeoutMs, fn) {
10328
10553
  }
10329
10554
  }
10330
10555
  async function createGitSnapshotLease(snapshotPath) {
10331
- const leasePath = `${snapshotPath}${leaseMarker}${process.pid}-${randomUUID3()}`;
10556
+ const leasePath = `${snapshotPath}${leaseMarker}${process.pid}-${randomUUID4()}`;
10332
10557
  await writeFile17(leasePath, JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }), {
10333
10558
  encoding: "utf8",
10334
10559
  flag: "wx"
@@ -10341,7 +10566,7 @@ async function releaseGitSnapshotLease(leasePath) {
10341
10566
  async function removeGeneratedEntries(root, preserveGit) {
10342
10567
  let entries;
10343
10568
  try {
10344
- entries = await readdir6(root, { withFileTypes: true });
10569
+ entries = await readdir7(root, { withFileTypes: true });
10345
10570
  } catch {
10346
10571
  return;
10347
10572
  }
@@ -10356,7 +10581,7 @@ async function removeGeneratedEntries(root, preserveGit) {
10356
10581
  }
10357
10582
  async function pruneGitCacheUnlocked(cacheRoot, options) {
10358
10583
  const referencedCommits = await referencedGraphLockCommits(join30(dirname19(cacheRoot), "locks"));
10359
- const entries = await readdir6(cacheRoot, { withFileTypes: true });
10584
+ const entries = await readdir7(cacheRoot, { withFileTypes: true });
10360
10585
  const groups = /* @__PURE__ */ new Map();
10361
10586
  for (const entry of entries) {
10362
10587
  if (!entry.isDirectory()) continue;
@@ -10403,7 +10628,7 @@ async function referencedGraphLockCommits(lockRoot) {
10403
10628
  async function walkGraphLocks(root, visit) {
10404
10629
  let entries;
10405
10630
  try {
10406
- entries = await readdir6(root, { withFileTypes: true });
10631
+ entries = await readdir7(root, { withFileTypes: true });
10407
10632
  } catch (error) {
10408
10633
  if (isNotFound(error)) return;
10409
10634
  throw new Error(`Cannot inspect graph-lock directory ${root}; cache prune aborted: ${errorMessage3(error)}`);
@@ -10424,7 +10649,7 @@ async function walkGraphLocks(root, visit) {
10424
10649
  async function hasLiveSnapshotLease(snapshotPath, dryRun) {
10425
10650
  const directory = dirname19(snapshotPath);
10426
10651
  const prefix = `${snapshotPath.slice(directory.length + 1)}${leaseMarker}`;
10427
- const entries = await readdir6(directory, { withFileTypes: true });
10652
+ const entries = await readdir7(directory, { withFileTypes: true });
10428
10653
  let live = false;
10429
10654
  for (const entry of entries) {
10430
10655
  if (!entry.isFile() || !entry.name.startsWith(prefix)) continue;
@@ -10523,10 +10748,10 @@ function normalizeGitSubpath(subpath, source) {
10523
10748
  }
10524
10749
  return normalized;
10525
10750
  }
10526
- function resolveGitRelativeSubpath(declaringSubpath, relative19, source) {
10527
- const joined = posix4.normalize(posix4.join(declaringSubpath ?? ".", relative19));
10751
+ function resolveGitRelativeSubpath(declaringSubpath, relative20, source) {
10752
+ const joined = posix4.normalize(posix4.join(declaringSubpath ?? ".", relative20));
10528
10753
  if (joined === ".." || joined.startsWith("../")) {
10529
- throw new Error(`Relative dependency '${relative19}' escapes the git repository it is declared in: ${source}`);
10754
+ throw new Error(`Relative dependency '${relative20}' escapes the git repository it is declared in: ${source}`);
10530
10755
  }
10531
10756
  return normalizeGitSubpath(joined, source);
10532
10757
  }
@@ -10562,7 +10787,7 @@ var GitSourceDriver = class {
10562
10787
  return withFilesystemLock(`${resolved.resolvedPath}.lock`, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
10563
10788
  const parsed = parseGitSource(resolved.source);
10564
10789
  const cacheRoot = dirname20(resolved.resolvedPath);
10565
- await mkdir16(cacheRoot, { recursive: true });
10790
+ await mkdir17(cacheRoot, { recursive: true });
10566
10791
  await assertOwnedByCurrentUser(cacheRoot);
10567
10792
  if (await pathExists(resolved.resolvedPath)) await assertOwnedByCurrentUser(resolved.resolvedPath);
10568
10793
  if (!await pathExists(join31(resolved.resolvedPath, ".git"))) {
@@ -10662,11 +10887,11 @@ async function snapshotCommit(checkoutPath, commit) {
10662
10887
  const tempIndexPath = `${tempPath}.index`;
10663
10888
  await rm10(tempPath, { recursive: true, force: true });
10664
10889
  await rm10(tempIndexPath, { force: true });
10665
- await mkdir16(tempPath, { recursive: true });
10890
+ await mkdir17(tempPath, { recursive: true });
10666
10891
  const env2 = { ...process.env, GIT_INDEX_FILE: tempIndexPath };
10667
10892
  try {
10668
10893
  await git(["-C", checkoutPath, "read-tree", commit], env2);
10669
- await git(["-C", checkoutPath, "checkout-index", "--all", `--prefix=${resolve19(tempPath)}${sep5}`], env2);
10894
+ await git(["-C", checkoutPath, "checkout-index", "--all", `--prefix=${resolve19(tempPath)}${sep6}`], env2);
10670
10895
  await removeGeneratedEntries(tempPath, false);
10671
10896
  } catch (error) {
10672
10897
  await rm10(tempPath, { recursive: true, force: true });
@@ -10695,7 +10920,7 @@ async function assertOwnedByCurrentUser(path) {
10695
10920
  }
10696
10921
 
10697
10922
  // src/source/mcp-registry.ts
10698
- import { mkdir as mkdir17, writeFile as writeFile18 } from "fs/promises";
10923
+ import { mkdir as mkdir18, writeFile as writeFile18 } from "fs/promises";
10699
10924
  import { basename as basename12, dirname as dirname21, join as join32, resolve as resolve20 } from "path";
10700
10925
  init_fs();
10701
10926
  var registryBaseUrl = "https://registry.modelcontextprotocol.io/v0.1";
@@ -10804,7 +11029,7 @@ function isSafeHttpUrl(value) {
10804
11029
  async function writeGeneratedPackage2(root, server) {
10805
11030
  const serverId = installNameFor3(server.serverName);
10806
11031
  const mcpPath = join32(root, "mcp", `${serverId}.json`);
10807
- await mkdir17(dirname21(mcpPath), { recursive: true });
11032
+ await mkdir18(dirname21(mcpPath), { recursive: true });
10808
11033
  await writeFile18(join32(root, "openpack.json"), `${JSON.stringify({
10809
11034
  schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
10810
11035
  name: `mcp-registry/${server.serverName}`,
@@ -10834,9 +11059,9 @@ function cachePathFor3(serverName, cacheRoot) {
10834
11059
  // src/source/skillkit.ts
10835
11060
  init_cache_identity();
10836
11061
  init_fs();
10837
- import { createHash as createHash14, randomUUID as randomUUID4 } from "crypto";
11062
+ import { createHash as createHash14, randomUUID as randomUUID5 } from "crypto";
10838
11063
  import { execFile as execFile6 } from "child_process";
10839
- import { cp as cp3, mkdir as mkdir18, readFile as readFile28, rename as rename7, rm as rm11 } from "fs/promises";
11064
+ import { cp as cp3, mkdir as mkdir19, readFile as readFile28, rename as rename7, rm as rm11 } from "fs/promises";
10840
11065
  import { homedir as homedir8 } from "os";
10841
11066
  import { basename as basename14, dirname as dirname23, join as join34, resolve as resolve21 } from "path";
10842
11067
  import { promisify as promisify6 } from "util";
@@ -10844,7 +11069,7 @@ import * as defaultSkillKit from "@skillkit/core";
10844
11069
 
10845
11070
  // src/source/skill-artifacts.ts
10846
11071
  init_fs();
10847
- import { readdir as readdir7, stat as stat8 } from "fs/promises";
11072
+ import { readdir as readdir8, stat as stat8 } from "fs/promises";
10848
11073
  import { basename as basename13, dirname as dirname22, extname as extname2, join as join33 } from "path";
10849
11074
  async function artifactsFromSkillPaths(paths, packageName) {
10850
11075
  const artifacts = [];
@@ -10912,7 +11137,7 @@ async function artifactFromSkillPath(item, packageName) {
10912
11137
  }
10913
11138
  async function walk(dir, paths) {
10914
11139
  if (!await pathExists(dir)) return;
10915
- const entries = await readdir7(dir, { withFileTypes: true });
11140
+ const entries = await readdir8(dir, { withFileTypes: true });
10916
11141
  if (entries.some((entry) => entry.isFile() && entry.name === "SKILL.md")) {
10917
11142
  paths.push({ path: dir });
10918
11143
  return;
@@ -11015,8 +11240,8 @@ var SkillKitSourceDriver = class {
11015
11240
  if (immutablePath && await pathExists(immutablePath)) {
11016
11241
  return { path: immutablePath, commit: requestedCommit, cacheIdentity: requestedCommit };
11017
11242
  }
11018
- await mkdir18(dirname23(specCachePath), { recursive: true });
11019
- const candidatePath = `${specCachePath}.agentwheel-tmp-${process.pid}-${randomUUID4()}`;
11243
+ await mkdir19(dirname23(specCachePath), { recursive: true });
11244
+ const candidatePath = `${specCachePath}.agentwheel-tmp-${process.pid}-${randomUUID5()}`;
11020
11245
  const publishPath = `${candidatePath}.publish`;
11021
11246
  let result;
11022
11247
  try {
@@ -11171,7 +11396,7 @@ async function checkoutCommit(root, commit) {
11171
11396
  // src/source/vercel-skills.ts
11172
11397
  init_fs();
11173
11398
  import { stat as stat9 } from "fs/promises";
11174
- import { basename as basename15, join as join35, relative as relative10, resolve as resolve22 } from "path";
11399
+ import { basename as basename15, join as join35, relative as relative11, resolve as resolve22 } from "path";
11175
11400
  var VercelSkillsSourceDriver = class {
11176
11401
  name = "vercel-skills";
11177
11402
  git = new GitSourceDriver();
@@ -11238,7 +11463,7 @@ async function resolveVercelSkillSubpath(root, subpath) {
11238
11463
  for (const candidate of candidates) {
11239
11464
  if (await pathExists(candidate)) return candidate;
11240
11465
  }
11241
- const tried = candidates.map((candidate) => relative10(root, candidate)).join(", ");
11466
+ const tried = candidates.map((candidate) => relative11(root, candidate)).join(", ");
11242
11467
  throw new Error(`Vercel skills subpath not found: ${subpath} (tried ${tried})`);
11243
11468
  }
11244
11469
  function parseVercelSource(source) {
@@ -11307,8 +11532,8 @@ function getSourceDriver(name = "local") {
11307
11532
  init_identify();
11308
11533
 
11309
11534
  // src/staging/staging.ts
11310
- import { chmod as chmod3, cp as cp5, mkdir as mkdir21, mkdtemp as mkdtemp4, readdir as readdir10, stat as stat12 } from "fs/promises";
11311
- import { basename as basename19, dirname as dirname27, join as join39, relative as relative12, resolve as resolve25, sep as sep7 } from "path";
11535
+ import { chmod as chmod3, cp as cp5, mkdir as mkdir22, mkdtemp as mkdtemp4, readdir as readdir11, stat as stat12 } from "fs/promises";
11536
+ import { basename as basename19, dirname as dirname27, join as join39, relative as relative13, resolve as resolve25, sep as sep8 } from "path";
11312
11537
  import { tmpdir as tmpdir5 } from "os";
11313
11538
  init_fs();
11314
11539
 
@@ -11316,8 +11541,8 @@ init_fs();
11316
11541
  init_artifact();
11317
11542
  init_fs();
11318
11543
  import { createHash as createHash15 } from "crypto";
11319
- import { readdir as readdir8, readFile as readFile29, stat as stat10, writeFile as writeFile19 } from "fs/promises";
11320
- import { basename as basename16, dirname as dirname24, extname as extname3, join as join36, relative as relative11, resolve as resolve24, sep as sep6 } from "path";
11544
+ import { readdir as readdir9, readFile as readFile29, stat as stat10, writeFile as writeFile19 } from "fs/promises";
11545
+ import { basename as basename16, dirname as dirname24, extname as extname3, join as join36, relative as relative12, resolve as resolve24, sep as sep7 } from "path";
11321
11546
  var includePattern = /<!--\s*openpack:include(\?)?\s+([^>]+?)\s*-->/g;
11322
11547
  var escapedIncludePattern = /<!--\s*openpack\\:include(\?)?\s+([^>]+?)\s*-->/g;
11323
11548
  var generatedPattern = /<!--\s*(?:BEGIN|END)\s+openpack:include\b/;
@@ -11527,7 +11752,7 @@ function extractOpenPackIncludeSelectors(content) {
11527
11752
  function resolvePackageSelector(packageRoot, selector) {
11528
11753
  const root = resolve24(packageRoot);
11529
11754
  const resolved = resolve24(root, selector);
11530
- if (resolved !== root && !resolved.startsWith(`${root}${sep6}`)) {
11755
+ if (resolved !== root && !resolved.startsWith(`${root}${sep7}`)) {
11531
11756
  throw new Error(`OpenPack include escapes package root: ${selector}`);
11532
11757
  }
11533
11758
  return resolved;
@@ -11542,7 +11767,7 @@ async function markdownFilesForArtifact(artifact) {
11542
11767
  async function listMarkdownFiles(root) {
11543
11768
  const out = [];
11544
11769
  async function walk2(dir) {
11545
- for (const entry of (await readdir8(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
11770
+ for (const entry of (await readdir9(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
11546
11771
  const full = join36(dir, entry.name);
11547
11772
  if (entry.isDirectory()) {
11548
11773
  await walk2(full);
@@ -11578,7 +11803,7 @@ function applyReplacements(content, replacements) {
11578
11803
  return out + content.slice(cursor);
11579
11804
  }
11580
11805
  function relativeSelector(root, file) {
11581
- return relative11(root, file).replaceAll("\\", "/");
11806
+ return relative12(root, file).replaceAll("\\", "/");
11582
11807
  }
11583
11808
  function ownerSelector(root, file, nodeId) {
11584
11809
  const selector = relativeSelector(root, file);
@@ -11608,7 +11833,7 @@ function artifactPathMap(artifacts) {
11608
11833
 
11609
11834
  // src/staging/customize.ts
11610
11835
  init_fs();
11611
- import { cp as cp4, mkdir as mkdir19, readdir as readdir9, readFile as readFile30, writeFile as writeFile20 } from "fs/promises";
11836
+ import { cp as cp4, mkdir as mkdir20, readdir as readdir10, readFile as readFile30, writeFile as writeFile20 } from "fs/promises";
11612
11837
  import { dirname as dirname25, join as join37 } from "path";
11613
11838
  async function applyCustomizations(artifacts, options) {
11614
11839
  let next = [...artifacts];
@@ -11633,7 +11858,7 @@ async function applyInstructionOverlay(artifacts, options) {
11633
11858
  const managed = await readFile30(artifact.stagedPath ?? artifact.sourcePath, "utf8");
11634
11859
  const local = await readFile30(overlayPath, "utf8");
11635
11860
  const composedPath = join37(options.stageRoot, ".agentwheel-composed", "instructions", "AGENTS.md");
11636
- await mkdir19(dirname25(composedPath), { recursive: true });
11861
+ await mkdir20(dirname25(composedPath), { recursive: true });
11637
11862
  await writeFile20(
11638
11863
  composedPath,
11639
11864
  [
@@ -11706,7 +11931,7 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
11706
11931
  const artifactKind = entry.isDirectory() ? "dir" : "file";
11707
11932
  const existing = byKey.get(artifactMapKey);
11708
11933
  const stagedPath = join37(options.stageRoot, ".agentwheel-composed", channel, type, entry.name);
11709
- await mkdir19(dirname25(stagedPath), { recursive: true });
11934
+ await mkdir20(dirname25(stagedPath), { recursive: true });
11710
11935
  await cp4(full, stagedPath, { recursive: artifactKind === "dir", dereference: true });
11711
11936
  byKey.set(artifactMapKey, {
11712
11937
  ...existing,
@@ -11746,12 +11971,12 @@ function installableArtifactTypes() {
11746
11971
  return ["instructions", "rules", "skills", "commands", "subagents", "mcp", "hooks", "settings", "plugins"];
11747
11972
  }
11748
11973
  async function sortedDirEntries2(path) {
11749
- return (await readdir9(path, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
11974
+ return (await readdir10(path, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
11750
11975
  }
11751
11976
 
11752
11977
  // src/staging/claude-subagents.ts
11753
11978
  init_fs();
11754
- import { mkdir as mkdir20, readFile as readFile31, writeFile as writeFile21 } from "fs/promises";
11979
+ import { mkdir as mkdir21, readFile as readFile31, writeFile as writeFile21 } from "fs/promises";
11755
11980
  import { basename as basename18, dirname as dirname26, join as join38 } from "path";
11756
11981
  async function renderClaudeSubagents(artifacts, stageRoot, adapter) {
11757
11982
  if (adapter?.name !== "claude") return artifacts;
@@ -11783,7 +12008,7 @@ async function renderClaudeSubagent(artifact, stageRoot) {
11783
12008
  }
11784
12009
  const content = await readFile31(markdownPath, "utf8");
11785
12010
  const renderedPath = join38(stageRoot, ".agentwheel-rendered", "claude-subagents", `${agentName}.md`);
11786
- await mkdir20(dirname26(renderedPath), { recursive: true });
12011
+ await mkdir21(dirname26(renderedPath), { recursive: true });
11787
12012
  await writeFile21(renderedPath, content.endsWith("\n") ? content : `${content}
11788
12013
  `, "utf8");
11789
12014
  return {
@@ -11825,7 +12050,7 @@ async function stageResolvedArtifactsRaw(resolved, artifacts, parentDir = tmpdir
11825
12050
  await removeOnFailure(root, async () => {
11826
12051
  for (const artifact of artifacts) {
11827
12052
  const stagedPath = join39(root, artifact.relativePath);
11828
- await mkdir21(dirname27(stagedPath), { recursive: true });
12053
+ await mkdir22(dirname27(stagedPath), { recursive: true });
11829
12054
  await cp5(artifact.sourcePath, stagedPath, {
11830
12055
  recursive: artifact.kind === "dir",
11831
12056
  dereference: true,
@@ -11922,7 +12147,7 @@ async function copyAsset(asset, source, dest) {
11922
12147
  const sourceStats = await stat12(source);
11923
12148
  if (sourceStats.isFile()) {
11924
12149
  if (matchesAny(basename19(source), asset.include)) {
11925
- await mkdir21(dest, { recursive: true });
12150
+ await mkdir22(dest, { recursive: true });
11926
12151
  await copyAssetFile(source, join39(dest, basename19(source)), asset);
11927
12152
  }
11928
12153
  return;
@@ -11931,26 +12156,26 @@ async function copyAsset(asset, source, dest) {
11931
12156
  throw new Error(`Asset include source is not a file or directory: ${source}`);
11932
12157
  }
11933
12158
  if (!asset.include?.length) {
11934
- await mkdir21(dirname27(dest), { recursive: true });
12159
+ await mkdir22(dirname27(dest), { recursive: true });
11935
12160
  await cp5(source, dest, { recursive: true, dereference: true });
11936
12161
  if (asset.mode === "copy") await normalizeCopiedModes(dest);
11937
12162
  return;
11938
12163
  }
11939
12164
  for (const file of await listFiles2(source)) {
11940
- const rel = relative12(source, file).replaceAll("\\", "/");
12165
+ const rel = relative13(source, file).replaceAll("\\", "/");
11941
12166
  if (!matchesAny(rel, asset.include) && !matchesAny(basename19(file), asset.include)) continue;
11942
12167
  await copyAssetFile(file, join39(dest, rel), asset);
11943
12168
  }
11944
12169
  }
11945
12170
  async function copyAssetFile(source, dest, asset) {
11946
- await mkdir21(dirname27(dest), { recursive: true });
12171
+ await mkdir22(dirname27(dest), { recursive: true });
11947
12172
  await cp5(source, dest, { dereference: true });
11948
12173
  if (asset.mode === "copy") await chmod3(dest, 420);
11949
12174
  }
11950
12175
  function resolvePackagePath(packageRoot, path) {
11951
12176
  const resolved = resolve25(packageRoot, path);
11952
12177
  const root = resolve25(packageRoot);
11953
- if (resolved !== root && !resolved.startsWith(`${root}${sep7}`)) {
12178
+ if (resolved !== root && !resolved.startsWith(`${root}${sep8}`)) {
11954
12179
  throw new Error(`Asset include escapes package root: ${path}`);
11955
12180
  }
11956
12181
  return resolved;
@@ -11958,7 +12183,7 @@ function resolvePackagePath(packageRoot, path) {
11958
12183
  async function listFiles2(root) {
11959
12184
  const out = [];
11960
12185
  async function walk2(dir) {
11961
- for (const entry of (await readdir10(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
12186
+ for (const entry of (await readdir11(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
11962
12187
  const full = join39(dir, entry.name);
11963
12188
  if (entry.isDirectory()) {
11964
12189
  await walk2(full);
@@ -11977,7 +12202,7 @@ async function normalizeCopiedModes(path) {
11977
12202
  return;
11978
12203
  }
11979
12204
  if (!stats.isDirectory()) return;
11980
- for (const entry of await readdir10(path, { withFileTypes: true })) {
12205
+ for (const entry of await readdir11(path, { withFileTypes: true })) {
11981
12206
  await normalizeCopiedModes(join39(path, entry.name));
11982
12207
  }
11983
12208
  }
@@ -11998,12 +12223,12 @@ init_adapters();
11998
12223
  init_adapter();
11999
12224
  init_artifact();
12000
12225
  init_workspace();
12001
- import { appendFile, cp as cp6, lstat as lstat2, mkdir as mkdir22, readdir as readdir12, rm as rm13 } from "fs/promises";
12002
- import { dirname as dirname29, join as join42, relative as relative13 } from "path";
12226
+ import { appendFile, cp as cp6, lstat as lstat3, mkdir as mkdir23, readdir as readdir13, rm as rm13 } from "fs/promises";
12227
+ import { dirname as dirname29, join as join42, relative as relative14 } from "path";
12003
12228
 
12004
12229
  // src/resolve/graph.ts
12005
12230
  import { createHash as createHash17 } from "crypto";
12006
- import { readdir as readdir11, readFile as readFile34, stat as stat14 } from "fs/promises";
12231
+ import { readdir as readdir12, readFile as readFile34, stat as stat14 } from "fs/promises";
12007
12232
  import { basename as basename20, extname as extname4, join as join41 } from "path";
12008
12233
  init_artifact();
12009
12234
  init_fs();
@@ -13075,7 +13300,7 @@ async function markdownFilesForArtifact2(artifact) {
13075
13300
  async function listMarkdownFiles2(root) {
13076
13301
  const out = [];
13077
13302
  async function walk2(dir) {
13078
- for (const entry of (await readdir11(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
13303
+ for (const entry of (await readdir12(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
13079
13304
  const full = join41(dir, entry.name);
13080
13305
  if (entry.isDirectory()) {
13081
13306
  await walk2(full);
@@ -13257,8 +13482,8 @@ function verifyIntegrity(integrity, sourceHash, label) {
13257
13482
  async function withCachePathLock(path, fn) {
13258
13483
  const previous = cacheLocks.get(path) ?? Promise.resolve();
13259
13484
  let release = () => void 0;
13260
- const current = previous.then(() => new Promise((resolve44) => {
13261
- release = resolve44;
13485
+ const current = previous.then(() => new Promise((resolve45) => {
13486
+ release = resolve45;
13262
13487
  }));
13263
13488
  cacheLocks.set(path, current);
13264
13489
  await previous;
@@ -13339,8 +13564,8 @@ function detectDirectCollisions(nodes) {
13339
13564
  }
13340
13565
  }
13341
13566
  function graphNodeId(name, version, normalizedSource, resolvedCommit, sourceHash) {
13342
- const digest2 = createHash17("sha256").update(normalizedSource).update("\0").update(resolvedCommit ?? sourceHash).digest("hex").slice(0, 12);
13343
- return `${name}@${version}+${digest2}`;
13567
+ const digest3 = createHash17("sha256").update(normalizedSource).update("\0").update(resolvedCommit ?? sourceHash).digest("hex").slice(0, 12);
13568
+ return `${name}@${version}+${digest3}`;
13344
13569
  }
13345
13570
  function sortedUnique4(values) {
13346
13571
  return [...new Set(values)].sort((a, b) => a.localeCompare(b));
@@ -13382,7 +13607,7 @@ init_declarations();
13382
13607
  async function remember(workspaceRoot, runtime, text) {
13383
13608
  const overlayPath = join42(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
13384
13609
  declareMutationPath(overlayPath);
13385
- await mkdir22(dirname29(overlayPath), { recursive: true });
13610
+ await mkdir23(dirname29(overlayPath), { recursive: true });
13386
13611
  await appendFile(overlayPath, `${text.trim()}
13387
13612
  `, "utf8");
13388
13613
  return { overlayPath };
@@ -13410,12 +13635,12 @@ async function ejectArtifact(workspaceRoot, item) {
13410
13635
  for (const path of await listFilesIfPresent(ejectedPath)) declareMutationPath(path);
13411
13636
  if (artifact.kind === "dir") {
13412
13637
  for (const sourceFile of await listFiles3(sourcePath)) {
13413
- declareMutationPath(join42(ejectedPath, relative13(sourcePath, sourceFile)));
13638
+ declareMutationPath(join42(ejectedPath, relative14(sourcePath, sourceFile)));
13414
13639
  }
13415
13640
  } else {
13416
13641
  declareMutationPath(ejectedPath);
13417
13642
  }
13418
- await mkdir22(dirname29(ejectedPath), { recursive: true });
13643
+ await mkdir23(dirname29(ejectedPath), { recursive: true });
13419
13644
  await rm13(ejectedPath, { recursive: true, force: true });
13420
13645
  await cp6(sourcePath, ejectedPath, { recursive: artifact.kind === "dir", dereference: true });
13421
13646
  return {
@@ -13431,11 +13656,11 @@ async function ejectArtifact(workspaceRoot, item) {
13431
13656
  }
13432
13657
  }
13433
13658
  async function listFiles3(root) {
13434
- const stats = await lstat2(root);
13659
+ const stats = await lstat3(root);
13435
13660
  if (stats.isFile()) return [root];
13436
13661
  const files = [];
13437
13662
  async function walk2(dir) {
13438
- for (const entry of await readdir12(dir, { withFileTypes: true })) {
13663
+ for (const entry of await readdir13(dir, { withFileTypes: true })) {
13439
13664
  const path = join42(dir, entry.name);
13440
13665
  if (entry.isDirectory()) await walk2(path);
13441
13666
  else files.push(path);
@@ -13533,7 +13758,7 @@ init_adapter();
13533
13758
  init_adapter();
13534
13759
  init_graph_lock();
13535
13760
  import { createHash as createHash19 } from "crypto";
13536
- import { mkdir as mkdir24, readdir as readdir13 } from "fs/promises";
13761
+ import { mkdir as mkdir25, readdir as readdir14 } from "fs/promises";
13537
13762
  import { basename as basename21, dirname as dirname31, join as join45, posix as posix6, resolve as resolve31 } from "path";
13538
13763
  init_paths();
13539
13764
  init_merge_removal();
@@ -13674,8 +13899,8 @@ function formatNamespace(decision) {
13674
13899
  function formatOverride(decision) {
13675
13900
  return `${decision.graphNodeId}:${decision.type}/${decision.name} replaces ${decision.overriddenGraphNodeId}:${decision.type}/${decision.name} via ${decision.rootId} (${decision.selector})`;
13676
13901
  }
13677
- function short(hash) {
13678
- return hash.slice(0, 12);
13902
+ function short(hash2) {
13903
+ return hash2.slice(0, 12);
13679
13904
  }
13680
13905
  function selectionImportKey(root) {
13681
13906
  const selection = root.selectionImport;
@@ -14215,7 +14440,7 @@ init_fs();
14215
14440
 
14216
14441
  // src/lifecycle/trust.ts
14217
14442
  init_fs();
14218
- import { mkdir as mkdir23, readFile as readFile36 } from "fs/promises";
14443
+ import { mkdir as mkdir24, readFile as readFile36 } from "fs/promises";
14219
14444
  import { homedir as homedir12 } from "os";
14220
14445
  import { dirname as dirname30, join as join44 } from "path";
14221
14446
  import { z as z14 } from "zod";
@@ -14294,7 +14519,7 @@ async function readTrustStore(path) {
14294
14519
  return trustStoreSchema.parse(JSON.parse(await readFile36(path, "utf8")));
14295
14520
  }
14296
14521
  async function writeTrustStore(path, store) {
14297
- await mkdir23(dirname30(path), { recursive: true });
14522
+ await mkdir24(dirname30(path), { recursive: true });
14298
14523
  await writeJsonAtomic(path, trustStoreSchema.parse(store));
14299
14524
  }
14300
14525
  function defaultTrustStorePath() {
@@ -14422,9 +14647,9 @@ async function createExactMcpRetirementPlan(desiredArtifacts, adapter, targetRoo
14422
14647
  init_fs();
14423
14648
  init_declarations();
14424
14649
  init_workspace();
14425
- import { lstat as lstat3, readFile as readFile37, realpath as realpath2 } from "fs/promises";
14650
+ import { lstat as lstat4, readFile as readFile37, realpath as realpath2 } from "fs/promises";
14426
14651
  import { homedir as homedir13 } from "os";
14427
- import { isAbsolute as isAbsolute10, relative as relative14, resolve as resolve29 } from "path";
14652
+ import { isAbsolute as isAbsolute10, relative as relative15, resolve as resolve29 } from "path";
14428
14653
  async function resolveWorkspaceScope(request = {}) {
14429
14654
  const selected = [request.user === true, request.local === true, request.fleet !== void 0].filter(Boolean).length;
14430
14655
  if (selected > 1) {
@@ -14562,7 +14787,7 @@ function assertFleetContract(id, registration, config) {
14562
14787
  async function assertCanonicalDirectory(input, label) {
14563
14788
  const canonical = await canonicalizeDirectory(input, label);
14564
14789
  const normalized = resolve29(input);
14565
- const stats = await lstat3(input);
14790
+ const stats = await lstat4(input);
14566
14791
  if (stats.isSymbolicLink() || canonical !== normalized || input !== normalized) {
14567
14792
  throw new Error(`${label} must be canonical and symlink-unambiguous: ${input} resolves to ${canonical}.`);
14568
14793
  }
@@ -14576,7 +14801,7 @@ async function canonicalizeDirectory(input, label) {
14576
14801
  } catch {
14577
14802
  throw new Error(`${label} does not exist: ${input}`);
14578
14803
  }
14579
- const stats = await lstat3(canonical);
14804
+ const stats = await lstat4(canonical);
14580
14805
  if (!stats.isDirectory()) throw new Error(`${label} is not a directory: ${input}`);
14581
14806
  return canonical;
14582
14807
  }
@@ -14596,7 +14821,7 @@ function sortedUnique6(values) {
14596
14821
  return [...new Set(values.map((value) => value.trim()).filter(Boolean))].sort((a, b) => a.localeCompare(b));
14597
14822
  }
14598
14823
  function containsPath(parent, candidate) {
14599
- const path = relative14(parent, candidate);
14824
+ const path = relative15(parent, candidate);
14600
14825
  return path === "" || !path.startsWith("..") && !isAbsolute10(path);
14601
14826
  }
14602
14827
 
@@ -15117,7 +15342,7 @@ async function discoverLegacyStateCandidates(options) {
15117
15342
  const directory = dirname31(options.graphLockPath);
15118
15343
  let names;
15119
15344
  try {
15120
- names = await readdir13(directory);
15345
+ names = await readdir14(directory);
15121
15346
  } catch (error) {
15122
15347
  if (error.code === "ENOENT") return [];
15123
15348
  throw error;
@@ -15553,7 +15778,7 @@ import { basename as basename22, dirname as dirname32, join as join47, resolve a
15553
15778
  // src/transport/run-as-identity.ts
15554
15779
  import { execFileSync } from "child_process";
15555
15780
  import { lstatSync, realpathSync as realpathSync2 } from "fs";
15556
- import { isAbsolute as isAbsolute11, join as join46, parse as parse5, resolve as resolve32, sep as sep8 } from "path";
15781
+ import { isAbsolute as isAbsolute11, join as join46, parse as parse5, resolve as resolve32, sep as sep9 } from "path";
15557
15782
  function resolveRunAsIdentity(user, root, getent = (name) => execFileSync("/usr/bin/getent", ["passwd", name], { encoding: "utf8" })) {
15558
15783
  if (!/^[a-z_][a-z0-9_-]*[$]?$/i.test(user) || user === "root") {
15559
15784
  throw new Error(`Invalid local run-as account '${user}'.`);
@@ -15575,19 +15800,19 @@ function resolveRunAsIdentity(user, root, getent = (name) => execFileSync("/usr/
15575
15800
  if (!Number.isSafeInteger(uid) || uid <= 0 || !Number.isSafeInteger(gid) || gid < 0 || !isAbsolute11(home) || resolve32(home) !== home) {
15576
15801
  throw new Error(`Invalid UID, GID or home for local run-as account '${user}'.`);
15577
15802
  }
15578
- assertNoSymlinkPath(home);
15803
+ assertNoSymlinkPath2(home);
15579
15804
  if (realpathSync2(home) !== home || !lstatSync(home).isDirectory()) {
15580
15805
  throw new Error(`Local run-as home ${home} must be a real directory.`);
15581
15806
  }
15582
- assertNoSymlinkPath(root);
15807
+ assertNoSymlinkPath2(root);
15583
15808
  if (realpathSync2(root) !== root || !lstatSync(root).isDirectory() || lstatSync(root).uid !== uid) {
15584
15809
  throw new Error(`Local run-as root ${root} must be a real directory owned by UID ${uid}.`);
15585
15810
  }
15586
15811
  return { user, uid, gid, home, root };
15587
15812
  }
15588
- function assertNoSymlinkPath(path) {
15813
+ function assertNoSymlinkPath2(path) {
15589
15814
  let current = parse5(path).root;
15590
- for (const part of path.slice(current.length).split(sep8).filter(Boolean)) {
15815
+ for (const part of path.slice(current.length).split(sep9).filter(Boolean)) {
15591
15816
  current = join46(current, part);
15592
15817
  if (lstatSync(current).isSymbolicLink()) throw new Error(`Local run-as root contains a symlink: ${current}`);
15593
15818
  }
@@ -16094,7 +16319,7 @@ function shellQuoteArg(value) {
16094
16319
  }
16095
16320
 
16096
16321
  // src/cli/update-check.ts
16097
- import { mkdir as mkdir25, readFile as readFile38, writeFile as writeFile22 } from "fs/promises";
16322
+ import { mkdir as mkdir26, readFile as readFile38, writeFile as writeFile22 } from "fs/promises";
16098
16323
  import { homedir as homedir14 } from "os";
16099
16324
  import { dirname as dirname33, join as join48 } from "path";
16100
16325
  var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -16149,7 +16374,7 @@ async function readCache(path) {
16149
16374
  }
16150
16375
  }
16151
16376
  async function writeCache(path, cache) {
16152
- await mkdir25(dirname33(path), { recursive: true });
16377
+ await mkdir26(dirname33(path), { recursive: true });
16153
16378
  await writeFile22(path, `${JSON.stringify(cache, null, 2)}
16154
16379
  `, "utf8");
16155
16380
  }
@@ -16872,14 +17097,222 @@ function canonicalJson6(value) {
16872
17097
  return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson6(record[key])}`).join(",")}}`;
16873
17098
  }
16874
17099
 
17100
+ // src/lifecycle/ownership-release.ts
17101
+ init_apply();
17102
+ init_manifest2();
17103
+ init_paths();
17104
+ init_transaction();
17105
+ import { createHash as createHash21, randomUUID as randomUUID6 } from "crypto";
17106
+ import { lstat as lstat5 } from "fs/promises";
17107
+ import { join as join52, resolve as resolve38 } from "path";
17108
+ init_coordinator();
17109
+ init_declarations();
17110
+ init_protocol();
17111
+ init_repository();
17112
+ init_process();
17113
+ init_transport();
17114
+ async function planReleaseOwnership(request) {
17115
+ return observe2(request);
17116
+ }
17117
+ async function applyReleaseOwnership(request) {
17118
+ for (const [name, value] of Object.entries({
17119
+ planDigest: request.planDigest,
17120
+ expectedSourceRevision: request.expectedSourceRevision,
17121
+ expectedInventoryRevision: request.expectedInventoryRevision
17122
+ })) {
17123
+ if (!value || !/^[a-f0-9]{64}$/.test(value)) throw new Error(`Reviewed SHA-256 ${name} is required to release a claim.`);
17124
+ }
17125
+ const workspaceRoot = resolve38(request.workspaceRoot);
17126
+ const existing = activeMutationMetadata();
17127
+ if (existing && (resolve38(existing.workspaceRoot) !== workspaceRoot || existing.reason !== request.reason.replace(/\r\n?/gu, "\n").trim() || request.operationId && request.operationId !== existing.operationId)) {
17128
+ throw new Error("Ownership release does not match the active governed workspace, reason or operation.");
17129
+ }
17130
+ const operationId = mutationOperationIdSchema.parse(existing?.operationId ?? request.operationId ?? randomUUID6());
17131
+ const auditPath = join52(workspaceRoot, ".agentwheel", "ownership-releases", `${operationId}.json`);
17132
+ const mutation = existing ? void 0 : await GovernedMutation.begin({
17133
+ workspaceRoot,
17134
+ commandName: "agentwheel ownership release-claim",
17135
+ reason: request.reason,
17136
+ operationId,
17137
+ noCommit: request.noCommit,
17138
+ globalRoot: request.globalRoot,
17139
+ anticipatedPaths: [auditPath]
17140
+ });
17141
+ try {
17142
+ if ((existing ?? mutation?.metadata())?.revisionMode === "commit-after-verify") {
17143
+ const repository = await discoverGitRepository(workspaceRoot);
17144
+ if (!repository) throw new Error("Ownership release requires a declarative Git audit path.");
17145
+ const ignored = await runProcess("git", ["-C", repository.root, "check-ignore", "--no-index", "--", auditPath], { allowExitCodes: [0, 1] });
17146
+ if (ignored.exitCode === 0) {
17147
+ throw new Error("Ownership release audit path is Git-ignored; explicitly declare it in repository policy before releasing a claim.");
17148
+ }
17149
+ }
17150
+ const result = await applyLocked(request, operationId, auditPath);
17151
+ await mutation?.complete();
17152
+ return result;
17153
+ } catch (error) {
17154
+ await mutation?.fail(error);
17155
+ throw error;
17156
+ }
17157
+ }
17158
+ async function applyLocked(request, operationId, auditPath) {
17159
+ const transport = request.transport ?? localTransport;
17160
+ if (transport.kind !== "local") throw new Error("Ownership release supports local targets only.");
17161
+ await assertNoSymlinkPath(join52(resolve38(request.targetRoot), ".agentwheel"));
17162
+ await assertNoSymlinkPath(auditPath);
17163
+ const lock = await acquireApplyLock(resolve38(request.targetRoot), request.adapter, transport, {}, {
17164
+ installationType: request.installationType,
17165
+ stateKey: request.stateKey
17166
+ });
17167
+ try {
17168
+ if ((await listAllApplyJournals(request.targetRoot, void 0, transport)).length) {
17169
+ throw new Error("Ownership release refuses pending runtime journals; recover them first.");
17170
+ }
17171
+ const plan = await observe2(request);
17172
+ if (plan.planDigest !== request.planDigest || plan.source.revision !== request.expectedSourceRevision || plan.manifestInventoryRevision !== request.expectedInventoryRevision) {
17173
+ throw new Error("Stale ownership release plan, manifest or inventory; replan required.");
17174
+ }
17175
+ if (await transport.pathExists(auditPath)) throw new Error(`Ownership release audit already exists: ${auditPath}`);
17176
+ declareMutationPath(auditPath);
17177
+ declareMutationPath(plan.source.manifestPath);
17178
+ const manifest = await readInstallManifest(plan.targetRoot, plan.adapter, transport, {
17179
+ installationType: plan.installationType,
17180
+ stateKey: plan.source.stateKey
17181
+ });
17182
+ if (!manifest || manifest.version !== 2 || manifest.revision !== plan.source.revision) {
17183
+ throw new Error("Source manifest changed after selection; replan required.");
17184
+ }
17185
+ const now = (/* @__PURE__ */ new Date()).toISOString();
17186
+ const content = `${JSON.stringify({
17187
+ schemaVersion: 1,
17188
+ event: "ownership-release-intent",
17189
+ operationId,
17190
+ reason: plan.reason,
17191
+ reviewedPlanDigest: plan.planDigest,
17192
+ plan,
17193
+ // This immutable dossier records intent. The linked journal verifies completion separately.
17194
+ completion: "Verify install state and the governed mutation receipt; intent alone does not prove completion."
17195
+ }, null, 2)}
17196
+ `;
17197
+ const metadata = mutationMetadataForApplyJournal();
17198
+ const journal = {
17199
+ version: metadata ? 2 : 1,
17200
+ ...metadata ? { mutation: metadata } : {},
17201
+ mode: "uninstall",
17202
+ adapter: plan.adapter,
17203
+ installationType: plan.installationType,
17204
+ stateKey: plan.source.stateKey,
17205
+ targetRoot: plan.targetRoot,
17206
+ baseRevision: manifest.revision,
17207
+ createdAt: now,
17208
+ updatedAt: now,
17209
+ operations: [],
17210
+ completed: [],
17211
+ manifest: { ...manifest, entries: manifest.entries.filter((entry) => digest2(entry) !== plan.source.entryDigest) },
17212
+ metadataAudit: {
17213
+ kind: "ownership-release",
17214
+ workspaceRoot: plan.workspaceRoot,
17215
+ operationId,
17216
+ planDigest: plan.planDigest,
17217
+ inventory: plan.inventory,
17218
+ runtime: [{ path: plan.path, hash: plan.runtimeHash, snapshotDigest: plan.runtimeSnapshotDigest }],
17219
+ auditFiles: [{ path: `.agentwheel/ownership-releases/${operationId}.json`, content, sha256: hash(content) }]
17220
+ }
17221
+ };
17222
+ await writeApplyJournal(journal, transport);
17223
+ await commitManifestMetadataJournal(journal, transport);
17224
+ return { ...plan, applied: true, operationId, auditPath, retainedEntries: journal.manifest.entries.length };
17225
+ } finally {
17226
+ await lock.release();
17227
+ }
17228
+ }
17229
+ async function observe2(request) {
17230
+ const transport = request.transport ?? localTransport;
17231
+ if (transport.kind !== "local") throw new Error("Ownership release supports local targets only.");
17232
+ const targetRoot = resolve38(request.targetRoot);
17233
+ const workspaceRoot = resolve38(request.workspaceRoot);
17234
+ const reason = mutationReasonSchema.parse(request.reason.trim());
17235
+ if (!request.stateKey || stateKeyFor(request.adapter, { stateKey: request.stateKey }) !== request.stateKey || !request.installationType.trim() || !request.selector.includes("/")) {
17236
+ throw new Error("Ownership release requires an exact state key, installation type and type/name selector.");
17237
+ }
17238
+ const runtimePath = metadataRuntimePath(targetRoot, request.path);
17239
+ await assertNoSymlinkPath(workspaceRoot);
17240
+ await assertNoSymlinkPath(join52(targetRoot, ".agentwheel"));
17241
+ const manifests = await listInstallManifests(targetRoot, void 0, transport);
17242
+ for (const item of manifests) await assertNoSymlinkPath(item.path);
17243
+ const source = manifests.find((item) => item.stateKey === request.stateKey);
17244
+ const manifest = source?.manifest;
17245
+ if (!manifest || manifest.version !== 2 || manifest.adapter !== request.adapter || manifest.targetRoot !== targetRoot || manifest.installationType !== request.installationType || stateKeyFor(manifest.adapter, { stateKey: manifest.stateKey, installationType: manifest.installationType }) !== request.stateKey) {
17246
+ throw new Error("Source manifest does not prove the requested target, adapter, installation type and state key.");
17247
+ }
17248
+ const matches = manifest.entries.filter((entry2) => entry2.path === request.path && `${entry2.artifactType}/${entry2.artifactName}` === request.selector);
17249
+ if (matches.length !== 1) throw new Error(`Expected exactly one ownership claim at ${request.path} for ${request.selector}.`);
17250
+ const entry = matches[0];
17251
+ const owner = workspaceOwnerForRoot(request.fromWorkspaceRoot, request.fromFleetId);
17252
+ if (entry.workspaceOwner !== owner) throw new Error(`Workspace owner does not match the selected claim at ${entry.path}.`);
17253
+ if (entry.mergeStrategy || entry.mode || entry.semanticPlugin || entry.semanticCommand || entry.executed || entry.channel === "ejected") {
17254
+ throw new Error("Ownership release only supports plain file/directory claims; shared or semantic contributions are protected.");
17255
+ }
17256
+ for (const item of manifests) {
17257
+ for (const other of item.manifest.entries) {
17258
+ if (item === source && other === entry) continue;
17259
+ const otherPath = metadataRuntimePath(targetRoot, other.path);
17260
+ if (otherPath === runtimePath || otherPath.startsWith(`${runtimePath}/`) || runtimePath.startsWith(`${otherPath}/`)) {
17261
+ throw new Error(`Ambiguous or overlapping ownership claim at ${entry.path} in ${item.stateKey}.`);
17262
+ }
17263
+ }
17264
+ }
17265
+ const snapshotDigest = await ownershipRuntimeSnapshot(runtimePath);
17266
+ const runtimeKind = (await lstat5(runtimePath)).isDirectory() ? "dir" : "file";
17267
+ if (runtimeKind !== entry.kind) throw new Error("Selected runtime kind does not match the manifest claim.");
17268
+ const runtimeHash = await transport.hashPath(runtimePath);
17269
+ const inventory = manifests.map((item) => ({ stateKey: item.stateKey, revision: item.manifest.revision }));
17270
+ const plan = {
17271
+ adapter: request.adapter,
17272
+ installationType: request.installationType,
17273
+ targetRoot,
17274
+ workspaceRoot,
17275
+ owner,
17276
+ selector: request.selector,
17277
+ path: entry.path,
17278
+ source: {
17279
+ stateKey: request.stateKey,
17280
+ manifestPath: installManifestPath(targetRoot, request.adapter, { installationType: request.installationType, stateKey: request.stateKey }),
17281
+ revision: manifest.revision,
17282
+ entryDigest: digest2(entry),
17283
+ entry
17284
+ },
17285
+ recordedHash: entry.hash,
17286
+ runtimeHash,
17287
+ runtimeSnapshotDigest: snapshotDigest,
17288
+ manifestInventoryRevision: await computeInstallManifestInventoryRevision(targetRoot, void 0, transport),
17289
+ inventory,
17290
+ reason
17291
+ };
17292
+ return { ...plan, planDigest: digest2(plan) };
17293
+ }
17294
+ function hash(content) {
17295
+ return createHash21("sha256").update(content).digest("hex");
17296
+ }
17297
+ function digest2(value) {
17298
+ return hash(canonicalJson7(value));
17299
+ }
17300
+ function canonicalJson7(value) {
17301
+ if (Array.isArray(value)) return `[${value.map(canonicalJson7).join(",")}]`;
17302
+ if (!value || typeof value !== "object") return JSON.stringify(value);
17303
+ const record = value;
17304
+ return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson7(record[key])}`).join(",")}}`;
17305
+ }
17306
+
16875
17307
  // src/lifecycle/ownership-adopt-legacy.ts
16876
17308
  init_apply();
16877
17309
  init_manifest2();
16878
17310
  init_paths();
16879
17311
  init_transaction();
16880
- import { createHash as createHash22 } from "crypto";
17312
+ init_instructions_block();
17313
+ import { createHash as createHash23 } from "crypto";
16881
17314
  import { realpath as realpath3 } from "fs/promises";
16882
- import { isAbsolute as isAbsolute12, relative as relative16, resolve as resolve39 } from "path";
17315
+ import { isAbsolute as isAbsolute12, join as join54, relative as relative17, resolve as resolve40 } from "path";
16883
17316
  init_manifest();
16884
17317
  init_declarations();
16885
17318
  init_transport();
@@ -16892,18 +17325,18 @@ init_instructions_block();
16892
17325
  init_merge_removal();
16893
17326
  init_graph_lock();
16894
17327
  init_manifest();
16895
- import { createHash as createHash21 } from "crypto";
16896
- import { lstat as lstat4, readdir as readdir14 } from "fs/promises";
16897
- import { basename as basename23, dirname as dirname35, join as join52, posix as posix7, relative as relative15, resolve as resolve38 } from "path";
17328
+ import { createHash as createHash22 } from "crypto";
17329
+ import { lstat as lstat6, readdir as readdir15 } from "fs/promises";
17330
+ import { basename as basename23, dirname as dirname35, join as join53, posix as posix7, relative as relative16, resolve as resolve39 } from "path";
16898
17331
  async function inventoryHistoricalLocks(fleetRoot) {
16899
- const root = join52(fleetRoot, ".agentwheel", "locks");
17332
+ const root = join53(fleetRoot, ".agentwheel", "locks");
16900
17333
  const found = [];
16901
17334
  async function visit(dir) {
16902
- for (const entry of await readdir14(dir, { withFileTypes: true }).catch((error) => {
17335
+ for (const entry of await readdir15(dir, { withFileTypes: true }).catch((error) => {
16903
17336
  if (error.code === "ENOENT") return [];
16904
17337
  throw error;
16905
17338
  })) {
16906
- const path = join52(dir, entry.name);
17339
+ const path = join53(dir, entry.name);
16907
17340
  if (entry.isDirectory()) await visit(path);
16908
17341
  else if (entry.isFile() && entry.name.endsWith(".graph-lock.json")) found.push(await historicalLock(path));
16909
17342
  }
@@ -16912,15 +17345,15 @@ async function inventoryHistoricalLocks(fleetRoot) {
16912
17345
  return found.sort((a, b) => a.path.localeCompare(b.path));
16913
17346
  }
16914
17347
  async function findLegacyNamedLocks(workspaceRoot, adapter, fingerprint) {
16915
- const root = join52(workspaceRoot, ".agentwheel", "locks");
17348
+ const root = join53(workspaceRoot, ".agentwheel", "locks");
16916
17349
  const found = [];
16917
- for (const target of await readdir14(root, { withFileTypes: true }).catch((error) => {
17350
+ for (const target of await readdir15(root, { withFileTypes: true }).catch((error) => {
16918
17351
  if (error.code === "ENOENT") return [];
16919
17352
  throw error;
16920
17353
  })) {
16921
17354
  if (!target.isDirectory()) continue;
16922
- const path = join52(root, target.name, adapter, `${fingerprint}.graph-lock.json`);
16923
- const stats = await lstat4(path).catch((error) => {
17355
+ const path = join53(root, target.name, adapter, `${fingerprint}.graph-lock.json`);
17356
+ const stats = await lstat6(path).catch((error) => {
16924
17357
  if (error.code === "ENOENT") return void 0;
16925
17358
  throw error;
16926
17359
  });
@@ -16959,7 +17392,7 @@ async function planLegacyRecovery(input) {
16959
17392
  const nodeHashes = new Map(graphPlan.bundle.graphLock.canonical.nodes.map((node) => [node.id, node.sourceHash]));
16960
17393
  for (const op of graphPlan.plan.operations) {
16961
17394
  if (!op.desiredHash || op.action === "remove" || op.action === "keep") continue;
16962
- const path = relative15(installRoot, op.destPath);
17395
+ const path = relative16(installRoot, op.destPath);
16963
17396
  if (path.startsWith("..") || path === "") throw new Error(`Planner destination escapes target: ${op.destPath}`);
16964
17397
  paths.add(path);
16965
17398
  const items = desired.get(path) ?? [];
@@ -16980,8 +17413,8 @@ async function planLegacyRecovery(input) {
16980
17413
  const currentNodeIds = [...new Set(current.map((item) => item.graphNodeId).filter((value) => Boolean(value)))].sort();
16981
17414
  const currentSelectors = [...new Set(current.map((item) => item.logicalSelector).filter((value) => Boolean(value)))].sort();
16982
17415
  const currentOwners = [...new Set(current.flatMap((item) => item.owners ?? []))].sort();
16983
- const livePath = resolve38(installRoot, path);
16984
- if (relative15(installRoot, livePath).startsWith("..")) throw new Error(`Manifest path escapes target: ${path}`);
17416
+ const livePath = resolve39(installRoot, path);
17417
+ if (relative16(installRoot, livePath).startsWith("..")) throw new Error(`Manifest path escapes target: ${path}`);
16985
17418
  const liveHash = await transport.pathExists(livePath) ? await transport.hashPath(livePath) : null;
16986
17419
  const reasons = [];
16987
17420
  const currentResults = await Promise.all(current.map((op) => verifyCurrentOperation(op, liveHash, transport)));
@@ -17046,14 +17479,14 @@ async function planLegacyRecovery(input) {
17046
17479
  };
17047
17480
  }
17048
17481
  function claimFor(item, entry, locks, binding) {
17049
- const digest2 = "graphLockDigest" in entry ? entry.graphLockDigest : void 0;
17482
+ const digest3 = "graphLockDigest" in entry ? entry.graphLockDigest : void 0;
17050
17483
  const nodeId = "graphNodeId" in entry ? entry.graphNodeId : void 0;
17051
17484
  const selector = "logicalSelector" in entry ? entry.logicalSelector : void 0;
17052
- const matches = locks.filter((candidate) => candidate.digest === digest2);
17485
+ const matches = locks.filter((candidate) => candidate.digest === digest3);
17053
17486
  const evidence = [];
17054
17487
  const owner = "workspaceOwner" in entry ? entry.workspaceOwner : legacyUnownedWorkspaceOwner;
17055
- const sameRoot = binding.transportKind === "ssh" ? posix7.normalize(item.manifest.targetRoot) === posix7.normalize(binding.installRoot) : resolve38(item.manifest.targetRoot) === resolve38(binding.installRoot);
17056
- const inTargetDir = matches.filter((candidate) => resolve38(dirname35(candidate.path)) === resolve38(binding.targetLockDir));
17488
+ const sameRoot = binding.transportKind === "ssh" ? posix7.normalize(item.manifest.targetRoot) === posix7.normalize(binding.installRoot) : resolve39(item.manifest.targetRoot) === resolve39(binding.installRoot);
17489
+ const inTargetDir = matches.filter((candidate) => resolve39(dirname35(candidate.path)) === resolve39(binding.targetLockDir));
17057
17490
  const boundLocks = inTargetDir.filter((candidate) => lockBindsState(candidate, item, binding));
17058
17491
  if (owner !== binding.expectedOwner) evidence.push("workspace owner differs from selected Fleet target");
17059
17492
  if (item.manifest.version !== 2 || item.manifest.installationType !== binding.installationType) evidence.push("installation type differs or manifest is legacy v1");
@@ -17061,7 +17494,7 @@ function claimFor(item, entry, locks, binding) {
17061
17494
  if (item.manifest.version === 2 && (item.manifest.stateKey !== item.stateKey || item.manifest.adapter !== binding.adapter)) {
17062
17495
  evidence.push("manifest state key or adapter differs from filename");
17063
17496
  }
17064
- if (!digest2) evidence.push("historical graph-lock digest missing");
17497
+ if (!digest3) evidence.push("historical graph-lock digest missing");
17065
17498
  else if (matches.length === 0) evidence.push("historical graph-lock digest has no matching lock");
17066
17499
  if (matches.length && !inTargetDir.length) evidence.push("claim belongs to another Fleet target graph");
17067
17500
  if (inTargetDir.length && !boundLocks.length) evidence.push("graph-lock fingerprint, filename, or state key does not bind claim");
@@ -17082,7 +17515,7 @@ function claimFor(item, entry, locks, binding) {
17082
17515
  owner,
17083
17516
  hash: entry.hash,
17084
17517
  sourceHash: entry.sourceHash,
17085
- graphLockDigest: digest2,
17518
+ graphLockDigest: digest3,
17086
17519
  graphNodeId: nodeId,
17087
17520
  logicalSelector: selector,
17088
17521
  owners: "owners" in entry ? entry.owners : [entry.packageName ?? "legacy"],
@@ -17095,7 +17528,7 @@ function lockBindsState(candidate, manifest, binding) {
17095
17528
  if (!name.endsWith(".graph-lock.json")) return false;
17096
17529
  const fingerprint = name.slice(0, -".graph-lock.json".length);
17097
17530
  if (!/^[a-f0-9]{64}$/u.test(fingerprint)) return false;
17098
- const stable = resolve38(candidate.path) === resolve38(binding.stableLockPath);
17531
+ const stable = resolve39(candidate.path) === resolve39(binding.stableLockPath);
17099
17532
  if (stable) {
17100
17533
  return manifest.stateKey === binding.stableStateKey && candidate.lock.canonical.targetFingerprint === binding.currentFingerprint;
17101
17534
  }
@@ -17163,7 +17596,7 @@ function assertCompleteGraphPlan(plan) {
17163
17596
  }
17164
17597
  }
17165
17598
  function sha2566(value) {
17166
- return createHash21("sha256").update(value).digest("hex");
17599
+ return createHash22("sha256").update(value).digest("hex");
17167
17600
  }
17168
17601
 
17169
17602
  // src/lifecycle/ownership-adopt-legacy.ts
@@ -17174,24 +17607,31 @@ function desiredCoverageFromPlan(plan) {
17174
17607
  artifactType: operation.artifactType,
17175
17608
  artifactName: operation.artifactName,
17176
17609
  kind: operation.kind,
17610
+ ...operation.mode ? { mode: operation.mode } : {},
17611
+ ...operation.mode && operation.logicalSelector ? { logicalSelector: operation.logicalSelector } : {},
17177
17612
  ...operation.packageName ? { packageName: operation.packageName } : {}
17178
17613
  })).sort((left, right) => left.path.localeCompare(right.path));
17179
17614
  }
17180
17615
  async function planAdoptLegacyOwnership(request) {
17181
- return observe2(request, request.transport ?? localTransport);
17616
+ return observe3(request, request.transport ?? localTransport);
17182
17617
  }
17183
17618
  async function applyAdoptLegacyOwnership(request) {
17184
17619
  assertApplyPreconditions2(request);
17185
17620
  const transport = request.transport ?? localTransport;
17186
- const targetRoot = resolve39(request.targetRoot);
17621
+ const targetRoot = resolve40(request.targetRoot);
17187
17622
  const installationType = request.installationType.trim();
17623
+ if (transport.kind !== "local") throw new Error("Legacy ownership adoption requires a local filesystem transport.");
17624
+ const beforeLock = await readInstallManifest(targetRoot, request.adapter, transport, { installationType, stateKey: request.sourceStateKey });
17625
+ if (beforeLock?.entries.some((entry) => entry.mode === "managed-block")) {
17626
+ await assertNoSymlinkPath(join54(targetRoot, ".agentwheel"));
17627
+ }
17188
17628
  const lock = await acquireApplyLock(targetRoot, request.adapter, transport, {}, {
17189
17629
  installationType,
17190
17630
  stateKey: request.destinationStateKey
17191
17631
  });
17192
17632
  try {
17193
17633
  await assertNoPendingJournals(targetRoot, request.adapter, transport);
17194
- const current = await observe2(request, transport);
17634
+ const current = await observe3(request, transport);
17195
17635
  assertExpected(request.planDigest, current.planDigest, "plan digest");
17196
17636
  assertExpected(request.expectedSourceRevision, current.source.revision, "source manifest revision");
17197
17637
  assertExpected(request.expectedDestinationRevision, current.destination.revision ?? absentRevision, "destination manifest revision");
@@ -17211,6 +17651,7 @@ async function applyAdoptLegacyOwnership(request) {
17211
17651
  throw new Error("Source manifest selection changed while locked; replan required.");
17212
17652
  }
17213
17653
  const now = (/* @__PURE__ */ new Date()).toISOString();
17654
+ let guards = current.metadataGuards;
17214
17655
  if (adopted.length > 0) {
17215
17656
  declareMutationPath(current.destination.manifestPath);
17216
17657
  const base = destination ?? {
@@ -17224,13 +17665,22 @@ async function applyAdoptLegacyOwnership(request) {
17224
17665
  legacy: false,
17225
17666
  entries: []
17226
17667
  };
17227
- await commitMetadata({
17668
+ const next = withManifestRevision({
17228
17669
  ...base,
17670
+ generatedAt: now,
17229
17671
  entries: [...base.entries, ...adopted].sort((left, right) => left.path.localeCompare(right.path))
17230
- }, destination?.revision ?? null, now, transport);
17672
+ });
17673
+ await commitMetadata(next, destination?.revision ?? null, now, transport, guards);
17674
+ if (guards) guards = {
17675
+ ...guards,
17676
+ inventory: [
17677
+ ...guards.inventory.filter((item) => item.stateKey !== current.destination.stateKey),
17678
+ { stateKey: current.destination.stateKey, revision: next.revision }
17679
+ ].sort((left, right) => left.stateKey.localeCompare(right.stateKey))
17680
+ };
17231
17681
  }
17232
17682
  declareMutationPath(current.source.manifestPath);
17233
- await commitMetadata({ ...source, entries: retained }, source.revision, now, transport);
17683
+ await commitMetadata({ ...source, entries: retained }, source.revision, now, transport, guards);
17234
17684
  return {
17235
17685
  ...current,
17236
17686
  applied: true,
@@ -17243,7 +17693,7 @@ async function applyAdoptLegacyOwnership(request) {
17243
17693
  await lock.release();
17244
17694
  }
17245
17695
  }
17246
- async function commitMetadata(manifest, baseRevision, now, transport) {
17696
+ async function commitMetadata(manifest, baseRevision, now, transport, metadataGuards) {
17247
17697
  const mutation = mutationMetadataForApplyJournal();
17248
17698
  const journal = {
17249
17699
  version: mutation ? 2 : 1,
@@ -17258,12 +17708,13 @@ async function commitMetadata(manifest, baseRevision, now, transport) {
17258
17708
  updatedAt: now,
17259
17709
  operations: [],
17260
17710
  completed: [],
17261
- manifest
17711
+ manifest,
17712
+ ...metadataGuards ? { metadataGuards } : {}
17262
17713
  };
17263
17714
  await writeApplyJournal(journal, transport);
17264
17715
  await commitManifestMetadataJournal(journal, transport);
17265
17716
  }
17266
- async function observe2(request, transport) {
17717
+ async function observe3(request, transport) {
17267
17718
  if (transport.kind === "ssh") {
17268
17719
  throw new Error("Legacy ownership adoption does not support SSH targets; legacy SSH state does not prove its endpoint.");
17269
17720
  }
@@ -17294,11 +17745,21 @@ async function observe2(request, transport) {
17294
17745
  desiredByPath
17295
17746
  );
17296
17747
  const selectedPaths = new Set(selectedEntries.map((entry) => entry.path));
17748
+ const hasManagedBlock = selectedEntries.some((entry) => entry.mode === "managed-block");
17749
+ if (hasManagedBlock && request.carryDrift) throw new Error("--carry-drift is forbidden for managed instruction block adoption.");
17297
17750
  const selected = [];
17298
17751
  for (const entry of selectedEntries) {
17299
17752
  const runtimePath = containedArtifactPath(targetRoot, entry.path);
17753
+ const managedBlock = entry.mode === "managed-block" ? exactManagedInstructionBlockSnapshot(
17754
+ await transport.readFile(runtimePath),
17755
+ managedInstructionSelector(entry.logicalSelector, entry.artifactType, entry.artifactName)
17756
+ ) : void 0;
17757
+ if (managedBlock && managedBlock.hash !== entry.hash) {
17758
+ throw new Error(`Managed instruction block hash differs from its recorded manifest hash at ${entry.path}; adoption is refused.`);
17759
+ }
17760
+ const runtimeSnapshotDigest = hasManagedBlock ? await ownershipRuntimeSnapshot(runtimePath) : void 0;
17300
17761
  const runtimeHash = await transport.pathExists(runtimePath) ? await transport.hashPath(runtimePath) : null;
17301
- const drift = runtimeHash !== entry.hash;
17762
+ const drift = managedBlock ? false : runtimeHash !== entry.hash;
17302
17763
  if (drift && request.carryDrift !== true) {
17303
17764
  throw new Error(
17304
17765
  runtimeHash === null ? `Managed artifact is missing at ${entry.path}; pass --carry-drift to keep the recorded hash.` : `Managed artifact is drifted at ${entry.path}: manifest ${entry.hash}, current ${runtimeHash}; pass --carry-drift to keep the recorded hash.`
@@ -17321,9 +17782,28 @@ async function observe2(request, transport) {
17321
17782
  ...destinationEntryDigest ? { destinationEntryDigest } : {},
17322
17783
  recordedHash: entry.hash,
17323
17784
  runtimeHash,
17324
- drift
17785
+ drift,
17786
+ ...runtimeSnapshotDigest ? { runtimeSnapshotDigest } : {},
17787
+ ...managedBlock ? { managedBlock } : {}
17325
17788
  });
17326
17789
  }
17790
+ const guardedInventory = hasManagedBlock ? await listInstallManifests(targetRoot, void 0, transport) : void 0;
17791
+ if (guardedInventory) {
17792
+ for (const item of guardedInventory) {
17793
+ await assertNoSymlinkPath(item.path);
17794
+ for (const other of item.manifest.entries) {
17795
+ const otherPath = containedArtifactPath(targetRoot, other.path);
17796
+ for (const entry of selectedEntries) {
17797
+ const path = containedArtifactPath(targetRoot, entry.path);
17798
+ const overlap = otherPath === path || otherPath.startsWith(`${path}/`) || path.startsWith(`${otherPath}/`);
17799
+ if (!overlap) continue;
17800
+ if (item.stateKey === input.sourceStateKey && otherPath === path && "workspaceOwner" in other && entryDigest(other) === entryDigest(entry)) continue;
17801
+ if (item.stateKey === input.destinationStateKey && otherPath === path && "workspaceOwner" in other && coversSourceEntry(other, entry, input.destinationOwner)) continue;
17802
+ throw new Error(`Overlapping or duplicate ownership claim at ${entry.path} in ${item.stateKey}; managed-block adoption is refused.`);
17803
+ }
17804
+ }
17805
+ }
17806
+ }
17327
17807
  const remainingDuplicates = [];
17328
17808
  const selectedByPath = new Map(selectedEntries.map((entry) => [entry.path, entry]));
17329
17809
  for (const item of await listInstallManifests(targetRoot, adapter, transport)) {
@@ -17360,20 +17840,35 @@ async function observe2(request, transport) {
17360
17840
  owner: input.destinationOwner,
17361
17841
  workspaceRoot: input.workspaceRoot
17362
17842
  },
17363
- manifestInventoryRevision: await computeInstallManifestInventoryRevision(targetRoot, adapter, transport),
17843
+ manifestInventoryRevision: await computeInstallManifestInventoryRevision(targetRoot, hasManagedBlock ? void 0 : adapter, transport),
17364
17844
  selected: selected.sort((left, right) => left.path.localeCompare(right.path)),
17365
17845
  retained: retained.sort((left, right) => left.path.localeCompare(right.path) || left.owner.localeCompare(right.owner)),
17366
17846
  remainingDuplicates: remainingDuplicates.sort((left, right) => left.stateKey.localeCompare(right.stateKey) || left.path.localeCompare(right.path)),
17367
17847
  // identity only, so a newer package revision doesn't invalidate a reviewed plan
17368
- desiredCoverage: request.desiredCoverage.filter((item) => selectedPaths.has(item.path)).map(({ path, artifactType, artifactName, kind }) => ({ path, artifactType, artifactName, kind })).sort((left, right) => left.path.localeCompare(right.path) || left.artifactType.localeCompare(right.artifactType) || left.artifactName.localeCompare(right.artifactName))
17848
+ desiredCoverage: request.desiredCoverage.filter((item) => selectedPaths.has(item.path)).map(({ path, artifactType, artifactName, kind, mode, logicalSelector }) => ({
17849
+ path,
17850
+ artifactType,
17851
+ artifactName,
17852
+ kind,
17853
+ ...mode ? { mode, logicalSelector: managedInstructionSelector(logicalSelector, artifactType, artifactName) } : {}
17854
+ })).sort((left, right) => left.path.localeCompare(right.path) || left.artifactType.localeCompare(right.artifactType) || left.artifactName.localeCompare(right.artifactName)),
17855
+ ...guardedInventory ? { metadataGuards: {
17856
+ inventory: guardedInventory.map((item) => ({ stateKey: item.stateKey, revision: item.manifest.revision })),
17857
+ runtime: selected.map((entry) => ({
17858
+ path: entry.path,
17859
+ hash: entry.runtimeHash,
17860
+ snapshotDigest: entry.runtimeSnapshotDigest,
17861
+ ...entry.managedBlock ? { managedBlock: entry.managedBlock } : {}
17862
+ }))
17863
+ } } : {}
17369
17864
  };
17370
- return { ...withoutDigest, planDigest: createHash22("sha256").update(canonicalJson6(withoutDigest)).digest("hex") };
17865
+ return { ...withoutDigest, planDigest: createHash23("sha256").update(canonicalJson6(withoutDigest)).digest("hex") };
17371
17866
  }
17372
17867
  async function normalizeRequest2(request) {
17373
17868
  if (request.destinationFleetId !== void 0) {
17374
17869
  throw new Error("Legacy ownership adoption targets a nested workspace; a Fleet target uses fleet normalize or ownership retire-stale.");
17375
17870
  }
17376
- const targetRoot = resolve39(request.targetRoot);
17871
+ const targetRoot = resolve40(request.targetRoot);
17377
17872
  const installationType = request.installationType.trim();
17378
17873
  const sourceStateKey = exactStateKey(request.adapter, request.sourceStateKey, installationType, "source");
17379
17874
  const destinationStateKey = exactStateKey(request.adapter, request.destinationStateKey, installationType, "destination");
@@ -17385,22 +17880,22 @@ async function normalizeRequest2(request) {
17385
17880
  const scope = await resolveWorkspaceOwnershipScope(request.workspaceRoot, { globalRoot: request.globalRoot });
17386
17881
  const destinationOwner = workspaceOwnerForRoot(scope.root, scope.fleetId);
17387
17882
  const workspaceRoot = await realpath3(request.workspaceRoot);
17388
- const sourceRoot = resolve39(request.fromWorkspaceRoot);
17883
+ const sourceRoot = resolve40(request.fromWorkspaceRoot);
17389
17884
  const sourceOwner = workspaceOwnerForRoot(sourceRoot);
17390
17885
  let sourceClass;
17391
- if (sourceRoot === workspaceRoot || sourceRoot === resolve39(request.workspaceRoot)) {
17886
+ if (sourceRoot === workspaceRoot || sourceRoot === resolve40(request.workspaceRoot)) {
17392
17887
  if (sourceOwner === destinationOwner) {
17393
17888
  throw new Error(`${sourceOwner} is already the destination owner; ordinary install migration handles its legacy state.`);
17394
17889
  }
17395
17890
  sourceClass = "own-legacy-owner";
17396
17891
  } else {
17397
17892
  const sourceForms = [sourceRoot, ...await realpath3(sourceRoot).then((path) => [path], () => [])];
17398
- const workspaceForms = [workspaceRoot, resolve39(request.workspaceRoot), scope.root];
17893
+ const workspaceForms = [workspaceRoot, resolve40(request.workspaceRoot), scope.root];
17399
17894
  if (sourceForms.some((source) => workspaceForms.some((workspace) => containsPath2(source, workspace) || containsPath2(workspace, source)))) {
17400
17895
  throw new Error(`Source root ${sourceRoot} contains or is contained by the destination workspace; it cannot be adopted as a foreign root.`);
17401
17896
  }
17402
17897
  for (const fleet of await listRegisteredFleets({ globalRoot: request.globalRoot })) {
17403
- const fleetForms = [resolve39(fleet.root), ...await realpath3(fleet.root).then((path) => [path], () => [])];
17898
+ const fleetForms = [resolve40(fleet.root), ...await realpath3(fleet.root).then((path) => [path], () => [])];
17404
17899
  if (sourceForms.some((source) => fleetForms.some((root) => containsPath2(root, source)))) {
17405
17900
  throw new Error(`Source root ${sourceRoot} is inside registered Fleet '${fleet.id}'; use fleet normalize or ownership retire-stale.`);
17406
17901
  }
@@ -17436,7 +17931,7 @@ async function selectLegacySource(input, stateKey, fingerprint, source, desiredB
17436
17931
  );
17437
17932
  }
17438
17933
  for (const entry of source.entries) {
17439
- if (entry.workspaceOwner === input.sourceOwner) assertPlainEntry(entry, input.targetRoot);
17934
+ if (entry.workspaceOwner === input.sourceOwner) assertSupportedLegacyEntry(entry, input.targetRoot);
17440
17935
  }
17441
17936
  const entries = [];
17442
17937
  const retained = [];
@@ -17514,20 +18009,21 @@ async function readDestination(identity, stateKey, transport) {
17514
18009
  }
17515
18010
  return requireManifest(identity, stateKey, transport, "destination");
17516
18011
  }
17517
- function assertPlainEntry(entry, targetRoot) {
17518
- if (entry.mode || entry.mergeStrategy || entry.semanticPlugin || entry.semanticCommand || entry.executed) {
18012
+ function assertSupportedLegacyEntry(entry, targetRoot) {
18013
+ const supportedBlock = entry.mode === "managed-block" && entry.kind === "file" && entry.artifactType === "instructions";
18014
+ if (entry.mode && !supportedBlock || entry.mergeStrategy || entry.semanticPlugin || entry.semanticCommand || entry.executed) {
17519
18015
  throw new Error(`Legacy ownership adoption supports only plain file or directory entries; ${entry.path} is not one.`);
17520
18016
  }
17521
18017
  containedArtifactPath(targetRoot, entry.path);
17522
18018
  }
17523
18019
  function desiredCovers(item, entry) {
17524
- return item.artifactType === entry.artifactType && item.artifactName === entry.artifactName && item.kind === entry.kind && (!item.packageName || !entry.packageName || item.packageName === entry.packageName);
18020
+ return item.artifactType === entry.artifactType && item.artifactName === entry.artifactName && item.kind === entry.kind && (!item.packageName || !entry.packageName || item.packageName === entry.packageName) && (entry.mode !== "managed-block" || item.mode === "managed-block" && managedInstructionSelector(item.logicalSelector, item.artifactType, item.artifactName) === managedInstructionSelector(entry.logicalSelector, entry.artifactType, entry.artifactName));
17525
18021
  }
17526
18022
  function coversSourceEntry(destination, source, owner) {
17527
- return destination.workspaceOwner === owner && !destination.mode && !destination.mergeStrategy && !destination.semanticPlugin && sameRecordedArtifact(destination, source);
18023
+ return destination.workspaceOwner === owner && destination.mode === source.mode && !destination.mergeStrategy && !destination.semanticPlugin && sameRecordedArtifact(destination, source) && (source.mode !== "managed-block" || entryDigest({ ...destination, workspaceOwner: source.workspaceOwner }) === entryDigest(source));
17528
18024
  }
17529
18025
  function sameRecordedArtifact(left, right) {
17530
- return left.artifactType === right.artifactType && left.artifactName === right.artifactName && left.kind === right.kind && left.hash === right.hash && left.sourceHash === right.sourceHash;
18026
+ return left.artifactType === right.artifactType && left.artifactName === right.artifactName && left.kind === right.kind && left.hash === right.hash && left.sourceHash === right.sourceHash && left.mode === right.mode && (left.mode !== "managed-block" || managedInstructionSelector(left.logicalSelector, left.artifactType, left.artifactName) === managedInstructionSelector(right.logicalSelector, right.artifactType, right.artifactName));
17531
18027
  }
17532
18028
  async function assertNoPendingJournals(targetRoot, adapter, transport) {
17533
18029
  const pending = await listAllApplyJournals(targetRoot, adapter, transport);
@@ -17549,14 +18045,14 @@ function assertApplyPreconditions2(request) {
17549
18045
  }
17550
18046
  }
17551
18047
  function containsPath2(parent, candidate) {
17552
- const path = relative16(parent, candidate);
18048
+ const path = relative17(parent, candidate);
17553
18049
  return path === "" || !path.startsWith("..") && !isAbsolute12(path);
17554
18050
  }
17555
18051
 
17556
18052
  // src/version/policy.ts
17557
18053
  import { execFile as execFile7 } from "child_process";
17558
18054
  import { readFile as readFile40 } from "fs/promises";
17559
- import { join as join53, resolve as resolve40 } from "path";
18055
+ import { join as join55, resolve as resolve41 } from "path";
17560
18056
  import { promisify as promisify7 } from "util";
17561
18057
  import { parse as parseJsonc } from "jsonc-parser";
17562
18058
  import { z as z15 } from "zod";
@@ -17653,7 +18149,7 @@ async function discoverVersionsFromSource(pkg, workspaceRoot) {
17653
18149
  if (tagged.length > 0) return tagged;
17654
18150
  }
17655
18151
  if (driverName === "local") {
17656
- const root = resolve40(workspaceRoot, pkg.source);
18152
+ const root = resolve41(workspaceRoot, pkg.source);
17657
18153
  const manifest2 = await readPackageManifest(root);
17658
18154
  const current = manifest2 ? [{ version: manifest2.version, ref: pkg.requestedRef ?? root }] : [];
17659
18155
  try {
@@ -17668,7 +18164,7 @@ async function discoverVersionsFromSource(pkg, workspaceRoot) {
17668
18164
  }
17669
18165
  const driver = getSourceDriver(driverName);
17670
18166
  const resolved = await driver.resolve(pkg.source, {
17671
- cacheRoot: join53(workspaceRoot, ".agentwheel", "cache"),
18167
+ cacheRoot: join55(workspaceRoot, ".agentwheel", "cache"),
17672
18168
  mode: "tracking",
17673
18169
  ref: pkg.requestedRef
17674
18170
  });
@@ -17762,7 +18258,7 @@ function gitUrlFromSource(source) {
17762
18258
  throw new Error(`Version discovery does not support Git source: ${source}`);
17763
18259
  }
17764
18260
  function versionCachePath(workspaceRoot) {
17765
- return join53(workspaceRoot, ".agentwheel", "cache", "version-index.json");
18261
+ return join55(workspaceRoot, ".agentwheel", "cache", "version-index.json");
17766
18262
  }
17767
18263
  async function readVersionCache(path) {
17768
18264
  if (!await pathExists(path)) return { schemaVersion: 1, sources: {} };
@@ -17779,7 +18275,7 @@ init_semver();
17779
18275
  // src/profile/members.ts
17780
18276
  import { execFile as execFile8 } from "child_process";
17781
18277
  import { readFile as readFile41 } from "fs/promises";
17782
- import { join as join54, resolve as resolve41 } from "path";
18278
+ import { join as join56, resolve as resolve42 } from "path";
17783
18279
  import { promisify as promisify8 } from "util";
17784
18280
  import { z as z17 } from "zod";
17785
18281
 
@@ -17955,7 +18451,7 @@ async function invokeMemberStatus(member, parentWorkspace, chain, options, cliEn
17955
18451
  let stderr = "";
17956
18452
  try {
17957
18453
  if (member.transport === "local") {
17958
- const workspace = resolve41(parentWorkspace, member.workspace);
18454
+ const workspace = resolve42(parentWorkspace, member.workspace);
17959
18455
  const result = await execFileAsync8(process.execPath, [cliEntry, ...args], {
17960
18456
  cwd: workspace,
17961
18457
  env: env2,
@@ -18001,7 +18497,7 @@ async function runMemberAgentwheel(member, parentWorkspace, args, chain) {
18001
18497
  process.execPath,
18002
18498
  [process.argv[1], ...memberCommandArgs(member, args)],
18003
18499
  {
18004
- cwd: resolve41(parentWorkspace, member.workspace),
18500
+ cwd: resolve42(parentWorkspace, member.workspace),
18005
18501
  env: env2,
18006
18502
  maxBuffer: 20 * 1024 * 1024
18007
18503
  }
@@ -18081,7 +18577,7 @@ function memberFailure(member, health, error) {
18081
18577
  };
18082
18578
  }
18083
18579
  function memberCachePath(workspaceRoot, profileName, memberId) {
18084
- return join54(workspaceRoot, ".agentwheel", "cache", "member-status", profileName, `${memberId}.json`);
18580
+ return join56(workspaceRoot, ".agentwheel", "cache", "member-status", profileName, `${memberId}.json`);
18085
18581
  }
18086
18582
  async function readMemberCache(path) {
18087
18583
  if (!await pathExists(path)) return void 0;
@@ -18107,7 +18603,7 @@ function assertNoCompositeCycle(workspaceRoot, profileName, chain) {
18107
18603
  }
18108
18604
  }
18109
18605
  function compositeKey(workspaceRoot, profileName) {
18110
- return `${resolve41(workspaceRoot)}#${profileName}`;
18606
+ return `${resolve42(workspaceRoot)}#${profileName}`;
18111
18607
  }
18112
18608
 
18113
18609
  // src/status/repository.ts
@@ -18154,10 +18650,10 @@ function valueAfter(lines, prefix) {
18154
18650
  }
18155
18651
 
18156
18652
  // src/catalogue/client.ts
18157
- import { createHash as createHash23 } from "crypto";
18653
+ import { createHash as createHash24 } from "crypto";
18158
18654
  import { readFile as readFile42, rm as rm15 } from "fs/promises";
18159
18655
  import { homedir as homedir15 } from "os";
18160
- import { join as join55 } from "path";
18656
+ import { join as join57 } from "path";
18161
18657
 
18162
18658
  // src/model/catalogue.ts
18163
18659
  import { z as z18 } from "zod";
@@ -18430,18 +18926,18 @@ var CatalogueClient = class {
18430
18926
  }
18431
18927
  return {
18432
18928
  value: schema.parse(value),
18433
- digest: createHash23("sha256").update(bytes).digest("hex")
18929
+ digest: createHash24("sha256").update(bytes).digest("hex")
18434
18930
  };
18435
18931
  }
18436
18932
  };
18437
18933
  function defaultCatalogueCachePath() {
18438
- return join55(homedir15(), ".agentwheel", "catalogue-cache.json");
18934
+ return join57(homedir15(), ".agentwheel", "catalogue-cache.json");
18439
18935
  }
18440
18936
  function sameSources2(a, b) {
18441
18937
  return a.length === b.length && a.every((source, index) => source === b[index]);
18442
18938
  }
18443
18939
  function catalogueContentHash(enriched, vercel) {
18444
- return createHash23("sha256").update(JSON.stringify({ enriched, vercel })).digest("hex");
18940
+ return createHash24("sha256").update(JSON.stringify({ enriched, vercel })).digest("hex");
18445
18941
  }
18446
18942
 
18447
18943
  // src/search/index.ts
@@ -18803,9 +19299,9 @@ function includesToken(normalizedText, token) {
18803
19299
  }
18804
19300
 
18805
19301
  // src/semantic/index.ts
18806
- import { createHash as createHash24 } from "crypto";
19302
+ import { createHash as createHash25 } from "crypto";
18807
19303
  import { homedir as homedir16 } from "os";
18808
- import { join as join56 } from "path";
19304
+ import { join as join58 } from "path";
18809
19305
  import { env, pipeline } from "@huggingface/transformers";
18810
19306
  var DEFAULT_SEMANTIC_INDEX_URL = "https://raw.githubusercontent.com/NestDevLab/agentwheel-registry/main/catalogue-semantic-index/gte-v1/";
18811
19307
  var CONTRACT = {
@@ -18893,13 +19389,13 @@ var SemanticSearchClient = class {
18893
19389
  if (!response.ok) throw new Error(`Semantic index file failed (${response.status}): ${descriptor.path}`);
18894
19390
  const bytes = new Uint8Array(await response.arrayBuffer());
18895
19391
  if (bytes.byteLength !== descriptor.bytes) throw new Error(`Semantic index file size does not match: ${descriptor.path}`);
18896
- const digest2 = createHash24("sha256").update(bytes).digest("hex");
18897
- if (digest2 !== descriptor.sha256) throw new Error(`Semantic index checksum does not match: ${descriptor.path}`);
19392
+ const digest3 = createHash25("sha256").update(bytes).digest("hex");
19393
+ if (digest3 !== descriptor.sha256) throw new Error(`Semantic index checksum does not match: ${descriptor.path}`);
18898
19394
  return bytes;
18899
19395
  }
18900
19396
  };
18901
19397
  async function embedQuery(query) {
18902
- env.cacheDir = join56(homedir16(), ".agentwheel", "semantic-models");
19398
+ env.cacheDir = join58(homedir16(), ".agentwheel", "semantic-models");
18903
19399
  const extractor = await pipeline("feature-extraction", CONTRACT.model.id, {
18904
19400
  revision: CONTRACT.model.revision,
18905
19401
  dtype: CONTRACT.model.dtype,
@@ -18983,9 +19479,9 @@ function ensureTrailingSlash(value) {
18983
19479
  }
18984
19480
 
18985
19481
  // src/trial/skill.ts
18986
- import { createHash as createHash25 } from "crypto";
19482
+ import { createHash as createHash26 } from "crypto";
18987
19483
  import { readFile as readFile43, stat as stat16 } from "fs/promises";
18988
- import { join as join57 } from "path";
19484
+ import { join as join59 } from "path";
18989
19485
  import { parse as parseYaml2 } from "yaml";
18990
19486
  var MAX_TRIAL_SKILL_BYTES = 512 * 1024;
18991
19487
  async function createSkillTrial(driver, resolved, selectors) {
@@ -18997,7 +19493,7 @@ async function createSkillTrial(driver, resolved, selectors) {
18997
19493
  throw new Error("Skill trial requires exactly one selected skill. Use --skill <name> or --select skills/<name>.");
18998
19494
  }
18999
19495
  const artifact = skills[0];
19000
- const path = artifact.kind === "dir" ? join57(artifact.sourcePath, "SKILL.md") : artifact.sourcePath;
19496
+ const path = artifact.kind === "dir" ? join59(artifact.sourcePath, "SKILL.md") : artifact.sourcePath;
19001
19497
  const info = await stat16(path);
19002
19498
  if (info.size > MAX_TRIAL_SKILL_BYTES) {
19003
19499
  throw new Error(`Skill trial exceeds the ${MAX_TRIAL_SKILL_BYTES / 1024} KiB content limit.`);
@@ -19013,7 +19509,7 @@ async function createSkillTrial(driver, resolved, selectors) {
19013
19509
  skill: {
19014
19510
  name: artifact.name,
19015
19511
  relativePath: artifact.relativePath,
19016
- sha256: createHash25("sha256").update(content).digest("hex"),
19512
+ sha256: createHash26("sha256").update(content).digest("hex"),
19017
19513
  frontmatter,
19018
19514
  content
19019
19515
  }
@@ -19032,10 +19528,10 @@ function readSkillFrontmatter(content, artifact) {
19032
19528
  }
19033
19529
 
19034
19530
  // src/lifecycle/fleet-normalize.ts
19035
- import { createHash as createHash26 } from "crypto";
19036
- import { readFile as readFile44, readdir as readdir15, rm as rm16 } from "fs/promises";
19531
+ import { createHash as createHash27 } from "crypto";
19532
+ import { readFile as readFile44, readdir as readdir16, rm as rm16 } from "fs/promises";
19037
19533
  import { homedir as homedir17 } from "os";
19038
- import { dirname as dirname36, isAbsolute as isAbsolute13, join as join58, relative as relative17, resolve as resolve42 } from "path";
19534
+ import { dirname as dirname36, isAbsolute as isAbsolute13, join as join60, relative as relative18, resolve as resolve43 } from "path";
19039
19535
  init_manifest2();
19040
19536
  init_paths();
19041
19537
  init_merge_removal();
@@ -19071,14 +19567,14 @@ async function planFleetNormalization(request) {
19071
19567
  if (legacySelfNormalization && normalizedRequest.orphanedOwnerRoots?.length && normalizedRequest.packages?.includes(name)) {
19072
19568
  packages.push({
19073
19569
  name,
19074
- declarationDigest: sha2567(canonicalJson7({ name, evidence: "orphaned-installed-state" }))
19570
+ declarationDigest: sha2567(canonicalJson8({ name, evidence: "orphaned-installed-state" }))
19075
19571
  });
19076
19572
  continue;
19077
19573
  }
19078
19574
  throw new Error(`Package '${name}' must be an existing duplicate in both source and destination fleets.`);
19079
19575
  }
19080
- const sourceDeclaration = canonicalJson7(sourcePackage);
19081
- const destinationDeclaration = canonicalJson7(destinationPackage);
19576
+ const sourceDeclaration = canonicalJson8(sourcePackage);
19577
+ const destinationDeclaration = canonicalJson8(destinationPackage);
19082
19578
  if (sourceDeclaration !== destinationDeclaration) {
19083
19579
  throw new Error(
19084
19580
  `Package '${name}' has divergent declarations. Source, driver, adapter, adapter configuration, installation type, version policy, runtime restrictions, selections, aliases, overrides, and suggestions must match before normalization.`
@@ -19115,7 +19611,7 @@ async function planFleetNormalization(request) {
19115
19611
  packages,
19116
19612
  installedState
19117
19613
  };
19118
- return { ...planWithoutDigest, planDigest: sha2567(canonicalJson7(planWithoutDigest)) };
19614
+ return { ...planWithoutDigest, planDigest: sha2567(canonicalJson8(planWithoutDigest)) };
19119
19615
  }
19120
19616
  async function applyFleetNormalization(request, hooks = {}) {
19121
19617
  if (!request.apply) throw new Error("Fleet normalization is dry-run by default; pass --apply with --plan-digest <digest>.");
@@ -19253,8 +19749,8 @@ async function assertNormalizationPostconditions(journal) {
19253
19749
  }
19254
19750
  for (const graphLock of journal.graphLocks) {
19255
19751
  const raw = await readOptionalRecord(graphLock.path);
19256
- const digest2 = raw ? sha2567(canonicalJson7(await readGraphLock(graphLock.path))) : null;
19257
- if (digest2 !== graphLock.afterDigest) {
19752
+ const digest3 = raw ? sha2567(canonicalJson8(await readGraphLock(graphLock.path))) : null;
19753
+ if (digest3 !== graphLock.afterDigest) {
19258
19754
  throw new Error(`Fleet normalization graph-lock postcheck failed: ${graphLock.path}`);
19259
19755
  }
19260
19756
  }
@@ -19325,17 +19821,17 @@ function normalizeRequest3(request) {
19325
19821
  ...profile ? { profile } : {},
19326
19822
  ...agent ? { agent } : {},
19327
19823
  ...orphanedOwnerRoots ? { orphanedOwnerRoots } : {},
19328
- ...request.globalRoot ? { globalRoot: resolve42(request.globalRoot) } : {}
19824
+ ...request.globalRoot ? { globalRoot: resolve43(request.globalRoot) } : {}
19329
19825
  };
19330
19826
  }
19331
19827
  function normalizeOrphanedOwnerRoot(value) {
19332
19828
  const root = value.trim();
19333
19829
  if (!root || !isAbsolute13(root)) throw new Error(`Invalid orphaned owner root '${value}'; expected an absolute workspace path.`);
19334
- return resolve42(root);
19830
+ return resolve43(root);
19335
19831
  }
19336
19832
  async function normalizationRoots(request) {
19337
19833
  const destination = await showRegisteredFleet(request.destinationFleet, { globalRoot: request.globalRoot });
19338
- const source = request.from === "user" ? resolve42(request.globalRoot ?? homedir17()) : (await showRegisteredFleet(request.from.slice("fleet:".length), { globalRoot: request.globalRoot })).root;
19834
+ const source = request.from === "user" ? resolve43(request.globalRoot ?? homedir17()) : (await showRegisteredFleet(request.from.slice("fleet:".length), { globalRoot: request.globalRoot })).root;
19339
19835
  return { source, destination: destination.root };
19340
19836
  }
19341
19837
  async function withOrderedLocks(roots, fn) {
@@ -19343,7 +19839,7 @@ async function withOrderedLocks(roots, fn) {
19343
19839
  if (index === roots.length) return fn();
19344
19840
  const root = roots[index];
19345
19841
  return withFilesystemLock(
19346
- join58(root, ".agentwheel", "fleet-normalize.lock"),
19842
+ join60(root, ".agentwheel", "fleet-normalize.lock"),
19347
19843
  5e3,
19348
19844
  () => run(index + 1),
19349
19845
  "fleet normalization"
@@ -19442,10 +19938,10 @@ async function inspectInstalledState(source, destination, packageNames) {
19442
19938
  const destinationGraphAfter = destinationGraph?.lock ?? destinationGraphFromSource(sourceGraph.lock, destinationState.targetFingerprint);
19443
19939
  graphTransfers.push({
19444
19940
  sourceGraphLockPath: sourceGraph.path,
19445
- sourceGraphLockDigest: sha2567(canonicalJson7(sourceGraph.lock)),
19941
+ sourceGraphLockDigest: sha2567(canonicalJson8(sourceGraph.lock)),
19446
19942
  destinationGraphLockPath: destinationState.graphLockPath,
19447
- destinationGraphLockDigest: destinationGraph ? sha2567(canonicalJson7(destinationGraph.lock)) : null,
19448
- destinationGraphLockAfterDigest: sha2567(canonicalJson7(destinationGraphAfter)),
19943
+ destinationGraphLockDigest: destinationGraph ? sha2567(canonicalJson8(destinationGraph.lock)) : null,
19944
+ destinationGraphLockAfterDigest: sha2567(canonicalJson8(destinationGraphAfter)),
19449
19945
  targetKey: sourceGraph.targetKey,
19450
19946
  adapter: destinationState.adapter,
19451
19947
  targetFingerprint: destinationState.targetFingerprint
@@ -19550,7 +20046,7 @@ async function inspectLegacySelfInstalledState(fleet, packageNames, profileName,
19550
20046
  let normalizedGraphCount = 0;
19551
20047
  for (const graph of graphCandidates) {
19552
20048
  const destinationState = await targetStateForGraph(fleet, graph, fleet.fleetId, allowOrphanedRetiredPackages);
19553
- if (resolve42(destinationState.graphLockPath) === resolve42(graph.path)) {
20049
+ if (resolve43(destinationState.graphLockPath) === resolve43(graph.path)) {
19554
20050
  const destinationManifest = (await collectManifestPaths([destinationState.manifestPath]))[0];
19555
20051
  if (destinationManifest?.manifest.entries.some((entry) => entry.workspaceOwner === fleetOwner && entryMatchesPackages(entry, selected))) {
19556
20052
  assertCorrelatedGraphManifest(
@@ -19565,7 +20061,7 @@ async function inspectLegacySelfInstalledState(fleet, packageNames, profileName,
19565
20061
  }
19566
20062
  }
19567
20063
  const legacyState = await legacyTargetStateForGraph(fleet, graph, allowOrphanedRetiredPackages);
19568
- if (resolve42(legacyState.graphLockPath) !== resolve42(graph.path)) {
20064
+ if (resolve43(legacyState.graphLockPath) !== resolve43(graph.path)) {
19569
20065
  throw new Error(`Legacy graph lock target identity is stale or noncanonical: ${graph.path}`);
19570
20066
  }
19571
20067
  const legacyManifest = (await collectManifestPaths([legacyState.manifestPath]))[0];
@@ -19673,7 +20169,7 @@ async function inspectLegacySelfInstalledState(fleet, packageNames, profileName,
19673
20169
  )
19674
20170
  });
19675
20171
  if (!selectedArtifacts) {
19676
- const fullDigest = sha2567(canonicalJson7(graph.lock));
20172
+ const fullDigest = sha2567(canonicalJson8(graph.lock));
19677
20173
  const existingDestinationGraph = graphCandidates.find((candidate) => candidate.path === destinationState.graphLockPath);
19678
20174
  if (existingDestinationGraph) assertGraphIsSubset(graph, existingDestinationGraph);
19679
20175
  const destinationGraph = destinationGraphFromSource(graph.lock, destinationState.targetFingerprint);
@@ -19681,8 +20177,8 @@ async function inspectLegacySelfInstalledState(fleet, packageNames, profileName,
19681
20177
  sourceGraphLockPath: graph.path,
19682
20178
  sourceGraphLockDigest: fullDigest,
19683
20179
  destinationGraphLockPath: destinationState.graphLockPath,
19684
- destinationGraphLockDigest: existingDestinationGraph ? sha2567(canonicalJson7(existingDestinationGraph.lock)) : null,
19685
- destinationGraphLockAfterDigest: sha2567(canonicalJson7(destinationGraph)),
20180
+ destinationGraphLockDigest: existingDestinationGraph ? sha2567(canonicalJson8(existingDestinationGraph.lock)) : null,
20181
+ destinationGraphLockAfterDigest: sha2567(canonicalJson8(destinationGraph)),
19686
20182
  targetKey: graph.targetKey,
19687
20183
  adapter: graph.adapter,
19688
20184
  targetFingerprint: destinationState.targetFingerprint
@@ -19740,7 +20236,7 @@ function targetKeysForAgent(scope, name) {
19740
20236
  async function runtimeRoots(scope) {
19741
20237
  const roots = /* @__PURE__ */ new Set([scope.root]);
19742
20238
  if (scope.config.packages.some((pkg) => pkg.installationType === "user") || Object.values(scope.config.agents).some((agent) => agent.installationType === "user")) {
19743
- roots.add(resolve42(process.env.AGENTWHEEL_TEST_HOME || process.env.HOME || homedir17()));
20239
+ roots.add(resolve43(process.env.AGENTWHEEL_TEST_HOME || process.env.HOME || homedir17()));
19744
20240
  }
19745
20241
  for (const [name, agent] of Object.entries(scope.config.agents)) {
19746
20242
  if (agent.transport === "ssh" || agent.transport === "local-run-as") throw new Error(`Installed-state normalization cannot inspect ${agent.transport} agent '${name}' locally.`);
@@ -19758,17 +20254,17 @@ async function runtimeRoots(scope) {
19758
20254
  async function collectManifests(roots) {
19759
20255
  const found = /* @__PURE__ */ new Map();
19760
20256
  for (const root of roots) {
19761
- const dir = join58(root, ".agentwheel");
20257
+ const dir = join60(root, ".agentwheel");
19762
20258
  let names;
19763
20259
  try {
19764
- names = await readdir15(dir);
20260
+ names = await readdir16(dir);
19765
20261
  } catch (error) {
19766
20262
  if (isMissing5(error)) continue;
19767
20263
  throw error;
19768
20264
  }
19769
20265
  for (const name of names.sort((a, b) => a.localeCompare(b))) {
19770
20266
  if (!name.endsWith(".install-manifest.json")) continue;
19771
- const path = join58(dir, name);
20267
+ const path = join60(dir, name);
19772
20268
  const raw = JSON.parse(await readFile44(path, "utf8"));
19773
20269
  const parsed = installManifestSchema.parse(raw);
19774
20270
  if (parsed.version !== 2) {
@@ -19777,14 +20273,14 @@ async function collectManifests(roots) {
19777
20273
  }
19778
20274
  continue;
19779
20275
  }
19780
- if (resolve42(parsed.targetRoot) !== resolve42(root)) {
20276
+ if (resolve43(parsed.targetRoot) !== resolve43(root)) {
19781
20277
  throw new Error(`Install manifest target root does not match its enumerated runtime root: ${path}`);
19782
20278
  }
19783
20279
  const expectedPath = installManifestPath(parsed.targetRoot, parsed.adapter, {
19784
20280
  installationType: parsed.installationType,
19785
20281
  stateKey: parsed.stateKey
19786
20282
  });
19787
- if (resolve42(expectedPath) !== resolve42(path)) {
20283
+ if (resolve43(expectedPath) !== resolve43(path)) {
19788
20284
  throw new Error(`Install manifest state identity does not match its canonical path: ${path}`);
19789
20285
  }
19790
20286
  found.set(path, { path, raw, manifest: { ...parsed, revision: computeManifestRevision(raw), legacy: false } });
@@ -19805,7 +20301,7 @@ async function collectManifestPaths(paths) {
19805
20301
  installationType: parsed.installationType,
19806
20302
  stateKey: parsed.stateKey
19807
20303
  });
19808
- if (resolve42(expectedPath) !== resolve42(path)) {
20304
+ if (resolve43(expectedPath) !== resolve43(path)) {
19809
20305
  throw new Error(`Install manifest state identity does not match its canonical path: ${path}`);
19810
20306
  }
19811
20307
  found.push({ path, raw, manifest: { ...parsed, revision: computeManifestRevision(raw), legacy: false } });
@@ -19824,14 +20320,14 @@ function assertNoForeignSamePathOwnership(manifests, renderedPaths, allowedOwner
19824
20320
  }
19825
20321
  }
19826
20322
  async function relevantGraphLocks(workspaceRoot, selected, targetKeys, include) {
19827
- const root = join58(workspaceRoot, ".agentwheel", "locks");
20323
+ const root = join60(workspaceRoot, ".agentwheel", "locks");
19828
20324
  if (!await pathExists(root)) return [];
19829
20325
  const results = [];
19830
20326
  for (const path of await listFiles(root)) {
19831
20327
  if (!path.endsWith(".graph-lock.json")) continue;
19832
20328
  const lock = await readGraphLock(path);
19833
20329
  if (!lock.canonical.roots.some((candidate2) => selected.has(candidate2.rootId))) continue;
19834
- const parts = relative17(root, path).split(/[\\/]/);
20330
+ const parts = relative18(root, path).split(/[\\/]/);
19835
20331
  if (parts.length !== 3) throw new Error(`Graph lock path is not canonical: ${path}`);
19836
20332
  const [targetKey2, adapter] = parts;
19837
20333
  if (targetKeys && !targetKeys.has(targetKey2)) continue;
@@ -19848,7 +20344,7 @@ async function relevantGraphLocks(workspaceRoot, selected, targetKeys, include)
19848
20344
  const projection = relevantGraphProjection(lock, selected);
19849
20345
  results.push({
19850
20346
  ...candidate,
19851
- digest: sha2567(canonicalJson7(projection)),
20347
+ digest: sha2567(canonicalJson8(projection)),
19852
20348
  artifactIdentities: lock.canonical.artifacts.filter((artifact) => artifact.owners.some((owner) => ownerMatchesGraphPackage(lock, owner, selected))).map(graphArtifactIdentity).sort()
19853
20349
  });
19854
20350
  }
@@ -19873,7 +20369,7 @@ async function hasRelevantLegacyManifestCandidate(scope, graph, selected) {
19873
20369
  const legacyManifest = (await collectManifestPaths([legacyState.manifestPath]))[0];
19874
20370
  if (legacyManifest?.manifest.entries.some((entry) => entryMatchesGraphPackages(entry, graph.lock, selected))) return true;
19875
20371
  const stableState = await targetStateForGraph(scope, graph, scope.fleetId ?? null);
19876
- if (resolve42(stableState.graphLockPath) !== resolve42(graph.path)) return false;
20372
+ if (resolve43(stableState.graphLockPath) !== resolve43(graph.path)) return false;
19877
20373
  const stableManifest = (await collectManifestPaths([stableState.manifestPath]))[0];
19878
20374
  return stableManifest?.manifest.entries.some((entry) => entryMatchesGraphPackages(entry, graph.lock, selected)) ?? false;
19879
20375
  }
@@ -19894,7 +20390,7 @@ async function legacyManifestPathForConfiguredTarget(scope, graph) {
19894
20390
  baseDir: scope.root
19895
20391
  });
19896
20392
  const targetRoot = resolveConfigPath(agent.root, scope.root);
19897
- const installRoot = resolve42(installRootForAdapterInstallationType(adapter, targetRoot, agent.installationType, { kind: "local" }));
20393
+ const installRoot = resolve43(installRootForAdapterInstallationType(adapter, targetRoot, agent.installationType, { kind: "local" }));
19898
20394
  const stateKey = stateKeyFor(adapter.name, {
19899
20395
  installationType: agent.installationType,
19900
20396
  stateKey: agent.stateKey,
@@ -19962,7 +20458,7 @@ async function targetStateForGraph(scope, graph, identityFleetId = scope.fleetId
19962
20458
  ssh: void 0,
19963
20459
  ...agent?.stateKey ? { stateKey: agent.stateKey } : {}
19964
20460
  };
19965
- const installRoot = resolve42(installRootForAdapterInstallationType(adapter, targetRoot, installationType, { kind: "local" }));
20461
+ const installRoot = resolve43(installRootForAdapterInstallationType(adapter, targetRoot, installationType, { kind: "local" }));
19966
20462
  const targetIdentity = resolveTargetStateIdentity({
19967
20463
  targetFingerprintParts: fingerprintParts,
19968
20464
  workspaceRoot: scope.root,
@@ -19994,16 +20490,16 @@ async function targetStateForGraph(scope, graph, identityFleetId = scope.fleetId
19994
20490
  async function installedTargetStateForGraph(scope, graph, manifests, owners, selected, identityFleetId = scope.fleetId ?? null) {
19995
20491
  const stable = await targetStateForGraph(scope, graph, identityFleetId);
19996
20492
  let state;
19997
- if (resolve42(graph.path) === resolve42(stable.graphLockPath)) {
20493
+ if (resolve43(graph.path) === resolve43(stable.graphLockPath)) {
19998
20494
  state = stable;
19999
20495
  } else {
20000
20496
  const released = await releasedTargetStateForGraph(scope, graph, identityFleetId);
20001
- if (resolve42(graph.path) !== resolve42(released.graphLockPath)) {
20497
+ if (resolve43(graph.path) !== resolve43(released.graphLockPath)) {
20002
20498
  throw new Error(`Graph lock target identity is stale or noncanonical: ${graph.path}`);
20003
20499
  }
20004
20500
  state = released;
20005
20501
  }
20006
- const manifest = manifests.find((candidate) => resolve42(candidate.path) === resolve42(state.manifestPath));
20502
+ const manifest = manifests.find((candidate) => resolve43(candidate.path) === resolve43(state.manifestPath));
20007
20503
  if (!manifest) {
20008
20504
  throw new Error(`Graph lock is not covered by its canonical install manifest: ${state.manifestPath}`);
20009
20505
  }
@@ -20027,7 +20523,7 @@ async function releasedTargetStateForGraph(scope, graph, identityFleetId = scope
20027
20523
  ...current,
20028
20524
  stateKey,
20029
20525
  targetFingerprint,
20030
- graphLockPath: join58(dirname36(graph.path), `${targetFingerprint}.graph-lock.json`),
20526
+ graphLockPath: join60(dirname36(graph.path), `${targetFingerprint}.graph-lock.json`),
20031
20527
  manifestPath: installManifestPath(current.installRoot, current.adapter, {
20032
20528
  installationType: current.installationType,
20033
20529
  stateKey
@@ -20035,7 +20531,7 @@ async function releasedTargetStateForGraph(scope, graph, identityFleetId = scope
20035
20531
  };
20036
20532
  }
20037
20533
  function assertCorrelatedGraphManifest(graph, state, manifest, owners, selected) {
20038
- if (manifest.manifest.adapter !== state.adapter || manifest.manifest.installationType !== state.installationType || manifest.manifest.stateKey !== state.stateKey || resolve42(manifest.manifest.targetRoot) !== resolve42(state.installRoot)) {
20534
+ if (manifest.manifest.adapter !== state.adapter || manifest.manifest.installationType !== state.installationType || manifest.manifest.stateKey !== state.stateKey || resolve43(manifest.manifest.targetRoot) !== resolve43(state.installRoot)) {
20039
20535
  throw new Error(`Install manifest identity does not match graph target state: ${manifest.path}`);
20040
20536
  }
20041
20537
  const entries = manifest.manifest.entries.filter((entry) => entryMatchesGraphPackages(entry, graph.lock, selected));
@@ -20043,7 +20539,7 @@ function assertCorrelatedGraphManifest(graph, state, manifest, owners, selected)
20043
20539
  throw new Error(`Graph lock is not covered by selected install-manifest contributions: ${graph.path}`);
20044
20540
  }
20045
20541
  const graphArtifacts = new Set(graph.artifactIdentities);
20046
- const graphLockDigest = sha2567(canonicalJson7(graph.lock));
20542
+ const graphLockDigest = sha2567(canonicalJson8(graph.lock));
20047
20543
  for (const entry of entries) {
20048
20544
  if (!owners.has(entry.workspaceOwner)) {
20049
20545
  throw new Error(`Graph lock manifest owner mismatch at ${manifest.path}: ${entry.workspaceOwner}.`);
@@ -20060,9 +20556,9 @@ async function legacyTargetStateForGraph(scope, graph, allowMissingNamedAgentPac
20060
20556
  return releasedTargetStateForGraph(scope, graph, null, allowMissingNamedAgentPackages);
20061
20557
  }
20062
20558
  function assertGraphIsSubset(source, destination) {
20063
- const sourceRoots = new Map(source.lock.canonical.roots.map((root) => [root.rootId, canonicalJson7(root)]));
20559
+ const sourceRoots = new Map(source.lock.canonical.roots.map((root) => [root.rootId, canonicalJson8(root)]));
20064
20560
  for (const root of destination.lock.canonical.roots) {
20065
- if (sourceRoots.get(root.rootId) !== canonicalJson7(root)) {
20561
+ if (sourceRoots.get(root.rootId) !== canonicalJson8(root)) {
20066
20562
  throw new Error(
20067
20563
  `Partially normalized destination graph diverges at root '${root.rootId}': ${destination.path}`
20068
20564
  );
@@ -20092,7 +20588,7 @@ function destinationGraphFromSource(source, targetFingerprint) {
20092
20588
  function mergeDestinationManifest(existing, state, generatedAt, desiredEntries, replaceOwners = /* @__PURE__ */ new Set()) {
20093
20589
  if (existing) {
20094
20590
  const manifest2 = existing.manifest;
20095
- if (manifest2.adapter !== state.adapter || manifest2.installationType !== state.installationType || manifest2.stateKey !== state.stateKey || resolve42(manifest2.targetRoot) !== state.installRoot) {
20591
+ if (manifest2.adapter !== state.adapter || manifest2.installationType !== state.installationType || manifest2.stateKey !== state.stateKey || resolve43(manifest2.targetRoot) !== state.installRoot) {
20096
20592
  throw new Error(`Destination manifest identity diverges from the derived target: ${existing.path}`);
20097
20593
  }
20098
20594
  }
@@ -20152,7 +20648,7 @@ async function assertEquivalentRuntimeState(entry, sourcePath, destinationPath)
20152
20648
  const content = await readFile44(path, "utf8");
20153
20649
  if (hasMergeRemovalContent(entry.mergeRemoval)) {
20154
20650
  assertExactMergeContribution(entry.mergeRemoval, entry.mergeStrategy, content);
20155
- } else if (resolve42(sourcePath) === resolve42(destinationPath) && entry.mergeStrategy !== "codex-toml-mcp") {
20651
+ } else if (resolve43(sourcePath) === resolve43(destinationPath) && entry.mergeStrategy !== "codex-toml-mcp") {
20156
20652
  assertExactMergeContribution({}, entry.mergeStrategy, content);
20157
20653
  } else {
20158
20654
  throw new Error(`Installed-state normalization cannot prove incomplete merge ownership at ${path}.`);
@@ -20163,8 +20659,8 @@ async function assertEquivalentRuntimeState(entry, sourcePath, destinationPath)
20163
20659
  await assertEquivalentRuntimeBytes(sourcePath, destinationPath, entry.hash);
20164
20660
  }
20165
20661
  function renderedEntryPathForRoot(root, entryPath) {
20166
- const normalizedRoot = resolve42(root);
20167
- const candidate = resolve42(normalizedRoot, entryPath);
20662
+ const normalizedRoot = resolve43(root);
20663
+ const candidate = resolve43(normalizedRoot, entryPath);
20168
20664
  if (candidate !== normalizedRoot && !candidate.startsWith(`${normalizedRoot}/`)) {
20169
20665
  throw new Error(`Install manifest entry escapes its target root: ${entryPath}`);
20170
20666
  }
@@ -20255,8 +20751,8 @@ function ownerMatchesGraphPackage(lock, owner, selected) {
20255
20751
  return ownerMatchesPackage(owner, selected) || lock.canonical.roots.some((root) => selected.has(root.rootId) && root.graphNodeId === owner);
20256
20752
  }
20257
20753
  function renderedEntryPath(manifest, entry) {
20258
- const root = resolve42(manifest.targetRoot);
20259
- const candidate = resolve42(root, entry.path);
20754
+ const root = resolve43(manifest.targetRoot);
20755
+ const candidate = resolve43(root, entry.path);
20260
20756
  if (candidate !== root && !candidate.startsWith(`${root}/`)) {
20261
20757
  throw new Error(`Install manifest entry escapes its target root: ${entry.path}`);
20262
20758
  }
@@ -20275,7 +20771,7 @@ function assertSimpleVerifiableEntry(entry, path) {
20275
20771
  if (entry.kind !== "file" && entry.kind !== "dir") throw new Error(`Unsupported installed entry kind at ${path}.`);
20276
20772
  }
20277
20773
  function entryIdentity(entry) {
20278
- return canonicalJson7({
20774
+ return canonicalJson8({
20279
20775
  path: entry.path,
20280
20776
  artifactType: entry.artifactType,
20281
20777
  artifactName: entry.artifactName,
@@ -20293,7 +20789,7 @@ function entryIdentity(entry) {
20293
20789
  });
20294
20790
  }
20295
20791
  function graphArtifactIdentity(artifact) {
20296
- return canonicalJson7({
20792
+ return canonicalJson8({
20297
20793
  graphNodeId: artifact.graphNodeId,
20298
20794
  type: artifact.type,
20299
20795
  name: artifact.name,
@@ -20307,7 +20803,7 @@ function graphArtifactIdentity(artifact) {
20307
20803
  });
20308
20804
  }
20309
20805
  function graphEntryIdentity(entry) {
20310
- return canonicalJson7({
20806
+ return canonicalJson8({
20311
20807
  graphNodeId: entry.graphNodeId,
20312
20808
  type: entry.artifactType,
20313
20809
  name: entry.artifactName,
@@ -20411,7 +20907,7 @@ async function buildJournalGraphLockStates(plan) {
20411
20907
  for (const transfer of plan.installedState.graphTransfers) {
20412
20908
  const sourceBefore = JSON.parse(await readFile44(transfer.sourceGraphLockPath, "utf8"));
20413
20909
  const sourceLock = await readGraphLock(transfer.sourceGraphLockPath);
20414
- const sourceDigest = sha2567(canonicalJson7(sourceLock));
20910
+ const sourceDigest = sha2567(canonicalJson8(sourceLock));
20415
20911
  if (sourceDigest !== transfer.sourceGraphLockDigest) {
20416
20912
  throw new Error(`Source graph lock changed after planning: ${transfer.sourceGraphLockPath}`);
20417
20913
  }
@@ -20429,9 +20925,9 @@ async function buildJournalGraphLockStates(plan) {
20429
20925
  continue;
20430
20926
  }
20431
20927
  const destinationBefore = await readOptionalRecord(transfer.destinationGraphLockPath);
20432
- const destinationBeforeDigest = destinationBefore ? sha2567(canonicalJson7(await readGraphLock(transfer.destinationGraphLockPath))) : null;
20928
+ const destinationBeforeDigest = destinationBefore ? sha2567(canonicalJson8(await readGraphLock(transfer.destinationGraphLockPath))) : null;
20433
20929
  const destinationAfter = destinationBefore ? await readGraphLock(transfer.destinationGraphLockPath) : destinationGraphFromSource(sourceLock, transfer.targetFingerprint);
20434
- const destinationAfterDigest = sha2567(canonicalJson7(destinationAfter));
20930
+ const destinationAfterDigest = sha2567(canonicalJson8(destinationAfter));
20435
20931
  if (destinationBeforeDigest !== transfer.destinationGraphLockDigest || destinationAfterDigest !== transfer.destinationGraphLockAfterDigest) {
20436
20932
  throw new Error(`Destination graph lock changed after planning: ${transfer.destinationGraphLockPath}`);
20437
20933
  }
@@ -20541,8 +21037,8 @@ async function assertJournalRecoverable(journal) {
20541
21037
  }
20542
21038
  for (const graphLock of journal.graphLocks) {
20543
21039
  const raw = await readOptionalRecord(graphLock.path);
20544
- const digest2 = raw ? sha2567(canonicalJson7(await readGraphLock(graphLock.path))) : null;
20545
- if (digest2 !== graphLock.beforeDigest && digest2 !== graphLock.afterDigest) {
21040
+ const digest3 = raw ? sha2567(canonicalJson8(await readGraphLock(graphLock.path))) : null;
21041
+ if (digest3 !== graphLock.beforeDigest && digest3 !== graphLock.afterDigest) {
20546
21042
  throw new Error(`Cannot recover fleet normalization because graph lock changed outside the transaction: ${graphLock.path}`);
20547
21043
  }
20548
21044
  }
@@ -20594,12 +21090,12 @@ function packageMap(config) {
20594
21090
  return result;
20595
21091
  }
20596
21092
  function configRevision(config) {
20597
- return sha2567(canonicalJson7(config));
21093
+ return sha2567(canonicalJson8(config));
20598
21094
  }
20599
21095
  function normalizationJournalPath(sourceRoot, destinationFleet) {
20600
- return join58(sourceRoot, ".agentwheel", `fleet-normalize-${destinationFleet}.journal.json`);
21096
+ return join60(sourceRoot, ".agentwheel", `fleet-normalize-${destinationFleet}.journal.json`);
20601
21097
  }
20602
- function canonicalJson7(value) {
21098
+ function canonicalJson8(value) {
20603
21099
  return JSON.stringify(sortValue(value));
20604
21100
  }
20605
21101
  function sortValue(value) {
@@ -20610,7 +21106,7 @@ function sortValue(value) {
20610
21106
  return value;
20611
21107
  }
20612
21108
  function sha2567(value) {
20613
- return createHash26("sha256").update(value).digest("hex");
21109
+ return createHash27("sha256").update(value).digest("hex");
20614
21110
  }
20615
21111
  function assertDigest(value) {
20616
21112
  if (!/^[a-f0-9]{64}$/.test(value)) throw new Error(`Invalid plan digest: ${value}`);
@@ -20655,6 +21151,7 @@ var commandGovernance = {
20655
21151
  "ownership handoff": "governed-unless-dry-run",
20656
21152
  "ownership recovery-plan": "incidental-cache",
20657
21153
  "ownership retire-stale": "governed-apply",
21154
+ "ownership release-claim": "governed-apply",
20658
21155
  "ownership adopt-legacy": "governed-apply",
20659
21156
  "mcp retire": "governed-apply",
20660
21157
  eject: "governed-always",
@@ -20761,7 +21258,7 @@ fleetCommand.command("normalize").description("plan or apply duplicate desired-s
20761
21258
  });
20762
21259
  cacheCommand.command("prune").description("remove old Git source snapshots while preserving locked commits").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("-t, --target-root <path>", "explicit workspace root").option("--keep <count>", "newest snapshots to retain per source", parsePositiveInteger, 3).option("--apply", "delete the selected snapshots; without this flag only preview", false).action(async (options) => {
20763
21260
  const targetRoot = await workspaceContextRootFromOptions(normalizeRuntimeScopeOptions(options));
20764
- const cacheRoot = join59(targetRoot, ".agentwheel", "cache");
21261
+ const cacheRoot = join61(targetRoot, ".agentwheel", "cache");
20765
21262
  const result = await pruneGitCache(cacheRoot, { keepSnapshots: options.keep, dryRun: !options.apply });
20766
21263
  const verb = options.apply ? "Removed" : "Would remove";
20767
21264
  for (const path of result.removedPaths) console.log(`${verb} ${path}`);
@@ -20779,7 +21276,7 @@ program.command("list").description("list artifacts exposed by a package source"
20779
21276
  const resolvedInput = await resolvePackageSource(source, targetRoot);
20780
21277
  const selectedArtifacts = selectedArtifactsFromOptionsOrRegistry(options, resolvedInput.registryEntry);
20781
21278
  const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
20782
- const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join59(targetRoot, ".agentwheel", "cache") }))));
21279
+ const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join61(targetRoot, ".agentwheel", "cache") }))));
20783
21280
  try {
20784
21281
  const artifacts = filterArtifactsBySelection(await driver.list(resolved), selectedArtifacts);
20785
21282
  for (const artifact of artifacts) {
@@ -20848,7 +21345,7 @@ program.command("try").description("read and validate one skill for the current
20848
21345
  const resolvedInput = await resolvePackageSource(source, targetRoot);
20849
21346
  const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
20850
21347
  const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, {
20851
- cacheRoot: join59(targetRoot, ".agentwheel", "cache")
21348
+ cacheRoot: join61(targetRoot, ".agentwheel", "cache")
20852
21349
  }))));
20853
21350
  try {
20854
21351
  const trial = await createSkillTrial(driver, resolved, selectedArtifactsFromOptionsOrRegistry(options, resolvedInput.registryEntry));
@@ -20870,7 +21367,7 @@ program.command("scan").description("scan a package source for validation findin
20870
21367
  const targetRoot = await workspaceContextRootFromOptions(normalizeRuntimeScopeOptions(options));
20871
21368
  const resolvedInput = await resolvePackageSource(source, targetRoot);
20872
21369
  const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
20873
- const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join59(targetRoot, ".agentwheel", "cache") }))));
21370
+ const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join61(targetRoot, ".agentwheel", "cache") }))));
20874
21371
  try {
20875
21372
  const result = await driver.scan(resolved);
20876
21373
  if (result.findings.length === 0) {
@@ -20885,10 +21382,10 @@ program.command("scan").description("scan a package source for validation findin
20885
21382
  await releaseGitSnapshotLease(resolved.cacheLeasePath);
20886
21383
  }
20887
21384
  });
20888
- program.command("plan").description("preview what install would reconcile without writing").argument("[name-or-source]", "configured package name/source or package source to preview").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter or comma-separated adapters").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--all-detected", "run for every runtime directory detected in the target root", false).option("--profile <name>", "workspace runtime profile").option("--mode <mode>", "pinned or tracking").option("--select <type/name>", "select an artifact by type/name (repeatable or comma-separated)", collectSelectOption, []).option("--skill <name>", "select a skill by name (repeatable or comma-separated)", collectSkillOption, []).option("--with-suggestions", "include suggested companion artifacts for selected roots", false).option("--suggestion <alias>", "include one suggested companion alias (repeatable or comma-separated)", collectSuggestionOption, []).option("--override <source-or-package::type/name>", "for source previews, allow the source to replace a colliding artifact (repeatable)", collectOverrideOption, []).option("--dry-run", "accepted for symmetry; plan never writes", false).option("--format <fmt>", "output format: human|json|mermaid|html", "human").option("--json", "print the resolved plan as JSON", false).option("--force-drift", "replace drifted managed artifacts during install planning", false).option("--force-foreign-state", "plan even when another workspace owns install state at the same paths", false).option("--force-conflict", "adopt unmanaged destinations when their content already matches the desired artifact", false).option("--replace-conflict", "replace unmanaged destinations even when their content differs", false).option("--recover-legacy-state", "build a stable state while preserving invalid legacy candidates", false).option("--no-deps", "resolve only root sources and ignore requires with a warning").option("--only-source", "exclude unrelated configured workspace packages", false).option("--frozen-lock", "resolve strictly from the existing graph lock and cached sources", false).option("--offline", "resolve strictly from graph locks and local caches", false).option("--refresh", "refresh available package versions even when the version-index TTL is fresh", false).option("--yes", "trust all new transitive sources", false).option("--trust <pattern>", "pre-approve a transitive source glob (repeatable)", collectTrustOption, []).action(async (source, options) => {
21385
+ program.command("plan").description("preview what install would reconcile without writing").argument("[name-or-source]", "configured package name/source or package source to preview").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter or comma-separated adapters").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--all-detected", "run for every runtime directory detected in the target root", false).option("--profile <name>", "workspace runtime profile").option("--mode <mode>", "pinned or tracking").option("--select <type/name>", "select an artifact by type/name (repeatable or comma-separated)", collectSelectOption, []).option("--skill <name>", "select a skill by name (repeatable or comma-separated)", collectSkillOption, []).option("--with-suggestions", "include suggested companion artifacts for selected roots", false).option("--suggestion <alias>", "include one suggested companion alias (repeatable or comma-separated)", collectSuggestionOption, []).option("--override <source-or-package::type/name>", "for source previews, allow the source to replace a colliding artifact (repeatable)", collectOverrideOption, []).option("--dry-run", "accepted for symmetry; plan never writes", false).option("--adopt", "adopt unmanaged destinations; managed drift and foreign ownership remain protected", false).option("--format <fmt>", "output format: human|json|mermaid|html", "human").option("--json", "print the resolved plan as JSON", false).option("--force-drift", "replace drifted managed artifacts during install planning", false).option("--force-foreign-state", "plan even when another workspace owns install state at the same paths", false).option("--force-conflict", "adopt unmanaged destinations when their content already matches the desired artifact", false).option("--replace-conflict", "replace unmanaged destinations even when their content differs", false).option("--recover-legacy-state", "build a stable state while preserving invalid legacy candidates", false).option("--no-deps", "resolve only root sources and ignore requires with a warning").option("--only-source", "exclude unrelated configured workspace packages", false).option("--frozen-lock", "resolve strictly from the existing graph lock and cached sources", false).option("--offline", "resolve strictly from graph locks and local caches", false).option("--refresh", "refresh available package versions even when the version-index TTL is fresh", false).option("--yes", "trust all new transitive sources", false).option("--trust <pattern>", "pre-approve a transitive source glob (repeatable)", collectTrustOption, []).action(async (source, options) => {
20889
21386
  await runInstallCommand(source, { ...options, dryRun: true }, { apply: false });
20890
21387
  });
20891
- program.command("install").description("install configured packages into runtime targets").argument("[name-or-source]", "configured package name/source or package source to add and install").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter or comma-separated adapters").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--all-detected", "run for every runtime directory detected in the target root", false).option("--mode <mode>", "pinned or tracking").option("--select <type/name>", "select an artifact by type/name (repeatable or comma-separated)", collectSelectOption, []).option("--skill <name>", "select a skill by name (repeatable or comma-separated)", collectSkillOption, []).option("--with-suggestions", "include suggested companion artifacts for selected roots", false).option("--suggestion <alias>", "include one suggested companion alias (repeatable or comma-separated)", collectSuggestionOption, []).option("--override <source-or-package::type/name>", "when adding a source, allow it to replace a colliding artifact (repeatable)", collectOverrideOption, []).option("--profile <name>", "workspace runtime profile").option("--dry-run", "show plan without writing", false).option("--format <fmt>", "output format: human|json|mermaid|html", "human").option("--json", "print the resolved plan as JSON", false).option("--force-drift", "replace drifted managed artifacts", false).option("--force-foreign-state", "plan even when another workspace owns install state at the same paths", false).option("--force-conflict", "adopt unmanaged destinations when their content already matches the desired artifact", false).option("--replace-conflict", "replace unmanaged destinations even when their content differs", false).option("--recover-legacy-state", "build a stable state while preserving invalid legacy candidates", false).option("--execute-plugins", "execute semantic plugin installs", false).option("--reload-runtimes", "run configured runtime reload commands after executed semantic plugin changes", false).option("--restart-runtimes", "alias for --reload-runtimes", false).option("--no-deps", "resolve only root sources and ignore requires with a warning").option("--only-source", "exclude unrelated configured workspace packages", false).option("--frozen-lock", "resolve strictly from the existing graph lock and cached sources", false).option("--offline", "resolve strictly from graph locks and local caches", false).option("--refresh", "refresh available package versions even when the version-index TTL is fresh", false).option("--yes", "trust all new transitive sources", false).option("--trust <pattern>", "pre-approve a transitive source glob (repeatable)", collectTrustOption, []).addHelpText("after", "\nScoped install never removes files owned only by other configured packages; run a full install to reconcile those removals.\n").action(async (source, options) => {
21388
+ program.command("install").description("install configured packages into runtime targets").argument("[name-or-source]", "configured package name/source or package source to add and install").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter or comma-separated adapters").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--all-detected", "run for every runtime directory detected in the target root", false).option("--mode <mode>", "pinned or tracking").option("--select <type/name>", "select an artifact by type/name (repeatable or comma-separated)", collectSelectOption, []).option("--skill <name>", "select a skill by name (repeatable or comma-separated)", collectSkillOption, []).option("--with-suggestions", "include suggested companion artifacts for selected roots", false).option("--suggestion <alias>", "include one suggested companion alias (repeatable or comma-separated)", collectSuggestionOption, []).option("--override <source-or-package::type/name>", "when adding a source, allow it to replace a colliding artifact (repeatable)", collectOverrideOption, []).option("--profile <name>", "workspace runtime profile").option("--dry-run", "show plan without writing", false).option("--adopt", "adopt unmanaged destinations; managed drift and foreign ownership remain protected", false).option("--format <fmt>", "output format: human|json|mermaid|html", "human").option("--json", "print the resolved plan as JSON", false).option("--force-drift", "replace drifted managed artifacts", false).option("--force-foreign-state", "plan even when another workspace owns install state at the same paths", false).option("--force-conflict", "adopt unmanaged destinations when their content already matches the desired artifact", false).option("--replace-conflict", "replace unmanaged destinations even when their content differs", false).option("--recover-legacy-state", "build a stable state while preserving invalid legacy candidates", false).option("--execute-plugins", "execute semantic plugin installs", false).option("--reload-runtimes", "run configured runtime reload commands after executed semantic plugin changes", false).option("--restart-runtimes", "alias for --reload-runtimes", false).option("--no-deps", "resolve only root sources and ignore requires with a warning").option("--only-source", "exclude unrelated configured workspace packages", false).option("--frozen-lock", "resolve strictly from the existing graph lock and cached sources", false).option("--offline", "resolve strictly from graph locks and local caches", false).option("--refresh", "refresh available package versions even when the version-index TTL is fresh", false).option("--yes", "trust all new transitive sources", false).option("--trust <pattern>", "pre-approve a transitive source glob (repeatable)", collectTrustOption, []).addHelpText("after", "\nScoped install never removes files owned only by other configured packages; run a full install to reconcile those removals.\n").action(async (source, options) => {
20892
21389
  await runInstallCommand(source, options, { apply: !options.dryRun });
20893
21390
  });
20894
21391
  program.command("serve").description("serve a read-only live dashboard for the resolved install plan").argument("[name-or-source]", "configured package name/source or package source to preview").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter or comma-separated adapters").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--all-detected", "run for every runtime directory detected in the target root", false).option("--profile <name>", "workspace runtime profile").option("--mode <mode>", "pinned or tracking").option("--select <type/name>", "select an artifact by type/name (repeatable or comma-separated)", collectSelectOption, []).option("--skill <name>", "select a skill by name (repeatable or comma-separated)", collectSkillOption, []).option("--with-suggestions", "include suggested companion artifacts for selected roots", false).option("--suggestion <alias>", "include one suggested companion alias (repeatable or comma-separated)", collectSuggestionOption, []).option("--override <source-or-package::type/name>", "for source previews, allow the source to replace a colliding artifact (repeatable)", collectOverrideOption, []).option("--force-drift", "replace drifted managed artifacts during install planning", false).option("--force-foreign-state", "plan even when another workspace owns install state at the same paths", false).option("--force-conflict", "adopt unmanaged destinations when their content already matches the desired artifact", false).option("--replace-conflict", "replace unmanaged destinations even when their content differs", false).option("--no-deps", "resolve only root sources and ignore requires with a warning").option("--only-source", "exclude unrelated configured workspace packages", false).option("--frozen-lock", "resolve strictly from the existing graph lock and cached sources", false).option("--offline", "resolve strictly from graph locks and local caches", false).option("--refresh", "refresh available package versions even when the version-index TTL is fresh", false).option("--yes", "trust all new transitive sources", false).option("--trust <pattern>", "pre-approve a transitive source glob (repeatable)", collectTrustOption, []).option("--bind <addr>", "interface to bind", "127.0.0.1").option("--port <n>", "TCP port (0 selects an ephemeral port)", "8765").option("--interval <seconds>", "background re-render cadence in seconds", "60").option("--once", "render once and skip the background re-render loop", false).action(async (source, options) => {
@@ -21051,6 +21548,48 @@ program.command("remember").description("append text to the local instructions o
21051
21548
  console.log(nextInstallNudge());
21052
21549
  });
21053
21550
  var ownershipCommand = program.command("ownership").description("inspect and transfer manifest ownership without rewriting runtime artifacts");
21551
+ ownershipCommand.command("release-claim").description("release one exact plain ownership claim while preserving runtime bytes and package declarations").argument("<selector>", "exact artifact selector in type/name form").requiredOption("--path <relative-path>", "exact owned runtime path from the install manifest").requiredOption("--state-key <key>", "exact source install-manifest state key").requiredOption("--from-workspace-root <path>", "exact current workspace owner root").option("--from-fleet-id <id>", "qualify the recorded owner with its Fleet id").option("--fleet <id>", "governing registered Fleet workspace").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--adapter <adapter>", "built-in adapter").option("--adapter-config <path>", "adapter JSON/JSONC file").option("-i, --installation-type <type>", "exact installation type").option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "configured agent resolving to one local target").option("--profile <name>", "profile resolving to one local target").option("--plan-digest <sha256>", "reviewed plan digest; required with --apply").option("--expected-source-revision <sha256>", "reviewed source manifest revision; required with --apply").option("--expected-inventory-revision <sha256>", "reviewed manifest inventory revision; required with --apply").option("--apply", "apply the exact reviewed metadata-only release", false).option("--json", "print the complete plan or result as JSON", false).action(async (selector, _options, command) => {
21552
+ const options = command.optsWithGlobals();
21553
+ if (!options.reason) throw new Error("Ownership release requires --reason <why> for planning and applying.");
21554
+ const normalized = normalizeRuntimeScopeOptions(options);
21555
+ const targets = await resolveCliTargets(normalized);
21556
+ if (targets.length !== 1) throw new Error("Ownership release requires exactly one target.");
21557
+ const target = targets[0];
21558
+ const adapterOptions = adapterOptionsForTarget(target, normalized);
21559
+ const adapter = await resolveAdapterForTarget(target, adapterOptions);
21560
+ const installationType = normalized.installationType ?? target.installationType ?? resolveInstallationTypeForAdapter(adapter);
21561
+ const state = installStateForTarget(target, adapter, adapterOptions, installationType);
21562
+ const request = {
21563
+ workspaceRoot: await workspaceRootFromOptions(normalized),
21564
+ fromWorkspaceRoot: normalizeCliPath(options.fromWorkspaceRoot),
21565
+ fromFleetId: options.fromFleetId,
21566
+ targetRoot: state.installRoot,
21567
+ adapter: adapter.name,
21568
+ installationType,
21569
+ stateKey: options.stateKey,
21570
+ selector,
21571
+ path: options.path,
21572
+ reason: options.reason,
21573
+ planDigest: options.planDigest,
21574
+ expectedSourceRevision: options.expectedSourceRevision,
21575
+ expectedInventoryRevision: options.expectedInventoryRevision,
21576
+ operationId: options.operationId,
21577
+ noCommit: options.commit === false,
21578
+ transport: transportForTarget(target)
21579
+ };
21580
+ const result = options.apply ? await applyReleaseOwnership(request) : await planReleaseOwnership(request);
21581
+ if (options.json) {
21582
+ console.log(JSON.stringify(result, null, 2));
21583
+ return;
21584
+ }
21585
+ console.log(`${options.apply ? "Released ownership claim" : "Ownership release plan"}: ${result.selector} at ${result.path}`);
21586
+ console.log(`Owner: ${result.owner}`);
21587
+ console.log(`Source: ${result.source.stateKey} revision ${result.source.revision}`);
21588
+ console.log(`Recorded hash: ${result.recordedHash}; actual runtime hash: ${result.runtimeHash}`);
21589
+ console.log(`Inventory revision: ${result.manifestInventoryRevision}`);
21590
+ console.log(`Plan digest: ${result.planDigest}`);
21591
+ if (!options.apply) console.log("Apply with this same scope and reason plus --apply --plan-digest, --expected-source-revision and --expected-inventory-revision from this plan.");
21592
+ });
21054
21593
  ownershipCommand.command("handoff").description("transfer one managed artifact between Agentwheel workspace roots").argument("<selector>", "exact artifact selector in type/name form").option("--from-workspace-root <path>", "current owning workspace root").option("--from-unknown-owner", "hand off an artifact recorded as workspace:unknown", false).requiredOption("--to-workspace-root <path>", "new owning workspace root").option("--to-fleet <id>", "qualify the new owner with a registered fleet id").option("--expected-hash <sha256>", "expected recorded artifact hash; required when applying").option("--expected-revision <sha256>", "expected install manifest revision; required when applying").option("--carry-drift", "accept a file or directory whose runtime differs from the recorded hash; the recorded hash is kept", false).option("--expected-runtime-hash <sha256>", "expected drifted runtime hash; required when applying with --carry-drift").option("--adapter <adapter>", "built-in adapter").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--profile <name>", "workspace runtime profile (must resolve to one target)").option("--dry-run", "validate all preconditions without writing the manifest", false).action(async (selector, options) => {
21055
21594
  if (!options.dryRun && (!options.expectedHash || !options.expectedRevision)) {
21056
21595
  throw new Error("Applying an ownership handoff requires --expected-hash and --expected-revision from a reviewed --dry-run.");
@@ -21078,7 +21617,7 @@ ownershipCommand.command("handoff").description("transfer one managed artifact b
21078
21617
  const toWorkspaceRoot = normalizeCliPath(options.toWorkspaceRoot);
21079
21618
  if (options.toFleet) {
21080
21619
  const fleet = await showRegisteredFleet(options.toFleet);
21081
- if (resolve43(fleet.root) !== resolve43(toWorkspaceRoot)) {
21620
+ if (resolve44(fleet.root) !== resolve44(toWorkspaceRoot)) {
21082
21621
  throw new Error(`Destination fleet '${options.toFleet}' is registered at ${fleet.root}, not ${toWorkspaceRoot}.`);
21083
21622
  }
21084
21623
  }
@@ -21119,8 +21658,8 @@ ownershipCommand.command("recovery-plan").description("write a read-only per-pat
21119
21658
  const adapter = await resolveAdapterForTarget(target, {});
21120
21659
  const transport = transportForTarget(target);
21121
21660
  const requestedReport = normalizeCliPath(options.report);
21122
- const reportPath = join59(await realpath4(dirname37(requestedReport)), basename24(requestedReport));
21123
- const reportInsideTarget = relative18(resolve43(target.targetRoot), reportPath);
21661
+ const reportPath = join61(await realpath4(dirname37(requestedReport)), basename24(requestedReport));
21662
+ const reportInsideTarget = relative19(resolve44(target.targetRoot), reportPath);
21124
21663
  if (reportInsideTarget === "" || !reportInsideTarget.startsWith("..") && !isAbsolute14(reportInsideTarget)) {
21125
21664
  throw new Error("Recovery report must be outside the runtime target root.");
21126
21665
  }
@@ -21151,7 +21690,7 @@ ownershipCommand.command("retire-stale").description("retire stale source-manife
21151
21690
  const normalizedOptions = normalizeRuntimeScopeOptions(options);
21152
21691
  const fleet = await showRegisteredFleet(options.fleet);
21153
21692
  const toWorkspaceRoot = normalizeCliPath(options.toWorkspaceRoot);
21154
- if (resolve43(fleet.root) !== resolve43(toWorkspaceRoot)) {
21693
+ if (resolve44(fleet.root) !== resolve44(toWorkspaceRoot)) {
21155
21694
  throw new Error(`Destination Fleet '${options.fleet}' is registered at ${fleet.root}, not ${toWorkspaceRoot}.`);
21156
21695
  }
21157
21696
  const targets = await resolveCliTargets(normalizedOptions);
@@ -21159,7 +21698,7 @@ ownershipCommand.command("retire-stale").description("retire stale source-manife
21159
21698
  throw new Error(`Stale ownership retirement requires exactly one destination Fleet target, found ${targets.length}.`);
21160
21699
  }
21161
21700
  const target = targets[0];
21162
- if (target.fleetId !== options.fleet || resolve43(target.workspaceRoot) !== resolve43(fleet.root)) {
21701
+ if (target.fleetId !== options.fleet || resolve44(target.workspaceRoot) !== resolve44(fleet.root)) {
21163
21702
  throw new Error(`Resolved target does not belong to destination Fleet '${options.fleet}'.`);
21164
21703
  }
21165
21704
  const adapterOptions = adapterOptionsForTarget(target, normalizedOptions);
@@ -21231,7 +21770,7 @@ ownershipCommand.command("retire-stale").description("retire stale source-manife
21231
21770
  console.log(`Plan digest: ${result.planDigest}`);
21232
21771
  if (!options.apply) console.log(`Apply: ${applyCommand}`);
21233
21772
  });
21234
- ownershipCommand.command("adopt-legacy").description("move proven legacy-keyed ownership into this workspace's stable target state without rewriting runtime artifacts").requiredOption("--source-state-key <key>", "exact legacy install-manifest state key").requiredOption("--from-workspace-root <path>", "exact plain workspace owner root of the entries to move").option("--agent <name>", "named agent of this workspace").option("--profile <name>", "workspace profile resolving to one target").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--carry-drift", "also move entries whose runtime differs from the recorded hash; the recorded hash is kept", false).option("--plan-digest <sha256>", "reviewed plan digest; required with --apply").option("--expected-source-revision <sha256>", "reviewed source manifest revision; required with --apply").option("--expected-destination-revision <sha256|absent>", "reviewed destination manifest revision; required with --apply").option("--expected-inventory-revision <sha256>", "reviewed runtime manifest inventory revision; required with --apply").option("--apply", "apply the exact reviewed metadata-only adoption", false).option("--json", "print the complete deterministic plan as JSON", false).action(async (options) => {
21773
+ ownershipCommand.command("adopt-legacy").description("move proven legacy-keyed ownership into this workspace's stable target state without rewriting runtime artifacts").requiredOption("--source-state-key <key>", "exact legacy install-manifest state key").requiredOption("--from-workspace-root <path>", "exact plain workspace owner root of the entries to move").option("--agent <name>", "named agent of this workspace").option("--profile <name>", "workspace profile resolving to one target").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--carry-drift", "also move drifted plain entries while keeping the recorded hash; forbidden for managed blocks", false).option("--plan-digest <sha256>", "reviewed plan digest; required with --apply").option("--expected-source-revision <sha256>", "reviewed source manifest revision; required with --apply").option("--expected-destination-revision <sha256|absent>", "reviewed destination manifest revision; required with --apply").option("--expected-inventory-revision <sha256>", "reviewed runtime manifest inventory revision; required with --apply").option("--apply", "apply the exact reviewed metadata-only adoption", false).option("--json", "print the complete deterministic plan as JSON", false).action(async (options) => {
21235
21774
  if (Boolean(options.agent) === Boolean(options.profile)) {
21236
21775
  throw new Error("Legacy ownership adoption requires exactly one of --agent or --profile.");
21237
21776
  }
@@ -21281,7 +21820,7 @@ ownershipCommand.command("adopt-legacy").description("move proven legacy-keyed o
21281
21820
  ];
21282
21821
  for (const { flag, requested, resolved, none } of requestedAdapterSettings) {
21283
21822
  if (requested === void 0) continue;
21284
- if (resolved !== void 0 && resolve43(target.workspaceRoot, requested) === resolve43(target.workspaceRoot, resolved)) continue;
21823
+ if (resolved !== void 0 && resolve44(target.workspaceRoot, requested) === resolve44(target.workspaceRoot, resolved)) continue;
21285
21824
  throw new Error(`${flag} ${requested} does not match what install resolves for the configured packages: ${resolved ?? none}.`);
21286
21825
  }
21287
21826
  const adapter = await resolveAdapterForTarget(group.target, adapterOptions);
@@ -21451,7 +21990,7 @@ journalCommand.command("list").description("show pending apply journals for reso
21451
21990
  if (!journal) continue;
21452
21991
  pending += 1;
21453
21992
  console.log(`PENDING ${state.adapter.name}/${state.installationType} at ${state.installRoot}`);
21454
- console.log(` journal: ${join59(state.installRoot, ".agentwheel", `${state.state.stateKey}.apply-journal.json`)}`);
21993
+ console.log(` journal: ${join61(state.installRoot, ".agentwheel", `${state.state.stateKey}.apply-journal.json`)}`);
21455
21994
  console.log(` stateKey: ${state.state.stateKey}`);
21456
21995
  console.log(` createdAt: ${journal.createdAt}`);
21457
21996
  console.log(` updatedAt: ${journal.updatedAt}`);
@@ -21515,7 +22054,11 @@ program.command("doctor").description("check agentwheel runtime setup and compan
21515
22054
  await printDoctor(targets[0], normalizedOptions);
21516
22055
  });
21517
22056
  async function runInstallCommand(nameOrSource, options, behavior) {
21518
- const normalizedOptions = normalizeRuntimeScopeOptions(options, { defaultUser: shouldDefaultUserInstall(nameOrSource, options) });
22057
+ const normalizedOptions = normalizeRuntimeScopeOptions({
22058
+ ...options,
22059
+ forceConflict: options.forceConflict || options.adopt,
22060
+ replaceConflict: options.replaceConflict || options.adopt
22061
+ }, { defaultUser: shouldDefaultUserInstall(nameOrSource, options) });
21519
22062
  const outputFormat = effectivePlanOutputFormat(normalizedOptions);
21520
22063
  const composite = await resolveSelectedCompositeProfile(normalizedOptions);
21521
22064
  if (composite) {
@@ -21797,14 +22340,14 @@ async function packageEntryFromSource(source, targetRoot, options) {
21797
22340
  );
21798
22341
  }
21799
22342
  const bundle = options.deferGraphRendering ? await stageSourceRaw(driver, resolvedSource, {
21800
- cacheRoot: join59(targetRoot, ".agentwheel", "cache"),
22343
+ cacheRoot: join61(targetRoot, ".agentwheel", "cache"),
21801
22344
  mode: options.mode,
21802
22345
  ref: initialVersion?.ref,
21803
22346
  frozenLock: lockMode
21804
22347
  }) : await stageSource(driver, resolvedSource, {
21805
22348
  workspaceRoot: targetRoot,
21806
22349
  adapter,
21807
- cacheRoot: join59(targetRoot, ".agentwheel", "cache"),
22350
+ cacheRoot: join61(targetRoot, ".agentwheel", "cache"),
21808
22351
  mode: options.mode,
21809
22352
  ref: initialVersion?.ref,
21810
22353
  frozenLock: lockMode,
@@ -22412,7 +22955,7 @@ function scopeUpdatePlanToDependencies(result, selectors, previousLock, manifest
22412
22955
  selectedPreviousNodeIds,
22413
22956
  selectedRootIds
22414
22957
  );
22415
- const graphLockDigest = createHash27("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
22958
+ const graphLockDigest = createHash28("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
22416
22959
  return {
22417
22960
  ...result,
22418
22961
  bundle: { ...result.bundle, graphLock },
@@ -22538,7 +23081,7 @@ function operationBelongsToDependencyUpdate(operation, allowedNodeIds, allowedNa
22538
23081
  function scopeInstallPlanToArtifact(result, rootId, focused, manifest) {
22539
23082
  const scoped = scopePlanOperationsToArtifact(result, rootId, focused, manifest);
22540
23083
  const graphLock = focusedGraphLockForInstall(scoped.bundle.graphLock, rootId, focused);
22541
- const graphLockDigest = createHash27("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
23084
+ const graphLockDigest = createHash28("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
22542
23085
  return {
22543
23086
  ...scoped,
22544
23087
  bundle: { ...scoped.bundle, graphLock },
@@ -22549,7 +23092,7 @@ function scopeInstallPlanToArtifact(result, rootId, focused, manifest) {
22549
23092
  function scopeUpdatePlanToArtifact(result, rootId, focused, previousLock, manifest) {
22550
23093
  const scoped = scopePlanOperationsToArtifact(result, rootId, focused, manifest, previousLock);
22551
23094
  const graphLock = mergeFocusedArtifactGraphLock(scoped.bundle.graphLock, previousLock, rootId, focused);
22552
- const graphLockDigest = createHash27("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
23095
+ const graphLockDigest = createHash28("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
22553
23096
  return {
22554
23097
  ...scoped,
22555
23098
  bundle: { ...scoped.bundle, graphLock },
@@ -22844,7 +23387,7 @@ function scopeUpdatePlanToRoot(result, rootId, previousLock, manifest) {
22844
23387
  selectedPreviousNodeIds,
22845
23388
  /* @__PURE__ */ new Set([rootId])
22846
23389
  );
22847
- const graphLockDigest = createHash27("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
23390
+ const graphLockDigest = createHash28("sha256").update(canonicalGraphLockJson(graphLock)).digest("hex");
22848
23391
  return {
22849
23392
  ...scoped,
22850
23393
  bundle: { ...scoped.bundle, graphLock },
@@ -22916,7 +23459,7 @@ function keepManifestEntryOperation(entry, targetRoot, scopeDescription, operati
22916
23459
  artifactType: entry.artifactType,
22917
23460
  artifactName: entry.artifactName,
22918
23461
  kind: entry.kind,
22919
- destPath: operation?.destPath ?? join59(targetRoot, entry.path),
23462
+ destPath: operation?.destPath ?? join61(targetRoot, entry.path),
22920
23463
  relativeDestPath: entry.path,
22921
23464
  desiredHash: entry.sourceHash,
22922
23465
  currentHash: operation?.currentHash ?? entry.hash,
@@ -23117,7 +23660,7 @@ function installRootContextForTarget(target) {
23117
23660
  return { kind: target.transport, homeRoot: target.runAs?.home };
23118
23661
  }
23119
23662
  async function withFreshReadOnlyGraphPlan(target, adapter, adapterOptions, installationType, packages, use) {
23120
- const stage = await mkdtemp6(join59(tmpdir7(), "agentwheel-recovery-"));
23663
+ const stage = await mkdtemp6(join61(tmpdir7(), "agentwheel-recovery-"));
23121
23664
  const priorTmpdir = process.env.TMPDIR;
23122
23665
  try {
23123
23666
  process.env.TMPDIR = stage;
@@ -23149,8 +23692,8 @@ async function withFreshReadOnlyGraphPlan(target, adapter, adapterOptions, insta
23149
23692
  yes: true,
23150
23693
  freshGraphOnly: true,
23151
23694
  deferForeignStateCheck: true,
23152
- cacheRoot: join59(stage, "source-cache"),
23153
- registryCachePath: join59(stage, "registry.json")
23695
+ cacheRoot: join61(stage, "source-cache"),
23696
+ registryCachePath: join61(stage, "registry.json")
23154
23697
  });
23155
23698
  return await use(graphPlan);
23156
23699
  } finally {
@@ -23237,7 +23780,7 @@ async function resolveCliTargetState(target, options) {
23237
23780
  migration: prior.migration,
23238
23781
  targetStateFilePreconditions: {
23239
23782
  graphLockPath: stableGraphLockPath,
23240
- graphLockRevision: stableLock ? createHash27("sha256").update(canonicalGraphLockJson(stableLock)).digest("hex") : null,
23783
+ graphLockRevision: stableLock ? createHash28("sha256").update(canonicalGraphLockJson(stableLock)).digest("hex") : null,
23241
23784
  sourceLockRevision: computeSourceLockRevision(stableSourceLock)
23242
23785
  }
23243
23786
  };
@@ -23260,7 +23803,7 @@ async function collectTargetStatus(target, options) {
23260
23803
  const pending = await collectPendingInstallWork(target, options);
23261
23804
  const foreignObservations = pending.foreignStateObservations;
23262
23805
  const effectiveGraphLock = graphLock ?? pending.observedGraphLock;
23263
- const observedManifestRevision = foreignObservations.length > 0 ? createHash27("sha256").update(JSON.stringify(foreignObservations.map((observation) => [
23806
+ const observedManifestRevision = foreignObservations.length > 0 ? createHash28("sha256").update(JSON.stringify(foreignObservations.map((observation) => [
23264
23807
  observation.fileName,
23265
23808
  observation.manifestRevision
23266
23809
  ]).sort())).digest("hex") : null;
@@ -23507,7 +24050,7 @@ async function assertCompositeMutationSupported(workspaceRoot, profile, readOnly
23507
24050
  `Composite-profile mutation is refused before member execution because ${member.id} uses ${member.transport}; durable remote policy and recovery preflight is not implemented.`
23508
24051
  );
23509
24052
  }
23510
- const memberRoot = resolve43(workspaceRoot, member.workspace);
24053
+ const memberRoot = resolve44(workspaceRoot, member.workspace);
23511
24054
  const memberPolicy = await mutationPolicyForWorkspace(memberRoot);
23512
24055
  if (memberPolicy?.revisioning.mode === "commit-after-verify") {
23513
24056
  throw new Error(
@@ -23744,12 +24287,12 @@ async function printDoctor(target, options) {
23744
24287
  const requestedSkills = doctorSkillRequests(target, options);
23745
24288
  const skills = [];
23746
24289
  for (const request of requestedSkills) {
23747
- const skillPath = join59(state.installRoot, targetMapping.dest, request.name);
24290
+ const skillPath = join61(state.installRoot, targetMapping.dest, request.name);
23748
24291
  const exists2 = await pathExists(skillPath);
23749
24292
  const manifestEntry = manifest?.entries.find((entry) => {
23750
24293
  if (entry.artifactType !== "skills") return false;
23751
24294
  const legacyInstallName = "installName" in entry && typeof entry.installName === "string" ? entry.installName : void 0;
23752
- return entry.artifactName === request.name || legacyInstallName === request.name || entry.path === join59(targetMapping.dest, request.name);
24295
+ return entry.artifactName === request.name || legacyInstallName === request.name || entry.path === join61(targetMapping.dest, request.name);
23753
24296
  });
23754
24297
  const status = manifestEntry ? "managed" : exists2 ? "present-unmanaged" : "missing";
23755
24298
  skills.push({
@@ -23829,7 +24372,7 @@ function doctorSkillLabel(name) {
23829
24372
  return `${name} skill`;
23830
24373
  }
23831
24374
  function isSyncwheelWorkspace(targetRoot) {
23832
- return existsSync(join59(targetRoot, ".syncwheel", "manifest.json"));
24375
+ return existsSync(join61(targetRoot, ".syncwheel", "manifest.json"));
23833
24376
  }
23834
24377
  function skillInstallCommand(adapter, installationType, options, skill, behavior = {}) {
23835
24378
  const args = [
@@ -23992,14 +24535,14 @@ function looksLikeSourceSpecifier(value) {
23992
24535
  }
23993
24536
  function normalizeCliPath(value) {
23994
24537
  if (value === "~") return homedir18();
23995
- if (value.startsWith("~/")) return resolve43(homedir18(), value.slice(2));
23996
- return resolve43(value);
24538
+ if (value.startsWith("~/")) return resolve44(homedir18(), value.slice(2));
24539
+ return resolve44(value);
23997
24540
  }
23998
24541
  function shellQuoteArgument(value) {
23999
24542
  return /^[a-z0-9_./:@%+=,-]+$/i.test(value) ? value : `'${value.replace(/'/g, `'"'"'`)}'`;
24000
24543
  }
24001
24544
  function isHomePath(path) {
24002
- return resolve43(path) === resolve43(homedir18());
24545
+ return resolve44(path) === resolve44(homedir18());
24003
24546
  }
24004
24547
  function adapterListFromOption(adapter) {
24005
24548
  if (!adapter) return [];
@@ -24054,11 +24597,11 @@ function filterUninstallPlanBySelection(plan, selected) {
24054
24597
  };
24055
24598
  }
24056
24599
  async function initPackage(root) {
24057
- await mkdir26(join59(root, "instructions"), { recursive: true });
24058
- await mkdir26(join59(root, "rules"), { recursive: true });
24059
- await mkdir26(join59(root, "skills"), { recursive: true });
24060
- const manifestPath = join59(root, "openpack.json");
24061
- const instructionsPath = join59(root, "instructions", "AGENTS.md");
24600
+ await mkdir27(join61(root, "instructions"), { recursive: true });
24601
+ await mkdir27(join61(root, "rules"), { recursive: true });
24602
+ await mkdir27(join61(root, "skills"), { recursive: true });
24603
+ const manifestPath = join61(root, "openpack.json");
24604
+ const instructionsPath = join61(root, "instructions", "AGENTS.md");
24062
24605
  const manifest = {
24063
24606
  schemaVersion: CURRENT_OPENPACK_SCHEMA_VERSION,
24064
24607
  name: "example/agentwheel-package",
@@ -24120,7 +24663,7 @@ function withFleetExample(config) {
24120
24663
  };
24121
24664
  }
24122
24665
  async function findAgentwheelPackageRoot(start) {
24123
- let current = resolve43(start);
24666
+ let current = resolve44(start);
24124
24667
  while (true) {
24125
24668
  if (await findPackageManifestPath(current, { warnLegacy: false })) return current;
24126
24669
  const parent = dirname37(current);
@@ -24248,14 +24791,14 @@ async function governedCommandContext(command, options) {
24248
24791
  const kind = String(command.args[0] ?? "workspace");
24249
24792
  return {
24250
24793
  workspaceRoot: workspaceRoot2,
24251
- anticipatedPaths: kind === "package" ? [join59(targetRoot, "openpack.json"), join59(targetRoot, "instructions", "AGENTS.md")] : [workspaceConfigPath(targetRoot)]
24794
+ anticipatedPaths: kind === "package" ? [join61(targetRoot, "openpack.json"), join61(targetRoot, "instructions", "AGENTS.md")] : [workspaceConfigPath(targetRoot)]
24252
24795
  };
24253
24796
  }
24254
24797
  if (path === "package migrate") {
24255
24798
  const packageRoot = normalizeTargetRoot(String(command.args[0] ?? "."));
24256
24799
  return {
24257
24800
  workspaceRoot: await findExistingWorkspaceRoot(packageRoot) ?? packageRoot,
24258
- anticipatedPaths: ["agentwheel.json", "agentwheel.jsonc", "openpack.json", "openpack.jsonc"].map((name) => join59(packageRoot, name))
24801
+ anticipatedPaths: ["agentwheel.json", "agentwheel.jsonc", "openpack.json", "openpack.jsonc"].map((name) => join61(packageRoot, name))
24259
24802
  };
24260
24803
  }
24261
24804
  const source = typeof command.args[0] === "string" ? command.args[0] : void 0;
@@ -24267,7 +24810,7 @@ async function governedCommandContext(command, options) {
24267
24810
  const anticipatedPaths = [];
24268
24811
  if (path === "add") anticipatedPaths.push(workspaceConfigPath(workspaceRoot));
24269
24812
  if (path === "remember" && options.runtime) {
24270
- anticipatedPaths.push(join59(workspaceRoot, ".agentwheel", "overlays", options.runtime, "instructions.local.md"));
24813
+ anticipatedPaths.push(join61(workspaceRoot, ".agentwheel", "overlays", options.runtime, "instructions.local.md"));
24271
24814
  }
24272
24815
  if (path === "uninstall" && source) anticipatedPaths.push(workspaceConfigPath(workspaceRoot));
24273
24816
  return {