@c4a/context-cli 0.7.30 → 0.7.34

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/cli.js CHANGED
@@ -42637,7 +42637,7 @@ function parseDocumentResourceMaterialization(value, field) {
42637
42637
  ...reason !== undefined ? { reason } : {}
42638
42638
  };
42639
42639
  });
42640
- const expectedStatus = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code)) ? "error" : items.some((item) => item.status === "failed") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true) ? "warning" : "complete";
42640
+ const expectedStatus = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code)) ? "error" : items.some((item) => item.status === "failed" || item.reason_code === "document.resource.preview") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true) ? "warning" : "complete";
42641
42641
  if (value.status !== expectedStatus)
42642
42642
  throw new TypeError(`${field}.status must be ${expectedStatus} for its items`);
42643
42643
  const expected = (status) => {
@@ -90705,7 +90705,7 @@ function documentSnapshotFidelityState(manifest, captureReport) {
90705
90705
  ],
90706
90706
  warnings: [
90707
90707
  ...report === undefined ? [] : render((issue) => issue.impact === "projection" || issue.severity === "warning"),
90708
- ...(resources?.items ?? []).filter((item) => item.status === "failed" && (!item.required || isNonBlockingDocumentResourceFailureReasonCode(item.reason_code))).map((item) => `${item.reason_code ?? "lark.capture.resource-materialization-warning"}: ${item.kind}: ${item.reason ?? item.locator}`)
90708
+ ...(resources?.items ?? []).filter((item) => item.reason_code === "document.resource.preview" || item.status === "failed" && (!item.required || isNonBlockingDocumentResourceFailureReasonCode(item.reason_code))).map((item) => `${item.reason_code ?? "lark.capture.resource-materialization-warning"}: ${item.kind}: ${item.reason ?? item.locator}`)
90709
90709
  ]
90710
90710
  };
90711
90711
  }
@@ -97826,32 +97826,6 @@ var init_larkDocxXml = __esm(() => {
97826
97826
  ]);
97827
97827
  });
97828
97828
 
97829
- // src/lib/larkImagePolicy.ts
97830
- function omitLarkImage(resource, policy, items, replacements, mediaType, failure2) {
97831
- if (resource.kind !== "image" && !mediaType?.startsWith("image/"))
97832
- return false;
97833
- const gif = mediaType === "image/gif" || /\.gif$/iu.test(resource.title ?? "") || Object.entries(resource.attributes).some(([key, value]) => ["mime_type", "content_type"].includes(key) && value === "image/gif");
97834
- if (!failure2 && policy.images !== "reference-only" && !(gif && policy.gifs === "reference-only"))
97835
- return false;
97836
- const title2 = (resource.title ?? "image").replace(/[\r\n<>]/gu, " ");
97837
- replacements.set(resource.locator, `> Image omitted: ${title2}. ${failure2 ? "Resource size limit exceeded." : "Excluded by selected policy."} See the source document. <!-- ${resource.locator} -->`);
97838
- items.push({
97839
- kind: resource.kind,
97840
- locator: resource.locator,
97841
- status: "reference-only",
97842
- required: false,
97843
- asset_paths: [],
97844
- reason_code: failure2 ? "image-budget-exceeded" : "image-excluded-by-policy",
97845
- reason: failure2 ?? "Image bytes were not retained; the selected image policy preserves a placeholder and source reference"
97846
- });
97847
- return true;
97848
- }
97849
- var LarkResourceBudgetError;
97850
- var init_larkImagePolicy = __esm(() => {
97851
- LarkResourceBudgetError = class LarkResourceBudgetError extends Error {
97852
- };
97853
- });
97854
-
97855
97829
  // src/lib/larkResourceCommand.ts
97856
97830
  function stableJson(value) {
97857
97831
  if (value === undefined)
@@ -97880,13 +97854,13 @@ function commandError(fallback, detail) {
97880
97854
  if (detail === undefined)
97881
97855
  return new LarkResourceCommandError(fallback);
97882
97856
  const message = [detail.message, detail.hint, detail.code].filter((value) => typeof value === "string" || typeof value === "number").map(String).join("; ");
97883
- return new LarkResourceCommandError(message.length > 0 ? message : stableJson(detail), typeof detail.type === "string" ? detail.type : undefined, typeof detail.subtype === "string" ? detail.subtype : undefined);
97857
+ return new LarkResourceCommandError(message.length > 0 ? message : stableJson(detail), typeof detail.type === "string" ? detail.type : undefined, typeof detail.subtype === "string" ? detail.subtype : undefined, typeof detail.code === "string" || typeof detail.code === "number" ? detail.code : undefined, typeof detail.log_id === "string" ? detail.log_id : undefined);
97884
97858
  }
97885
97859
  async function runLarkResourceCommand(runner2, args, options) {
97886
97860
  const result = await runner2(args, options);
97887
97861
  if (result.exitCode !== 0) {
97888
97862
  const fallback = result.stderr.trim() || `lark-cli ${args.slice(0, 2).join(" ")} failed with exit code ${result.exitCode ?? "unknown"}`;
97889
- throw commandError(fallback, errorDetail(result.stderr));
97863
+ throw commandError(fallback, errorDetail(result.stderr) ?? errorDetail(result.stdout));
97890
97864
  }
97891
97865
  const trimmed = result.stdout.trim();
97892
97866
  if (!trimmed.startsWith("{"))
@@ -97906,24 +97880,78 @@ async function runLarkResourceCommand(runner2, args, options) {
97906
97880
  }
97907
97881
  return result.stdout;
97908
97882
  }
97883
+ function isLarkResourcePermissionDenied(error) {
97884
+ return error instanceof LarkResourceCommandError && (String(error.code) === "403" || error.errorType === "authorization" && ["permission_denied", "access_denied", "missing_scope"].includes(error.errorSubtype ?? ""));
97885
+ }
97909
97886
  var LarkResourceCommandError;
97910
97887
  var init_larkResourceCommand = __esm(() => {
97911
97888
  LarkResourceCommandError = class LarkResourceCommandError extends Error {
97912
97889
  errorType;
97913
97890
  errorSubtype;
97914
- constructor(message, errorType, errorSubtype) {
97891
+ code;
97892
+ logId;
97893
+ constructor(message, errorType, errorSubtype, code3, logId) {
97915
97894
  super(message);
97916
97895
  this.errorType = errorType;
97917
97896
  this.errorSubtype = errorSubtype;
97897
+ this.code = code3;
97898
+ this.logId = logId;
97918
97899
  this.name = "LarkResourceCommandError";
97919
97900
  }
97920
97901
  };
97921
97902
  });
97922
97903
 
97904
+ // src/lib/larkMediaDownload.ts
97905
+ import { readdir as readdir21, rm as rm20 } from "node:fs/promises";
97906
+ import { join as join94 } from "node:path";
97907
+ async function downloadLarkMedia(input) {
97908
+ const shared = ["--as", input.identity, "--token", input.token, "--output", "./resource", "--format", "json"];
97909
+ try {
97910
+ await runLarkResourceCommand(input.runner, ["docs", "+media-download", ...shared, "--type", input.type, "--overwrite"], { cwd: input.cwd });
97911
+ return "original";
97912
+ } catch (error) {
97913
+ if (!input.allowPreview || !isLarkResourcePermissionDenied(error))
97914
+ throw error;
97915
+ for (const entry of await readdir21(input.cwd))
97916
+ await rm20(join94(input.cwd, entry), { recursive: true, force: true });
97917
+ await runLarkResourceCommand(input.runner, ["docs", "+media-preview", ...shared], { cwd: input.cwd });
97918
+ return "preview";
97919
+ }
97920
+ }
97921
+ var init_larkMediaDownload = __esm(() => {
97922
+ init_larkResourceCommand();
97923
+ });
97924
+
97925
+ // src/lib/larkImagePolicy.ts
97926
+ function omitLarkImage(resource, policy, items, replacements, mediaType, failure2) {
97927
+ if (resource.kind !== "image" && !mediaType?.startsWith("image/"))
97928
+ return false;
97929
+ const gif = mediaType === "image/gif" || /\.gif$/iu.test(resource.title ?? "") || Object.entries(resource.attributes).some(([key, value]) => ["mime_type", "content_type"].includes(key) && value === "image/gif");
97930
+ if (!failure2 && policy.images !== "reference-only" && !(gif && policy.gifs === "reference-only"))
97931
+ return false;
97932
+ const title2 = (resource.title ?? "image").replace(/[\r\n<>]/gu, " ");
97933
+ replacements.set(resource.locator, `> Image omitted: ${title2}. ${failure2 ? "Resource size limit exceeded." : "Excluded by selected policy."} See the source document. <!-- ${resource.locator} -->`);
97934
+ items.push({
97935
+ kind: resource.kind,
97936
+ locator: resource.locator,
97937
+ status: "reference-only",
97938
+ required: false,
97939
+ asset_paths: [],
97940
+ reason_code: failure2 ? "image-budget-exceeded" : "image-excluded-by-policy",
97941
+ reason: failure2 ?? "Image bytes were not retained; the selected image policy preserves a placeholder and source reference"
97942
+ });
97943
+ return true;
97944
+ }
97945
+ var LarkResourceBudgetError;
97946
+ var init_larkImagePolicy = __esm(() => {
97947
+ LarkResourceBudgetError = class LarkResourceBudgetError extends Error {
97948
+ };
97949
+ });
97950
+
97923
97951
  // src/lib/larkResourceMaterialization.ts
97924
97952
  import { createHash as createHash28 } from "node:crypto";
97925
- import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as readdir21, rm as rm20 } from "node:fs/promises";
97926
- import { extname as extname13, join as join94 } from "node:path";
97953
+ import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as readdir22, rm as rm21 } from "node:fs/promises";
97954
+ import { extname as extname13, join as join95 } from "node:path";
97927
97955
  import { tmpdir } from "node:os";
97928
97956
  function countByKind(items, status) {
97929
97957
  const counts2 = new Map;
@@ -98029,33 +98057,19 @@ function findBooleanField(value, name3) {
98029
98057
  async function downloadedFile(input) {
98030
98058
  if (input.localPath !== undefined) {
98031
98059
  const bytes = await readFile74(input.localPath);
98032
- return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes) };
98060
+ return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes), representation: "original" };
98033
98061
  }
98034
- const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-resource-"));
98062
+ const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-resource-"));
98035
98063
  try {
98036
- await runLarkResourceCommand(input.runner, [
98037
- "docs",
98038
- "+media-download",
98039
- "--as",
98040
- input.identity,
98041
- "--token",
98042
- input.token,
98043
- "--type",
98044
- input.type,
98045
- "--output",
98046
- "./resource",
98047
- "--overwrite",
98048
- "--format",
98049
- "json"
98050
- ], { cwd: tempRoot });
98051
- const entries2 = (await readdir21(tempRoot, { withFileTypes: true })).filter((entry) => entry.isFile());
98064
+ const representation = await downloadLarkMedia({ ...input, cwd: tempRoot });
98065
+ const entries2 = (await readdir22(tempRoot, { withFileTypes: true })).filter((entry) => entry.isFile());
98052
98066
  if (entries2.length !== 1)
98053
98067
  throw new Error(`media download produced ${entries2.length} files, expected exactly one`);
98054
98068
  const path3 = entries2[0]?.name ?? "resource.bin";
98055
- const bytes = await readFile74(join94(tempRoot, path3));
98056
- return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes) };
98069
+ const bytes = await readFile74(join95(tempRoot, path3));
98070
+ return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes), representation };
98057
98071
  } finally {
98058
- await rm20(tempRoot, { recursive: true, force: true });
98072
+ await rm21(tempRoot, { recursive: true, force: true });
98059
98073
  }
98060
98074
  }
98061
98075
  function parseCsv(value) {
@@ -98143,9 +98157,9 @@ async function sheetMaterialization(resource, runner2, identity2) {
98143
98157
  const sheetId = resource.attributes["sheet-id"];
98144
98158
  if (token === undefined || sheetId === undefined)
98145
98159
  throw new Error("embedded Sheet requires token and sheet-id");
98146
- const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-sheet-"));
98160
+ const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-sheet-"));
98147
98161
  try {
98148
- const outputPath = join94(tempRoot, "sheet.json");
98162
+ const outputPath = join95(tempRoot, "sheet.json");
98149
98163
  const stdout = await runLarkResourceCommand(runner2, [
98150
98164
  "sheets",
98151
98165
  "+csv-get",
@@ -98187,7 +98201,7 @@ ${markdownTable2(parseCsv(csv))}
98187
98201
  [CSV snapshot](${sourceAssetTarget(path3)}) <!-- ${resource.locator} -->`
98188
98202
  };
98189
98203
  } finally {
98190
- await rm20(tempRoot, { recursive: true, force: true });
98204
+ await rm21(tempRoot, { recursive: true, force: true });
98191
98205
  }
98192
98206
  }
98193
98207
  function basePageRecords(value) {
@@ -98301,7 +98315,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
98301
98315
  if (token === undefined)
98302
98316
  throw new Error(`${resource.kind} has no whiteboard token`);
98303
98317
  const preview = await downloadedFile({ runner: runner2, identity: identity2, token, type: "whiteboard" });
98304
- const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-whiteboard-"));
98318
+ const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-whiteboard-"));
98305
98319
  let rawPayload;
98306
98320
  try {
98307
98321
  await runLarkResourceCommand(runner2, [
@@ -98319,9 +98333,9 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
98319
98333
  "--format",
98320
98334
  "json"
98321
98335
  ], { cwd: tempRoot });
98322
- rawPayload = JSON.parse(await readFile74(join94(tempRoot, "raw.json"), "utf8"));
98336
+ rawPayload = JSON.parse(await readFile74(join95(tempRoot, "raw.json"), "utf8"));
98323
98337
  } finally {
98324
- await rm20(tempRoot, { recursive: true, force: true });
98338
+ await rm21(tempRoot, { recursive: true, force: true });
98325
98339
  }
98326
98340
  const digest6 = resourceDigest(resource);
98327
98341
  const previewPath = `materialized/${resource.kind}/${digest6}${extensionFor2(preview.mediaType, preview.path)}`;
@@ -98380,7 +98394,7 @@ function referenceOnlyReason(resource) {
98380
98394
  }
98381
98395
  function materializationReport(items) {
98382
98396
  const hasRequiredFailure = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code));
98383
- const hasOptionalFailure = items.some((item) => item.status === "failed" || item.reason_code === "image-budget-exceeded") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true);
98397
+ const hasOptionalFailure = items.some((item) => item.status === "failed" || item.reason_code === "image-budget-exceeded" || item.reason_code === "document.resource.preview") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true);
98384
98398
  return {
98385
98399
  status: hasRequiredFailure ? "error" : hasOptionalFailure ? "warning" : "complete",
98386
98400
  discovered: countByKind(items),
@@ -98391,7 +98405,7 @@ function materializationReport(items) {
98391
98405
  };
98392
98406
  }
98393
98407
  function resourceFailureReasonCode(resource, error) {
98394
- if (error instanceof LarkResourceCommandError && error.errorType === "authorization" && error.errorSubtype === "permission_denied") {
98408
+ if (isLarkResourcePermissionDenied(error)) {
98395
98409
  return DOCUMENT_RESOURCE_PERMISSION_DENIED_REASON_CODE;
98396
98410
  }
98397
98411
  if (resource.kind !== "diagram" && resource.kind !== "whiteboard")
@@ -98511,6 +98525,7 @@ async function materializeLarkResources(input) {
98511
98525
  identity: identity2,
98512
98526
  token,
98513
98527
  type: "media",
98528
+ allowPreview: resource.kind === "image",
98514
98529
  ...input.mediaFiles?.[token] === undefined ? {} : { localPath: input.mediaFiles[token] }
98515
98530
  });
98516
98531
  if (omitLarkImage(resource, input.policy, items, replacements, downloaded.mediaType))
@@ -98522,7 +98537,7 @@ async function materializeLarkResources(input) {
98522
98537
  bytes: downloaded.bytes,
98523
98538
  mediaType: downloaded.mediaType,
98524
98539
  role: "evidence",
98525
- source: { kind: resource.kind, locator: resource.locator }
98540
+ source: { kind: resource.kind, locator: resource.locator, identity: identity2, representation: downloaded.representation }
98526
98541
  };
98527
98542
  assertBudget(asset, input.policy, totalBytes);
98528
98543
  totalBytes += asset.bytes.byteLength;
@@ -98530,8 +98545,17 @@ async function materializeLarkResources(input) {
98530
98545
  const title2 = markdownLabel(safeLabel(resource.title, resource.kind));
98531
98546
  const target = sourceAssetTarget(asset.path);
98532
98547
  const replacement = downloaded.mediaType.startsWith("image/") ? `![${title2}](${target}) <!-- ${resource.locator} -->` : `[${title2}](${target}) <!-- ${resource.locator} -->`;
98533
- replacements.set(resource.locator, replacement);
98534
- items.push({ kind: resource.kind, locator: resource.locator, status: "materialized", required, asset_paths: [asset.path] });
98548
+ replacements.set(resource.locator, downloaded.representation === "preview" ? `${replacement}
98549
+
98550
+ > Image preview captured; the original could not be downloaded.` : replacement);
98551
+ items.push({
98552
+ kind: resource.kind,
98553
+ locator: resource.locator,
98554
+ status: "materialized",
98555
+ required,
98556
+ asset_paths: [asset.path],
98557
+ ...downloaded.representation === "preview" ? { reason_code: "document.resource.preview", reason: "Same-identity preview captured; original download permission denied" } : {}
98558
+ });
98535
98559
  } catch (error) {
98536
98560
  if (error instanceof LarkResourceBudgetError && omitLarkImage(resource, input.policy, items, replacements, undefined, error.message))
98537
98561
  return;
@@ -98579,6 +98603,7 @@ function applyLarkResourceReplacements(markdown, resources, replacements) {
98579
98603
  }
98580
98604
  var REQUIRED_KINDS, MEDIA_TYPES_BY_EXTENSION;
98581
98605
  var init_larkResourceMaterialization = __esm(() => {
98606
+ init_larkMediaDownload();
98582
98607
  init_larkImagePolicy();
98583
98608
  init_src3();
98584
98609
  init_larkResourceCommand();
@@ -98691,10 +98716,13 @@ function credentialFailure(result) {
98691
98716
  function createLarkReadSession(runner2, initial, fallback = initial === "bot") {
98692
98717
  let identity2 = initial;
98693
98718
  let usedFallback = false;
98719
+ let readingDocument = false;
98720
+ let locked = false;
98721
+ const restart = new Error("Restart document with user identity");
98694
98722
  const run = async (args, options) => {
98695
98723
  const explicit = args.indexOf("--as");
98696
98724
  const requested = explicit >= 0 ? args[explicit + 1] : identity2;
98697
- const selected = usedFallback ? "user" : requested === "bot" ? "bot" : "user";
98725
+ const selected = locked || usedFallback ? identity2 : requested === "bot" ? "bot" : "user";
98698
98726
  const withIdentity = [...args];
98699
98727
  if (explicit >= 0)
98700
98728
  withIdentity[explicit + 1] = selected;
@@ -98702,14 +98730,28 @@ function createLarkReadSession(runner2, initial, fallback = initial === "bot") {
98702
98730
  withIdentity.push("--as", selected);
98703
98731
  const result = await runner2(withIdentity, options);
98704
98732
  identity2 = selected;
98705
- if (identity2 !== "bot" || !fallback || usedFallback || args.includes("--help") || !credentialFailure(result))
98706
- return result;
98707
- usedFallback = true;
98708
- identity2 = "user";
98709
- withIdentity[withIdentity.indexOf("--as") + 1] = "user";
98710
- return runner2(withIdentity, options);
98733
+ if (readingDocument && identity2 === "bot" && fallback && !usedFallback && !args.includes("--help") && credentialFailure(result))
98734
+ throw restart;
98735
+ return result;
98711
98736
  };
98712
- return { run, get identity() {
98737
+ async function readDocument(read) {
98738
+ readingDocument = true;
98739
+ try {
98740
+ try {
98741
+ return await read();
98742
+ } catch (error) {
98743
+ if (error !== restart)
98744
+ throw error;
98745
+ usedFallback = true;
98746
+ identity2 = "user";
98747
+ return await read();
98748
+ }
98749
+ } finally {
98750
+ readingDocument = false;
98751
+ locked = true;
98752
+ }
98753
+ }
98754
+ return { run, readDocument, get identity() {
98713
98755
  return identity2;
98714
98756
  }, get usedFallback() {
98715
98757
  return usedFallback;
@@ -99054,7 +99096,7 @@ async function fetchFeishuDocSnapshot(input, runner2 = defaultRunner) {
99054
99096
  fetched: await fetchDocsResponse(input, docsFetchPlan, runner2, input.prefetched.identity),
99055
99097
  identity: input.prefetched.identity,
99056
99098
  fallback: false
99057
- } : await fetchWithIdentity({ ...input, identity: preference }, docsFetchPlan, runner2);
99099
+ } : await session.readDocument(() => fetchWithIdentity({ ...input, identity: preference }, docsFetchPlan, runner2));
99058
99100
  let fetched = identityFetch.fetched;
99059
99101
  let accessIdentity = input.prefetched?.identity ?? session.identity;
99060
99102
  let projection;
@@ -99245,8 +99287,8 @@ var init_sensitiveSourceLiteral = __esm(() => {
99245
99287
  });
99246
99288
 
99247
99289
  // src/project/documentCaptureLark.ts
99248
- import { readdir as readdir22, readFile as readFile75 } from "node:fs/promises";
99249
- import { basename as basename10, extname as extname14, join as join95 } from "node:path";
99290
+ import { readdir as readdir23, readFile as readFile75 } from "node:fs/promises";
99291
+ import { basename as basename10, extname as extname14, join as join96 } from "node:path";
99250
99292
  function titleFromMarkdown2(markdown, fallbackPath) {
99251
99293
  const heading2 = markdown.split(`
99252
99294
  `).find((line) => /^#\s+\S/u.test(line));
@@ -99273,7 +99315,7 @@ async function fileContentMatches(path3, content3) {
99273
99315
  }
99274
99316
  }
99275
99317
  function sourceManifestPath2(entry) {
99276
- return entry.snapshot?.manifest ?? join95(entry.materializedAt, "manifest.json");
99318
+ return entry.snapshot?.manifest ?? join96(entry.materializedAt, "manifest.json");
99277
99319
  }
99278
99320
  function larkRuntimeError(message, detail) {
99279
99321
  return new ContextError(ExitCode.ExternalToolError, message, {
@@ -99400,12 +99442,12 @@ function assetManifestEntry(asset, assetRoot) {
99400
99442
  };
99401
99443
  }
99402
99444
  async function listSnapshotAssetFiles(root2, assetRoot) {
99403
- const assetsRoot = join95(root2, assetRoot);
99445
+ const assetsRoot = join96(root2, assetRoot);
99404
99446
  const files = [];
99405
99447
  const visit4 = async (dir, prefix = assetRoot) => {
99406
99448
  let entries2;
99407
99449
  try {
99408
- entries2 = await readdir22(dir, { withFileTypes: true });
99450
+ entries2 = await readdir23(dir, { withFileTypes: true });
99409
99451
  } catch (error) {
99410
99452
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
99411
99453
  return;
@@ -99413,7 +99455,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
99413
99455
  }
99414
99456
  for (const entry of entries2) {
99415
99457
  const relPath = `${prefix}/${entry.name}`;
99416
- const absolutePath = join95(dir, entry.name);
99458
+ const absolutePath = join96(dir, entry.name);
99417
99459
  if (entry.isDirectory()) {
99418
99460
  await visit4(absolutePath, relPath);
99419
99461
  continue;
@@ -99428,7 +99470,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
99428
99470
  }
99429
99471
  async function staleSnapshotAssetPaths(input) {
99430
99472
  const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
99431
- return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join95(input.materializedAtAbsPath, path3));
99473
+ return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join96(input.materializedAtAbsPath, path3));
99432
99474
  }
99433
99475
  function normalizeLarkError(error, sourceName) {
99434
99476
  if (error instanceof ContextError)
@@ -99542,9 +99584,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
99542
99584
  locator
99543
99585
  }];
99544
99586
  const manifestPath = sourceManifestPath2(entry);
99545
- const manifestAbsPath = join95(input.projectRoot, manifestPath);
99587
+ const manifestAbsPath = join96(input.projectRoot, manifestPath);
99546
99588
  const materializedAt = entry.materializedAt;
99547
- const materializedAtAbsPath = join95(input.projectRoot, materializedAt);
99589
+ const materializedAtAbsPath = join96(input.projectRoot, materializedAt);
99548
99590
  const manifest = createDocumentSnapshotManifest({
99549
99591
  sourceType: "lark",
99550
99592
  sourceName: resolved.sourceName,
@@ -99578,13 +99620,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
99578
99620
  }));
99579
99621
  try {
99580
99622
  const requestedWrites = [{
99581
- path: join95(materializedAtAbsPath, documentPath),
99623
+ path: join96(materializedAtAbsPath, documentPath),
99582
99624
  bytes: normalized
99583
99625
  }];
99584
99626
  for (const asset of assets) {
99585
99627
  if (asset.bytes !== undefined) {
99586
99628
  requestedWrites.push({
99587
- path: join95(materializedAtAbsPath, asset.entry.path),
99629
+ path: join96(materializedAtAbsPath, asset.entry.path),
99588
99630
  bytes: asset.bytes
99589
99631
  });
99590
99632
  }
@@ -99601,7 +99643,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
99601
99643
  currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
99602
99644
  });
99603
99645
  await applyAtomicFileBatch({
99604
- transactionRoot: join95(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
99646
+ transactionRoot: join96(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
99605
99647
  writes,
99606
99648
  removals
99607
99649
  });
@@ -99747,7 +99789,7 @@ __export(exports_articleRetirement, {
99747
99789
  retireArticles: () => retireArticles,
99748
99790
  articleRetirementSchema: () => articleRetirementSchema
99749
99791
  });
99750
- import { readFile as readFile81, readdir as readdir23 } from "node:fs/promises";
99792
+ import { readFile as readFile81, readdir as readdir24 } from "node:fs/promises";
99751
99793
  import { posix as posix10 } from "node:path";
99752
99794
  function rebuildInput(revision) {
99753
99795
  return JSON.stringify({ id: `retirement-${revision.slice(7)}`, operation: "rebuild", timing: "priority", targets: [] });
@@ -99880,7 +99922,7 @@ async function retireArticles(input) {
99880
99922
  }
99881
99923
  async function inspectTemplates(directory2) {
99882
99924
  const absolute = await safeProjectTarget(input.projectRoot, directory2);
99883
- const entries2 = await readdir23(absolute, { withFileTypes: true }).catch((error) => {
99925
+ const entries2 = await readdir24(absolute, { withFileTypes: true }).catch((error) => {
99884
99926
  if (error.code === "ENOENT")
99885
99927
  return [];
99886
99928
  throw error;
@@ -100030,8 +100072,8 @@ __export(exports_writeLockRecovery, {
100030
100072
  recoverWriterLock: () => recoverWriterLock,
100031
100073
  inspectWriterLock: () => inspectWriterLock
100032
100074
  });
100033
- import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as readdir24, rename as rename8, rmdir as rmdir2 } from "node:fs/promises";
100034
- import { join as join100 } from "node:path";
100075
+ import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as readdir25, rename as rename8, rmdir as rmdir2 } from "node:fs/promises";
100076
+ import { join as join101 } from "node:path";
100035
100077
  import { createHash as createHash30, randomUUID as randomUUID7 } from "node:crypto";
100036
100078
  async function inspectWriterLock(root2) {
100037
100079
  const path3 = await safeProjectTarget(root2, lockRelative);
@@ -100078,19 +100120,19 @@ async function recoverWriterLock(input) {
100078
100120
  };
100079
100121
  if (input.plan_digest !== before.digest)
100080
100122
  throw new Error("Writer lock changed; preview recovery again.");
100081
- const path3 = join100(input.projectRoot, lockRelative);
100082
- const guard = join100(path3, ".recovery");
100123
+ const path3 = join101(input.projectRoot, lockRelative);
100124
+ const guard = join101(path3, ".recovery");
100083
100125
  await mkdir34(guard);
100084
100126
  let archived = false;
100085
100127
  try {
100086
100128
  const current2 = await inspectWriterLock(input.projectRoot);
100087
100129
  if (current2?.digest !== before.digest || current2.process_state !== "not-running")
100088
100130
  throw new Error("Writer lock changed or owner resumed; keep the lock.");
100089
- const names = await readdir24(path3);
100131
+ const names = await readdir25(path3);
100090
100132
  if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
100091
100133
  throw new Error("Unexpected lock contents; preserve for diagnosis.");
100092
100134
  const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
100093
- await rename8(path3, join100(input.projectRoot, archive));
100135
+ await rename8(path3, join101(input.projectRoot, archive));
100094
100136
  archived = true;
100095
100137
  return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
100096
100138
  } finally {
@@ -100114,8 +100156,8 @@ __export(exports_taskRecovery, {
100114
100156
  RECOVERY_COMMAND: () => RECOVERY_COMMAND
100115
100157
  });
100116
100158
  import { existsSync as existsSync26 } from "node:fs";
100117
- import { dirname as dirname41, join as join101 } from "node:path";
100118
- import { lstat as lstat11, readdir as readdir25, readFile as readFile83 } from "node:fs/promises";
100159
+ import { dirname as dirname41, join as join102 } from "node:path";
100160
+ import { lstat as lstat11, readdir as readdir26, readFile as readFile83 } from "node:fs/promises";
100119
100161
  async function recoveryText(root2, path3) {
100120
100162
  const target = await safeProjectTarget(root2, path3);
100121
100163
  try {
@@ -100132,7 +100174,7 @@ async function recoveryJournals(root2) {
100132
100174
  await safeProjectTarget(root2, path3);
100133
100175
  let stat11;
100134
100176
  try {
100135
- stat11 = await lstat11(join101(root2, path3));
100177
+ stat11 = await lstat11(join102(root2, path3));
100136
100178
  } catch (error) {
100137
100179
  if (error.code === "ENOENT")
100138
100180
  return;
@@ -100143,7 +100185,7 @@ async function recoveryJournals(root2) {
100143
100185
  if (stat11.isDirectory()) {
100144
100186
  if (depth > 3)
100145
100187
  throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
100146
- for (const name3 of (await readdir25(join101(root2, path3))).sort())
100188
+ for (const name3 of (await readdir26(join102(root2, path3))).sort())
100147
100189
  await visit4(`${path3}/${name3}`, depth + 1);
100148
100190
  } else if (stat11.isFile())
100149
100191
  entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
@@ -100155,8 +100197,8 @@ function recoveryResources() {
100155
100197
  try {
100156
100198
  const root2 = dirname41(contextWorkflowProviderPath());
100157
100199
  const resources = {
100158
- skill: join101(root2, "skills/recover-workspace/SKILL.md"),
100159
- issue_template: join101(root2, "resources/templates/recovery-issue.md")
100200
+ skill: join102(root2, "skills/recover-workspace/SKILL.md"),
100201
+ issue_template: join102(root2, "resources/templates/recovery-issue.md")
100160
100202
  };
100161
100203
  if (!Object.values(resources).every((path3) => existsSync26(path3)))
100162
100204
  throw new Error("Recovery resources are absent from this Provider.");
@@ -100242,7 +100284,7 @@ __export(exports_taskLocalSourceAdjustment, {
100242
100284
  adjustLocalRevisionSources: () => adjustLocalRevisionSources
100243
100285
  });
100244
100286
  import { readFile as readFile84 } from "node:fs/promises";
100245
- import { join as join102 } from "node:path";
100287
+ import { join as join103 } from "node:path";
100246
100288
  async function adjustLocalRevisionSources(root2, input) {
100247
100289
  const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
100248
100290
  if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
@@ -100285,7 +100327,7 @@ async function adjustLocalRevisionSources(root2, input) {
100285
100327
  if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
100286
100328
  throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
100287
100329
  }
100288
- const raw = await readFile84(join102(root2, await revisionStoragePath(root2)), "utf8");
100330
+ const raw = await readFile84(join103(root2, await revisionStoragePath(root2)), "utf8");
100289
100331
  let next2;
100290
100332
  const discardIds = new Set;
100291
100333
  if (!input.refresh) {
@@ -100388,7 +100430,7 @@ ${input.instruction}` : revision.instruction
100388
100430
  content: content3
100389
100431
  }];
100390
100432
  if (discardIds.size > 0) {
100391
- const ledger = await readFile84(join102(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
100433
+ const ledger = await readFile84(join103(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
100392
100434
  if (error.code === "ENOENT")
100393
100435
  return;
100394
100436
  throw error;
@@ -100645,7 +100687,7 @@ __export(exports_managedDocumentRename, {
100645
100687
  renameManagedDocument: () => renameManagedDocument
100646
100688
  });
100647
100689
  import { readFile as readFile92 } from "node:fs/promises";
100648
- import { join as join110, posix as posix11 } from "node:path";
100690
+ import { join as join111, posix as posix11 } from "node:path";
100649
100691
  async function optionalText2(path3) {
100650
100692
  try {
100651
100693
  return await readFile92(path3, "utf8");
@@ -100732,7 +100774,7 @@ async function renameManagedDocument(input) {
100732
100774
  if (path3.split("/").includes("..") || path3.startsWith("/"))
100733
100775
  throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
100734
100776
  await safeProjectTarget(input.projectRoot, path3);
100735
- const before = await optionalText2(join110(input.projectRoot, path3));
100777
+ const before = await optionalText2(join111(input.projectRoot, path3));
100736
100778
  if (before === undefined)
100737
100779
  continue;
100738
100780
  let after;
@@ -100821,7 +100863,7 @@ var init_managedDocumentRename = __esm(() => {
100821
100863
 
100822
100864
  // src/cli.ts
100823
100865
  import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
100824
- import { dirname as dirname49, join as join116 } from "node:path";
100866
+ import { dirname as dirname49, join as join117 } from "node:path";
100825
100867
  import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL3 } from "node:url";
100826
100868
 
100827
100869
  // ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
@@ -106104,14 +106146,14 @@ function compactJsonResult(result, verbose) {
106104
106146
  // src/project/runLog.ts
106105
106147
  import { randomUUID as randomUUID5 } from "node:crypto";
106106
106148
  import { mkdir as mkdir33, writeFile as writeFile26 } from "node:fs/promises";
106107
- import { dirname as dirname39, join as join96 } from "node:path";
106149
+ import { dirname as dirname39, join as join97 } from "node:path";
106108
106150
  var createPhaseRunId = () => {
106109
106151
  const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
106110
106152
  return `run_${timestamp}_${randomUUID5().slice(0, 8)}`;
106111
106153
  };
106112
106154
  async function writePhaseRunLog(input) {
106113
- const relPath = join96(".tmp", "context-runtime", "runs", `${input.runId}.json`);
106114
- const absPath = join96(input.projectRoot, relPath);
106155
+ const relPath = join97(".tmp", "context-runtime", "runs", `${input.runId}.json`);
106156
+ const absPath = join97(input.projectRoot, relPath);
106115
106157
  await mkdir33(dirname39(absPath), { recursive: true });
106116
106158
  await writeFile26(absPath, `${JSON.stringify({
106117
106159
  run_id: input.runId,
@@ -107211,7 +107253,7 @@ init_reviewApplyIndexer();
107211
107253
  init_approvedKnowledgeSnapshots();
107212
107254
  import { existsSync as existsSync25 } from "node:fs";
107213
107255
  import { readFile as readFile76 } from "node:fs/promises";
107214
- import { join as join97 } from "node:path";
107256
+ import { join as join98 } from "node:path";
107215
107257
 
107216
107258
  // src/project/reviewCandidateAuthority.ts
107217
107259
  init_src2();
@@ -107274,7 +107316,7 @@ async function prepareApprovedPage(input) {
107274
107316
  next: "Refresh the current production or article revision, then reopen Review before approval."
107275
107317
  });
107276
107318
  }
107277
- const relPath = join97("knowledge", input.record.path);
107319
+ const relPath = join98("knowledge", input.record.path);
107278
107320
  const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
107279
107321
  const previousPath = input.record.approved_revision?.previous_path;
107280
107322
  if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
@@ -107289,13 +107331,13 @@ async function prepareApprovedPage(input) {
107289
107331
  next: "Resolve the approved page path migration explicitly before approving this candidate."
107290
107332
  });
107291
107333
  }
107292
- const absPath = join97(input.projectRoot, relPath);
107334
+ const absPath = join98(input.projectRoot, relPath);
107293
107335
  const existing = existsSync25(absPath) ? await readFile76(absPath, "utf8") : undefined;
107294
107336
  let previous3;
107295
107337
  if (previousPath !== undefined) {
107296
107338
  if (existing !== undefined || existingView?.relPath !== `knowledge/${previousPath}`)
107297
107339
  throw new TypeError("Page move destination or original identity changed; refresh its revision.");
107298
- previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join97(input.projectRoot, "knowledge", previousPath), "utf8") };
107340
+ previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join98(input.projectRoot, "knowledge", previousPath), "utf8") };
107299
107341
  }
107300
107342
  if (input.record.approved_revision !== undefined) {
107301
107343
  const base = previous3?.content ?? existing;
@@ -107342,7 +107384,7 @@ async function prepareApprovedPage(input) {
107342
107384
  }
107343
107385
  async function readProjectFileMaybe(projectRoot, relPath) {
107344
107386
  try {
107345
- return await readFile76(join97(projectRoot, relPath), "utf8");
107387
+ return await readFile76(join98(projectRoot, relPath), "utf8");
107346
107388
  } catch (error) {
107347
107389
  if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
107348
107390
  return;
@@ -107565,7 +107607,7 @@ async function applyReviewDecisions(input) {
107565
107607
  });
107566
107608
  }
107567
107609
  seenApprovedIds.set(approvedRef, row.candidate_id);
107568
- const approvedPath = join97("knowledge", row.path);
107610
+ const approvedPath = join98("knowledge", row.path);
107569
107611
  const previousPathCandidate = seenApprovedPaths.get(knowledgeTargetPathKey(approvedPath));
107570
107612
  if (previousPathCandidate !== undefined) {
107571
107613
  throw new ContextError(ExitCode.UserError, `multiple approved review decisions target the same knowledge path: ${approvedPath}`, {
@@ -107615,7 +107657,7 @@ async function applyReviewDecisions(input) {
107615
107657
  for (const path3 of approvedPageIndex.byRelPath.keys()) {
107616
107658
  if (pagesToWrite.some((page) => page.relPath === path3 || page.previous?.path === path3))
107617
107659
  continue;
107618
- const before = await readFile76(join97(input.projectRoot, path3), "utf8");
107660
+ const before = await readFile76(join98(input.projectRoot, path3), "utf8");
107619
107661
  const local = path3.replace(/^knowledge\//u, "");
107620
107662
  const after = moveKnowledgeLinkTargets2(before, local, local, moved);
107621
107663
  navigationTargets.push(reviewFileTarget({ path: path3, baseContent: before, targetContent: after }));
@@ -107699,12 +107741,12 @@ init_candidateLedger();
107699
107741
 
107700
107742
  // src/project/localHtmlReport.ts
107701
107743
  import { execFile as execFile11 } from "node:child_process";
107702
- import { isAbsolute as isAbsolute17, join as join98 } from "node:path";
107744
+ import { isAbsolute as isAbsolute17, join as join99 } from "node:path";
107703
107745
  import { pathToFileURL as pathToFileURL2 } from "node:url";
107704
107746
  import { promisify as promisify11 } from "node:util";
107705
107747
  var execFileAsync5 = promisify11(execFile11);
107706
107748
  function htmlReportReference(input) {
107707
- const absolutePath = isAbsolute17(input.path) ? input.path : join98(input.projectRoot, input.path);
107749
+ const absolutePath = isAbsolute17(input.path) ? input.path : join99(input.projectRoot, input.path);
107708
107750
  return {
107709
107751
  format: "html",
107710
107752
  path: input.path,
@@ -108728,7 +108770,7 @@ init_maintenanceStorage();
108728
108770
  init_productionFeedback();
108729
108771
  import { randomUUID as randomUUID6 } from "node:crypto";
108730
108772
  import { readFile as readFile79 } from "node:fs/promises";
108731
- import { join as join99 } from "node:path";
108773
+ import { join as join100 } from "node:path";
108732
108774
  async function beginProductionRevision(input) {
108733
108775
  return withProductionFeedback({ operation: "revision" }, () => withProjectWriteLock(input.projectRoot, "production-revision", async () => {
108734
108776
  await recoverDurableMultiFileTransactions(input.projectRoot);
@@ -108767,7 +108809,7 @@ async function beginProductionRevision(input) {
108767
108809
  const formal = approved.byPath.get(path3);
108768
108810
  if (!prior && !formal)
108769
108811
  throw invalid2("Write the current task first; there is no article draft to revise yet.");
108770
- const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join99("knowledge", path3)), "utf8");
108812
+ const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join100("knowledge", path3)), "utf8");
108771
108813
  const sections = prior?.indexer_candidate.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
108772
108814
  const sources = [];
108773
108815
  for (const source2 of owner.sources) {
@@ -109407,7 +109449,7 @@ init_atomicWrite();
109407
109449
  var import_yaml44 = __toESM(require_dist(), 1);
109408
109450
  import { Buffer as Buffer4 } from "node:buffer";
109409
109451
  import { createHash as createHash31 } from "node:crypto";
109410
- import { join as join103 } from "node:path";
109452
+ import { join as join104 } from "node:path";
109411
109453
  var INLINE_LIMIT = 16 * 1024;
109412
109454
  function record4(value) {
109413
109455
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
@@ -109433,8 +109475,8 @@ async function prepareActionCompletionOutput(input) {
109433
109475
  if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
109434
109476
  return input.result;
109435
109477
  const digest6 = createHash31("sha256").update(full).digest("hex");
109436
- const root2 = join103(input.projectRoot, ".tmp/context-runtime/action-results");
109437
- const resultFile = join103(root2, `${digest6}.json`);
109478
+ const root2 = join104(input.projectRoot, ".tmp/context-runtime/action-results");
109479
+ const resultFile = join104(root2, `${digest6}.json`);
109438
109480
  await atomicWriteFile(resultFile, full);
109439
109481
  if (production)
109440
109482
  return {
@@ -109445,7 +109487,7 @@ async function prepareActionCompletionOutput(input) {
109445
109487
  ...pick(result, ["next", "next_preparation"])
109446
109488
  };
109447
109489
  const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
109448
- const nextFile = next2 === undefined ? undefined : join103(root2, `${digest6}.next.json`);
109490
+ const nextFile = next2 === undefined ? undefined : join104(root2, `${digest6}.next.json`);
109449
109491
  if (nextFile !== undefined)
109450
109492
  await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
109451
109493
  const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
@@ -109850,9 +109892,9 @@ function registerProjectActionCommands(program2) {
109850
109892
  // src/commands/cleanClaudePluginCache.ts
109851
109893
  init_cliFeedback();
109852
109894
  import { existsSync as existsSync27 } from "node:fs";
109853
- import { readdir as readdir26, rm as rm21 } from "node:fs/promises";
109895
+ import { readdir as readdir27, rm as rm22 } from "node:fs/promises";
109854
109896
  import { homedir } from "node:os";
109855
- import { join as join104 } from "node:path";
109897
+ import { join as join105 } from "node:path";
109856
109898
  var ORPHAN_MARKER = ".orphaned_at";
109857
109899
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
109858
109900
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -109865,40 +109907,40 @@ async function cleanClaudePluginCache(opts = {}) {
109865
109907
  lines.push("· claude plugin cache: missing — nothing to clean");
109866
109908
  return { lines, removed, scanned };
109867
109909
  }
109868
- const marketplaces = await readdir26(cacheRoot, { withFileTypes: true });
109910
+ const marketplaces = await readdir27(cacheRoot, { withFileTypes: true });
109869
109911
  for (const mp of marketplaces) {
109870
109912
  if (!mp.isDirectory())
109871
109913
  continue;
109872
- const mpDir = join104(cacheRoot, mp.name);
109873
- const plugins = await readdir26(mpDir, { withFileTypes: true });
109914
+ const mpDir = join105(cacheRoot, mp.name);
109915
+ const plugins = await readdir27(mpDir, { withFileTypes: true });
109874
109916
  for (const pl of plugins) {
109875
109917
  if (!pl.isDirectory())
109876
109918
  continue;
109877
- const plDir = join104(mpDir, pl.name);
109878
- const versions = await readdir26(plDir, { withFileTypes: true });
109919
+ const plDir = join105(mpDir, pl.name);
109920
+ const versions = await readdir27(plDir, { withFileTypes: true });
109879
109921
  for (const ver of versions) {
109880
109922
  if (!ver.isDirectory())
109881
109923
  continue;
109882
109924
  scanned += 1;
109883
- const verDir = join104(plDir, ver.name);
109884
- const markerPath = join104(verDir, ORPHAN_MARKER);
109925
+ const verDir = join105(plDir, ver.name);
109926
+ const markerPath = join105(verDir, ORPHAN_MARKER);
109885
109927
  if (!existsSync27(markerPath))
109886
109928
  continue;
109887
109929
  const label2 = `${mp.name}/${pl.name}/${ver.name}`;
109888
109930
  if (opts.dryRun) {
109889
109931
  lines.push(` - would remove: ${label2}`);
109890
109932
  } else {
109891
- await rm21(verDir, { recursive: true, force: true });
109933
+ await rm22(verDir, { recursive: true, force: true });
109892
109934
  removed += 1;
109893
109935
  lines.push(` ✓ removed: ${label2}`);
109894
109936
  }
109895
109937
  }
109896
109938
  if (!opts.dryRun && await isEmptyDir(plDir)) {
109897
- await rm21(plDir, { recursive: true, force: true });
109939
+ await rm22(plDir, { recursive: true, force: true });
109898
109940
  }
109899
109941
  }
109900
109942
  if (!opts.dryRun && await isEmptyDir(mpDir)) {
109901
- await rm21(mpDir, { recursive: true, force: true });
109943
+ await rm22(mpDir, { recursive: true, force: true });
109902
109944
  }
109903
109945
  }
109904
109946
  if (scanned === 0) {
@@ -109913,11 +109955,11 @@ function resolveClaudePluginCacheRoot(opts) {
109913
109955
  if (explicitRoot)
109914
109956
  return explicitRoot;
109915
109957
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
109916
- return join104(home, ".claude", "plugins", "cache");
109958
+ return join105(home, ".claude", "plugins", "cache");
109917
109959
  }
109918
109960
  async function isEmptyDir(dir) {
109919
109961
  try {
109920
- const entries2 = await readdir26(dir);
109962
+ const entries2 = await readdir27(dir);
109921
109963
  return entries2.length === 0;
109922
109964
  } catch {
109923
109965
  return false;
@@ -109945,13 +109987,13 @@ init_exitCode();
109945
109987
 
109946
109988
  // src/lib/packageVersion.ts
109947
109989
  import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
109948
- import { dirname as dirname42, join as join105 } from "node:path";
109990
+ import { dirname as dirname42, join as join106 } from "node:path";
109949
109991
  import { fileURLToPath as fileURLToPath8 } from "node:url";
109950
109992
  function readPackageVersion() {
109951
109993
  try {
109952
109994
  let dir = dirname42(fileURLToPath8(import.meta.url));
109953
109995
  for (let depth = 0;depth < 8; depth += 1) {
109954
- const packagePath = join105(dir, "package.json");
109996
+ const packagePath = join106(dir, "package.json");
109955
109997
  if (existsSync28(packagePath)) {
109956
109998
  const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
109957
109999
  if (typeof parsed.version === "string" && parsed.version.length > 0) {
@@ -109991,7 +110033,7 @@ init_repoSourceRegistry();
109991
110033
  init_writeLock();
109992
110034
  import { execFile as execFile12 } from "node:child_process";
109993
110035
  import { existsSync as existsSync29 } from "node:fs";
109994
- import { lstat as lstat12, mkdir as mkdir35, readlink as readlink2, realpath as realpath10, rm as rm22, symlink as symlink4 } from "node:fs/promises";
110036
+ import { lstat as lstat12, mkdir as mkdir35, readlink as readlink2, realpath as realpath10, rm as rm23, symlink as symlink4 } from "node:fs/promises";
109995
110037
  import { basename as basename11, dirname as dirname43, isAbsolute as isAbsolute19, relative as relative26, resolve as resolve34 } from "node:path";
109996
110038
  import { promisify as promisify12 } from "node:util";
109997
110039
  var execFileAsync6 = promisify12(execFile12);
@@ -110181,14 +110223,14 @@ async function cloneCheckout(input) {
110181
110223
  try {
110182
110224
  await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
110183
110225
  } catch {
110184
- await rm22(target, { recursive: true, force: true });
110226
+ await rm23(target, { recursive: true, force: true });
110185
110227
  try {
110186
110228
  await execFileAsync6("git", ["clone", "--no-checkout", "--depth=1", input.remote, target], {
110187
110229
  encoding: "utf8",
110188
110230
  maxBuffer: 4 * 1024 * 1024
110189
110231
  });
110190
110232
  } catch (error) {
110191
- await rm22(target, { recursive: true, force: true });
110233
+ await rm23(target, { recursive: true, force: true });
110192
110234
  const detail = error !== null && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "").trim() : error instanceof Error ? error.message : String(error);
110193
110235
  throw new ContextError(ExitCode.ExternalToolError, `cannot clone registered repository: ${input.remote}`, {
110194
110236
  category: ErrorCategory.ExternalToolFailed,
@@ -110213,7 +110255,7 @@ async function cloneCheckout(input) {
110213
110255
  await verifyCheckout({ checkout: target, remote: input.remote, ref: input.ref, subpaths: input.subpaths });
110214
110256
  return target;
110215
110257
  } catch (error) {
110216
- await rm22(target, { recursive: true, force: true });
110258
+ await rm23(target, { recursive: true, force: true });
110217
110259
  throw error;
110218
110260
  }
110219
110261
  }
@@ -110229,7 +110271,7 @@ async function bindLocalAlias(input) {
110229
110271
  const actualReal = await realpath10(actual).catch(() => null);
110230
110272
  if (actualReal !== null && actualReal === await realpath10(input.checkout))
110231
110273
  return;
110232
- await rm22(alias);
110274
+ await rm23(alias);
110233
110275
  } else {
110234
110276
  const actual = await realpath10(alias);
110235
110277
  if (actual === await realpath10(input.checkout))
@@ -110338,14 +110380,14 @@ init_src2();
110338
110380
  init_documentCapture();
110339
110381
  import { existsSync as existsSync30 } from "node:fs";
110340
110382
  import { readFile as readFile86 } from "node:fs/promises";
110341
- import { join as join107 } from "node:path";
110383
+ import { join as join108 } from "node:path";
110342
110384
 
110343
110385
  // src/project/sourceCommandViews.ts
110344
110386
  init_documentSiteDetection();
110345
110387
  init_workspace();
110346
110388
  init_documentBatchManifest();
110347
110389
  import { readFile as readFile85 } from "node:fs/promises";
110348
- import { join as join106 } from "node:path";
110390
+ import { join as join107 } from "node:path";
110349
110391
  function repoSourceAgentView(source2) {
110350
110392
  return {
110351
110393
  id: source2.id ?? source2.name,
@@ -110406,7 +110448,7 @@ async function fileSourceAgentViewWithNextAction(input) {
110406
110448
  };
110407
110449
  }
110408
110450
  function documentSourceManifestPath(source2) {
110409
- return source2.snapshot?.manifest ?? join106(source2.materializedAt, "manifest.json");
110451
+ return source2.snapshot?.manifest ?? join107(source2.materializedAt, "manifest.json");
110410
110452
  }
110411
110453
  async function fileSourceDocumentSiteHint(input) {
110412
110454
  const detection = await detectDocumentSiteFiles({
@@ -110416,7 +110458,7 @@ async function fileSourceDocumentSiteHint(input) {
110416
110458
  let snapshotConfigured = false;
110417
110459
  const manifest = documentSourceManifestPath(input.source);
110418
110460
  try {
110419
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join106(input.projectRoot, manifest), "utf8")), input.source.name);
110461
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join107(input.projectRoot, manifest), "utf8")), input.source.name);
110420
110462
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
110421
110463
  } catch {
110422
110464
  snapshotConfigured = false;
@@ -110449,11 +110491,11 @@ async function larkSourceAgentViewWithNextAction(input) {
110449
110491
  init_documentBatchManifest();
110450
110492
  init_documentSnapshotFidelity();
110451
110493
  function documentSourceManifestPath2(source2) {
110452
- return source2.snapshot?.manifest ?? join107(source2.materializedAt, "manifest.json");
110494
+ return source2.snapshot?.manifest ?? join108(source2.materializedAt, "manifest.json");
110453
110495
  }
110454
110496
  async function documentSnapshotState(input) {
110455
110497
  const manifest = documentSourceManifestPath2(input.source);
110456
- const manifestPath = join107(input.projectRoot, manifest);
110498
+ const manifestPath = join108(input.projectRoot, manifest);
110457
110499
  if (!existsSync30(manifestPath)) {
110458
110500
  return {
110459
110501
  snapshotReady: false,
@@ -110532,7 +110574,7 @@ async function documentSnapshotState(input) {
110532
110574
  const missing = [
110533
110575
  ...parsed.files.map((file) => file.path),
110534
110576
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
110535
- ].find((path3) => !existsSync30(join107(input.projectRoot, input.source.materializedAt, path3)));
110577
+ ].find((path3) => !existsSync30(join108(input.projectRoot, input.source.materializedAt, path3)));
110536
110578
  if (missing !== undefined) {
110537
110579
  return {
110538
110580
  snapshotReady: false,
@@ -110634,7 +110676,7 @@ init_exitCode();
110634
110676
  var import_yaml47 = __toESM(require_dist(), 1);
110635
110677
  import { createHash as createHash32 } from "node:crypto";
110636
110678
  import { readFile as readFile87, realpath as realpath11 } from "node:fs/promises";
110637
- import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join108, relative as relative27, resolve as resolve35 } from "node:path";
110679
+ import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join109, relative as relative27, resolve as resolve35 } from "node:path";
110638
110680
  init_writeLock();
110639
110681
  var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
110640
110682
  function isDateSourceNamespace(value) {
@@ -110730,7 +110772,7 @@ function assertSafeFileInclude(value) {
110730
110772
  }
110731
110773
  async function readRegistryDocument(projectRoot, registryPath2) {
110732
110774
  try {
110733
- const content3 = await readFile87(join108(projectRoot, registryPath2), "utf8");
110775
+ const content3 = await readFile87(join109(projectRoot, registryPath2), "utf8");
110734
110776
  return content3.trim().length === 0 ? { sources: [] } : import_yaml47.default.parse(content3);
110735
110777
  } catch (error) {
110736
110778
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -110848,7 +110890,7 @@ async function addFileSourceUnlocked(input) {
110848
110890
  const record6 = entry2;
110849
110891
  return record6.name !== input.name && record6.id !== input.name;
110850
110892
  }), nextEntry];
110851
- await atomicWriteFile(join108(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110893
+ await atomicWriteFile(join109(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110852
110894
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
110853
110895
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
110854
110896
  if (entry === undefined) {
@@ -110904,7 +110946,7 @@ async function addLarkSourceUnlocked(input) {
110904
110946
  const record6 = entry2;
110905
110947
  return record6.name !== input.name && record6.id !== input.name;
110906
110948
  }), nextEntry];
110907
- await atomicWriteFile(join108(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110949
+ await atomicWriteFile(join109(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110908
110950
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
110909
110951
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
110910
110952
  if (entry === undefined) {
@@ -111108,8 +111150,8 @@ init_writeLock();
111108
111150
  var import_yaml48 = __toESM(require_dist(), 1);
111109
111151
  import { existsSync as existsSync31 } from "node:fs";
111110
111152
  import { createHash as createHash33 } from "node:crypto";
111111
- import { readFile as readFile88, readdir as readdir27, rm as rm23 } from "node:fs/promises";
111112
- import { isAbsolute as isAbsolute21, join as join109, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
111153
+ import { readFile as readFile88, readdir as readdir28, rm as rm24 } from "node:fs/promises";
111154
+ import { isAbsolute as isAbsolute21, join as join110, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
111113
111155
  function sourceIdentity(source2) {
111114
111156
  if (source2.kind === "source.collection")
111115
111157
  return;
@@ -111141,7 +111183,7 @@ function collectStrings(value, output) {
111141
111183
  }
111142
111184
  }
111143
111185
  async function yamlReferences(input) {
111144
- const absolutePath = join109(input.projectRoot, input.path);
111186
+ const absolutePath = join110(input.projectRoot, input.path);
111145
111187
  if (!existsSync31(absolutePath))
111146
111188
  return false;
111147
111189
  const parsed = import_yaml48.default.parse(await readFile88(absolutePath, "utf8"));
@@ -111270,7 +111312,7 @@ async function registryRemovalWrite(projectRoot, source2) {
111270
111312
  const path3 = registryPath2(source2.type);
111271
111313
  if (path3 === null)
111272
111314
  return;
111273
- const absolutePath = join109(projectRoot, path3);
111315
+ const absolutePath = join110(projectRoot, path3);
111274
111316
  const document4 = existsSync31(absolutePath) ? import_yaml48.default.parse(await readFile88(absolutePath, "utf8")) : { sources: [] };
111275
111317
  return {
111276
111318
  path: absolutePath,
@@ -111289,7 +111331,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
111289
111331
  return absolute;
111290
111332
  }
111291
111333
  function safeManagedManifestPath(projectRoot, source2) {
111292
- const manifest = source2.manifest ?? join109(source2.materializedAt, "manifest.json");
111334
+ const manifest = source2.manifest ?? join110(source2.materializedAt, "manifest.json");
111293
111335
  if (isAbsolute21(manifest))
111294
111336
  throw unsafeOwnership(source2, manifest);
111295
111337
  const absolute = resolve36(projectRoot, manifest);
@@ -111451,7 +111493,7 @@ function publicRemovalResult(plan, action) {
111451
111493
  };
111452
111494
  }
111453
111495
  async function pruneExtractRuntime(projectRoot, source2) {
111454
- const fingerprintPath = join109(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
111496
+ const fingerprintPath = join110(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
111455
111497
  const removedPhaseIds = new Set;
111456
111498
  if (existsSync31(fingerprintPath)) {
111457
111499
  const parsed = JSON.parse(await readFile88(fingerprintPath, "utf8"));
@@ -111468,14 +111510,14 @@ async function pruneExtractRuntime(projectRoot, source2) {
111468
111510
  await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
111469
111511
  `);
111470
111512
  }
111471
- const phaseOwnershipPath = join109(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
111513
+ const phaseOwnershipPath = join110(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
111472
111514
  if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
111473
111515
  const parsed = JSON.parse(await readFile88(phaseOwnershipPath, "utf8"));
111474
111516
  const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
111475
111517
  await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
111476
111518
  `);
111477
111519
  }
111478
- const symbolPath = join109(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
111520
+ const symbolPath = join110(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
111479
111521
  if (existsSync31(symbolPath)) {
111480
111522
  const parsed = JSON.parse(await readFile88(symbolPath, "utf8"));
111481
111523
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
@@ -111483,12 +111525,12 @@ async function pruneExtractRuntime(projectRoot, source2) {
111483
111525
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
111484
111526
  `);
111485
111527
  }
111486
- const snapshotRoot = join109(projectRoot, ".tmp/context-runtime/extract/candidates");
111528
+ const snapshotRoot = join110(projectRoot, ".tmp/context-runtime/extract/candidates");
111487
111529
  const visit4 = async (directory) => {
111488
111530
  if (!existsSync31(directory))
111489
111531
  return;
111490
- for (const entry of await readdir27(directory, { withFileTypes: true })) {
111491
- const path3 = join109(directory, entry.name);
111532
+ for (const entry of await readdir28(directory, { withFileTypes: true })) {
111533
+ const path3 = join110(directory, entry.name);
111492
111534
  if (entry.isDirectory()) {
111493
111535
  await visit4(path3);
111494
111536
  continue;
@@ -111499,7 +111541,7 @@ async function pruneExtractRuntime(projectRoot, source2) {
111499
111541
  const parsed = JSON.parse(await readFile88(path3, "utf8"));
111500
111542
  const refs = Array.isArray(parsed.source_refs) ? parsed.source_refs : [];
111501
111543
  if (parsed.source === source2.name || refs.some((ref2) => typeof ref2 === "string" && stringReferencesSource(ref2, source2))) {
111502
- await rm23(path3, { force: true });
111544
+ await rm24(path3, { force: true });
111503
111545
  }
111504
111546
  } catch {}
111505
111547
  }
@@ -111538,7 +111580,7 @@ async function removeProjectSource(input) {
111538
111580
  });
111539
111581
  }
111540
111582
  await applyAtomicFileBatch({
111541
- transactionRoot: join109(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
111583
+ transactionRoot: join110(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
111542
111584
  writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
111543
111585
  removals: plan.absoluteRemovals
111544
111586
  });
@@ -112180,8 +112222,8 @@ init_cliFeedback();
112180
112222
  init_exitCode();
112181
112223
  var import_yaml51 = __toESM(require_dist(), 1);
112182
112224
  import { constants as constants6, existsSync as existsSync32 } from "node:fs";
112183
- import { lstat as lstat13, open as open5, readdir as readdir28 } from "node:fs/promises";
112184
- import { dirname as dirname44, join as join111, resolve as resolve38 } from "node:path";
112225
+ import { lstat as lstat13, open as open5, readdir as readdir29 } from "node:fs/promises";
112226
+ import { dirname as dirname44, join as join112, resolve as resolve38 } from "node:path";
112185
112227
  import { fileURLToPath as fileURLToPath9 } from "node:url";
112186
112228
  function bundledSkillRoot() {
112187
112229
  const directory = dirname44(fileURLToPath9(import.meta.url));
@@ -112208,10 +112250,10 @@ async function listProductionSkills(root2) {
112208
112250
  }
112209
112251
  }
112210
112252
  async function readProductionSkills(root2) {
112211
- const entries2 = (await readdir28(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
112253
+ const entries2 = (await readdir29(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
112212
112254
  const skills = [];
112213
112255
  for (const directory of entries2) {
112214
- const entry = join111(root2, directory.name, "SKILL.md");
112256
+ const entry = join112(root2, directory.name, "SKILL.md");
112215
112257
  if (!(await lstat13(entry)).isFile())
112216
112258
  throw new TypeError(`Skill entry must be a regular file: ${entry}`);
112217
112259
  const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
@@ -112619,8 +112661,8 @@ init_cliFeedback();
112619
112661
  init_errors3();
112620
112662
  init_exitCode();
112621
112663
  import { createHash as createHash34 } from "node:crypto";
112622
- import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as readdir29, rename as rename9, rm as rm24, writeFile as writeFile28 } from "node:fs/promises";
112623
- import { dirname as dirname46, join as join112, resolve as resolve40 } from "node:path";
112664
+ import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as readdir30, rename as rename9, rm as rm25, writeFile as writeFile28 } from "node:fs/promises";
112665
+ import { dirname as dirname46, join as join113, resolve as resolve40 } from "node:path";
112624
112666
  var MARKER = ".context-skill-install.json";
112625
112667
  function conflict(path3) {
112626
112668
  throw new ContextError(ExitCode.UserError, `Local skill install conflict: ${path3}`, {
@@ -112648,10 +112690,10 @@ async function checkParents(path3) {
112648
112690
  async function digest7(root2) {
112649
112691
  const hash4 = createHash34("sha256");
112650
112692
  async function visit4(dir, prefix) {
112651
- for (const name3 of (await readdir29(dir)).sort()) {
112693
+ for (const name3 of (await readdir30(dir)).sort()) {
112652
112694
  if (!prefix && name3 === MARKER)
112653
112695
  continue;
112654
- const path3 = join112(dir, name3);
112696
+ const path3 = join113(dir, name3);
112655
112697
  const entry = await lstat14(path3);
112656
112698
  if (entry.isSymbolicLink())
112657
112699
  conflict(path3);
@@ -112671,31 +112713,31 @@ async function installLocalSkills(root2, path3, dryRun, agent) {
112671
112713
  if (!path3.trim())
112672
112714
  conflict("--local requires a non-empty path");
112673
112715
  const targetRoot = resolve40(path3);
112674
- const skillsRoot = join112(targetRoot, "skills");
112716
+ const skillsRoot = join113(targetRoot, "skills");
112675
112717
  await checkParents(skillsRoot);
112676
- const sourceRoot2 = join112(root2, "skills");
112718
+ const sourceRoot2 = join113(root2, "skills");
112677
112719
  const commandPlans = [];
112678
112720
  const commandEntries = new Set;
112679
112721
  if (agent === "claude" || agent === "cursor") {
112680
- for (const name3 of await readdir29(join112(root2, "claude", "commands"))) {
112722
+ for (const name3 of await readdir30(join113(root2, "claude", "commands"))) {
112681
112723
  if (name3.endsWith(".md"))
112682
112724
  commandEntries.add(name3.slice(0, -3));
112683
112725
  }
112684
- const commandsRoot = join112(targetRoot, "commands");
112726
+ const commandsRoot = join113(targetRoot, "commands");
112685
112727
  await checkParents(commandsRoot);
112686
- for (const entry of await readdir29(join112(root2, agent, "commands"), { withFileTypes: true })) {
112728
+ for (const entry of await readdir30(join113(root2, agent, "commands"), { withFileTypes: true })) {
112687
112729
  if (!entry.isFile() || !entry.name.endsWith(".md"))
112688
112730
  continue;
112689
- let content3 = await readFile94(join112(root2, agent, "commands", entry.name), "utf8");
112731
+ let content3 = await readFile94(join113(root2, agent, "commands", entry.name), "utf8");
112690
112732
  if (agent === "claude") {
112691
112733
  const frontmatter2 = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
112692
112734
  if (!frontmatter2)
112693
- conflict(join112(root2, agent, "commands", entry.name));
112735
+ conflict(join113(root2, agent, "commands", entry.name));
112694
112736
  content3 = `${frontmatter2[1]}disable-model-invocation: true
112695
112737
  ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmatter2[3]}${content3.slice(frontmatter2[0].length)}`;
112696
112738
  }
112697
- const target = join112(commandsRoot, entry.name);
112698
- const marker = join112(commandsRoot, `.context-${entry.name}.json`);
112739
+ const target = join113(commandsRoot, entry.name);
112740
+ const marker = join113(commandsRoot, `.context-${entry.name}.json`);
112699
112741
  for (const file of [target, marker]) {
112700
112742
  const existing = await stat11(file);
112701
112743
  if (existing && (!existing.isFile() || existing.isSymbolicLink()))
@@ -112716,14 +112758,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112716
112758
  commandPlans.push({ name: entry.name, target, marker, content: content3, hash: createHash34("sha256").update(content3).digest("hex") });
112717
112759
  }
112718
112760
  if (!commandPlans.length)
112719
- conflict(join112(root2, agent, "commands"));
112761
+ conflict(join113(root2, agent, "commands"));
112720
112762
  }
112721
112763
  const plans = [];
112722
- for (const entry of (await readdir29(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
112723
- if (!entry.isDirectory() || !await stat11(join112(sourceRoot2, entry.name, "SKILL.md")))
112764
+ for (const entry of (await readdir30(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
112765
+ if (!entry.isDirectory() || !await stat11(join113(sourceRoot2, entry.name, "SKILL.md")))
112724
112766
  continue;
112725
- const source2 = join112(sourceRoot2, entry.name);
112726
- const target = join112(skillsRoot, entry.name);
112767
+ const source2 = join113(sourceRoot2, entry.name);
112768
+ const target = join113(skillsRoot, entry.name);
112727
112769
  if (commandEntries.has(entry.name)) {
112728
112770
  if (await stat11(target))
112729
112771
  conflict(`${target} (use a fresh host directory to avoid duplicate command/skill entries)`);
@@ -112733,7 +112775,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112733
112775
  if (existing) {
112734
112776
  if (!existing.isDirectory() || existing.isSymbolicLink())
112735
112777
  conflict(target);
112736
- const markerPath = join112(target, MARKER);
112778
+ const markerPath = join113(target, MARKER);
112737
112779
  if (!(await stat11(markerPath))?.isFile())
112738
112780
  conflict(target);
112739
112781
  let marker;
@@ -112752,14 +112794,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112752
112794
  if (!dryRun) {
112753
112795
  await mkdir36(skillsRoot, { recursive: true });
112754
112796
  for (const plan of plans) {
112755
- const staging = await mkdtemp5(join112(skillsRoot, ".context-install-"));
112756
- const candidate = join112(staging, "candidate");
112757
- const previous3 = join112(staging, "previous");
112797
+ const staging = await mkdtemp5(join113(skillsRoot, ".context-install-"));
112798
+ const candidate = join113(staging, "candidate");
112799
+ const previous3 = join113(staging, "previous");
112758
112800
  let moved = false;
112759
112801
  try {
112760
112802
  await cp2(plan.source, candidate, { recursive: true });
112761
112803
  if (agent === "claude") {
112762
- const skillFile = join112(candidate, "SKILL.md");
112804
+ const skillFile = join113(candidate, "SKILL.md");
112763
112805
  const content3 = await readFile94(skillFile, "utf8");
112764
112806
  const parts = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
112765
112807
  if (parts && /^\s*context-public-entry:\s*["']?false["']?\s*$/mu.test(parts[2])) {
@@ -112768,7 +112810,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112768
112810
  ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
112769
112811
  }
112770
112812
  }
112771
- await writeFile28(join112(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
112813
+ await writeFile28(join113(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
112772
112814
  `);
112773
112815
  if (plan.exists) {
112774
112816
  await rename9(plan.target, previous3);
@@ -112781,7 +112823,7 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
112781
112823
  await rename9(previous3, plan.target);
112782
112824
  throw error;
112783
112825
  }
112784
- await rm24(staging, { recursive: true, force: true });
112826
+ await rm25(staging, { recursive: true, force: true });
112785
112827
  } catch (error) {
112786
112828
  throw new ContextError(ExitCode.WorkspaceStateError, `Local skill installation failed: ${plan.target}`, {
112787
112829
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -112792,13 +112834,13 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
112792
112834
  }
112793
112835
  for (const command3 of commandPlans) {
112794
112836
  await mkdir36(dirname46(command3.target), { recursive: true });
112795
- const staging = await mkdtemp5(join112(dirname46(command3.target), ".context-install-"));
112796
- await writeFile28(join112(staging, "command"), command3.content);
112797
- await writeFile28(join112(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
112837
+ const staging = await mkdtemp5(join113(dirname46(command3.target), ".context-install-"));
112838
+ await writeFile28(join113(staging, "command"), command3.content);
112839
+ await writeFile28(join113(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
112798
112840
  `);
112799
- await rename9(join112(staging, "command"), command3.target);
112800
- await rename9(join112(staging, "marker"), command3.marker);
112801
- await rm24(staging, { recursive: true, force: true });
112841
+ await rename9(join113(staging, "command"), command3.target);
112842
+ await rename9(join113(staging, "marker"), command3.marker);
112843
+ await rm25(staging, { recursive: true, force: true });
112802
112844
  }
112803
112845
  }
112804
112846
  return formatFeedback({
@@ -112821,10 +112863,10 @@ init_cliFeedback();
112821
112863
  init_errors3();
112822
112864
  init_exitCode();
112823
112865
  import { lstat as lstat15 } from "node:fs/promises";
112824
- import { join as join113, resolve as resolve41 } from "node:path";
112866
+ import { join as join114, resolve as resolve41 } from "node:path";
112825
112867
  var HOST_DIRS = { claude: ".claude", cursor: ".cursor", codex: ".agents" };
112826
112868
  async function detectLocalAgent(agent, repo) {
112827
- const path3 = join113(repo, HOST_DIRS[agent]);
112869
+ const path3 = join114(repo, HOST_DIRS[agent]);
112828
112870
  try {
112829
112871
  const entry = await lstat15(path3);
112830
112872
  if (!entry.isDirectory() || entry.isSymbolicLink()) {
@@ -112849,7 +112891,7 @@ async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocal
112849
112891
  if (selectedAgent ? selectedAgent === "all" || agent === selectedAgent : await detect(agent, repo))
112850
112892
  agents.push(agent);
112851
112893
  }
112852
- const targets = agents.length ? agents.map((agent) => ({ agent, path: join113(repo, HOST_DIRS[agent]) })) : [{ path: join113(repo, ".agents") }];
112894
+ const targets = agents.length ? agents.map((agent) => ({ agent, path: join114(repo, HOST_DIRS[agent]) })) : [{ path: join114(repo, ".agents") }];
112853
112895
  const previews = [];
112854
112896
  for (const target of targets)
112855
112897
  previews.push(await installLocalSkills(root2, target.path, true, target.agent));
@@ -112882,7 +112924,7 @@ init_cliFeedback();
112882
112924
  init_errors3();
112883
112925
  init_exitCode();
112884
112926
  import { existsSync as existsSync35 } from "node:fs";
112885
- import { dirname as dirname48, join as join115, resolve as resolve42 } from "node:path";
112927
+ import { dirname as dirname48, join as join116, resolve as resolve42 } from "node:path";
112886
112928
  import { fileURLToPath as fileURLToPath10 } from "node:url";
112887
112929
 
112888
112930
  // src/project/pluginInstallTargets.ts
@@ -112891,9 +112933,9 @@ init_errors3();
112891
112933
  init_exitCode();
112892
112934
  import { execFile as execFile13 } from "node:child_process";
112893
112935
  import { existsSync as existsSync34 } from "node:fs";
112894
- import { cp as cp3, mkdir as mkdir37, readdir as readdir30, readFile as readFile95, rename as rename10, rm as rm25, writeFile as writeFile29 } from "node:fs/promises";
112936
+ import { cp as cp3, mkdir as mkdir37, readdir as readdir31, readFile as readFile95, rename as rename10, rm as rm26, writeFile as writeFile29 } from "node:fs/promises";
112895
112937
  import { homedir as homedir2 } from "node:os";
112896
- import { dirname as dirname47, join as join114 } from "node:path";
112938
+ import { dirname as dirname47, join as join115 } from "node:path";
112897
112939
  import { promisify as promisify13 } from "node:util";
112898
112940
  var execFileAsync7 = promisify13(execFile13);
112899
112941
  var MARKETPLACE_NAME = "c4a";
@@ -112947,23 +112989,23 @@ async function claudePluginInstalled(pluginId) {
112947
112989
  }
112948
112990
  }
112949
112991
  function codexHome() {
112950
- return process.env.CODEX_HOME?.trim() || join114(homedir2(), ".codex");
112992
+ return process.env.CODEX_HOME?.trim() || join115(homedir2(), ".codex");
112951
112993
  }
112952
112994
  function claudePluginCacheRoot() {
112953
112995
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
112954
112996
  if (explicitRoot)
112955
112997
  return explicitRoot;
112956
112998
  const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
112957
- return join114(home, ".claude", "plugins", "cache");
112999
+ return join115(home, ".claude", "plugins", "cache");
112958
113000
  }
112959
113001
  function sharedSkillsRoot() {
112960
- return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join114(homedir2(), ".agents", "skills");
113002
+ return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join115(homedir2(), ".agents", "skills");
112961
113003
  }
112962
113004
  function claudeSkillsRoot() {
112963
- return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join114(homedir2(), ".claude", "skills");
113005
+ return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join115(homedir2(), ".claude", "skills");
112964
113006
  }
112965
113007
  function cursorPluginRoot() {
112966
- return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join114(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
113008
+ return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join115(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
112967
113009
  }
112968
113010
  function blockHeader(line) {
112969
113011
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -113014,7 +113056,7 @@ function pruneLegacyCodexConfigContent(content3) {
113014
113056
  `), removed };
113015
113057
  }
113016
113058
  async function pruneLegacyCodexConfig(dryRun, steps) {
113017
- const configPath = join114(codexHome(), "config.toml");
113059
+ const configPath = join115(codexHome(), "config.toml");
113018
113060
  const current2 = await readFile95(configPath, "utf8").catch(() => "");
113019
113061
  if (!current2)
113020
113062
  return;
@@ -113031,10 +113073,10 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
113031
113073
  }
113032
113074
  }
113033
113075
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
113034
- const cacheRoot = join114(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
113076
+ const cacheRoot = join115(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
113035
113077
  if (!existsSync34(cacheRoot))
113036
113078
  return;
113037
- const versions = (await readdir30(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
113079
+ const versions = (await readdir31(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
113038
113080
  if (versions.length === 0)
113039
113081
  return;
113040
113082
  steps.push({
@@ -113043,7 +113085,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
113043
113085
  status: dryRun ? "planned" : "ran"
113044
113086
  });
113045
113087
  if (!dryRun)
113046
- await Promise.all(versions.map((version3) => rm25(join114(cacheRoot, version3), { recursive: true, force: true })));
113088
+ await Promise.all(versions.map((version3) => rm26(join115(cacheRoot, version3), { recursive: true, force: true })));
113047
113089
  }
113048
113090
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
113049
113091
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -113053,7 +113095,7 @@ async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
113053
113095
  }
113054
113096
  async function isEmptyDir2(dir) {
113055
113097
  try {
113056
- return (await readdir30(dir)).length === 0;
113098
+ return (await readdir31(dir)).length === 0;
113057
113099
  } catch {
113058
113100
  return false;
113059
113101
  }
@@ -113063,31 +113105,31 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
113063
113105
  if (!existsSync34(cacheRoot))
113064
113106
  return;
113065
113107
  const removed = [];
113066
- const marketplaces = await readdir30(cacheRoot, { withFileTypes: true }).catch(() => []);
113108
+ const marketplaces = await readdir31(cacheRoot, { withFileTypes: true }).catch(() => []);
113067
113109
  for (const marketplace of marketplaces) {
113068
113110
  if (!marketplace.isDirectory())
113069
113111
  continue;
113070
- const pluginDir = join114(cacheRoot, marketplace.name, PLUGIN_NAME);
113112
+ const pluginDir = join115(cacheRoot, marketplace.name, PLUGIN_NAME);
113071
113113
  if (!existsSync34(pluginDir))
113072
113114
  continue;
113073
- const versions = await readdir30(pluginDir, { withFileTypes: true }).catch(() => []);
113115
+ const versions = await readdir31(pluginDir, { withFileTypes: true }).catch(() => []);
113074
113116
  for (const version3 of versions) {
113075
113117
  if (!version3.isDirectory())
113076
113118
  continue;
113077
- const versionDir = join114(pluginDir, version3.name);
113078
- if (!existsSync34(join114(versionDir, ORPHAN_MARKER2)))
113119
+ const versionDir = join115(pluginDir, version3.name);
113120
+ if (!existsSync34(join115(versionDir, ORPHAN_MARKER2)))
113079
113121
  continue;
113080
113122
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
113081
113123
  if (!dryRun) {
113082
- await rm25(versionDir, { recursive: true, force: true });
113124
+ await rm26(versionDir, { recursive: true, force: true });
113083
113125
  }
113084
113126
  }
113085
113127
  if (!dryRun && await isEmptyDir2(pluginDir)) {
113086
- await rm25(pluginDir, { recursive: true, force: true });
113128
+ await rm26(pluginDir, { recursive: true, force: true });
113087
113129
  }
113088
- const marketplaceDir = join114(cacheRoot, marketplace.name);
113130
+ const marketplaceDir = join115(cacheRoot, marketplace.name);
113089
113131
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
113090
- await rm25(marketplaceDir, { recursive: true, force: true });
113132
+ await rm26(marketplaceDir, { recursive: true, force: true });
113091
113133
  }
113092
113134
  }
113093
113135
  if (removed.length > 0) {
@@ -113106,12 +113148,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
113106
113148
  return;
113107
113149
  const removed = [];
113108
113150
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
113109
- const pluginDir = join114(cacheRoot, MARKETPLACE_NAME, pluginName);
113151
+ const pluginDir = join115(cacheRoot, MARKETPLACE_NAME, pluginName);
113110
113152
  if (!existsSync34(pluginDir))
113111
113153
  continue;
113112
113154
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
113113
113155
  if (!dryRun) {
113114
- await rm25(pluginDir, { recursive: true, force: true });
113156
+ await rm26(pluginDir, { recursive: true, force: true });
113115
113157
  }
113116
113158
  }
113117
113159
  if (removed.length > 0) {
@@ -113123,12 +113165,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
113123
113165
  }
113124
113166
  }
113125
113167
  async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
113126
- const manifest = await readFile95(join114(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
113168
+ const manifest = await readFile95(join115(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
113127
113169
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
113128
113170
  if (!currentVersion)
113129
113171
  return;
113130
- const pluginDir = join114(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
113131
- const staleVersions = (await readdir30(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
113172
+ const pluginDir = join115(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
113173
+ const staleVersions = (await readdir31(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
113132
113174
  if (staleVersions.length === 0)
113133
113175
  return;
113134
113176
  steps.push({
@@ -113137,7 +113179,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
113137
113179
  status: dryRun ? "planned" : "ran"
113138
113180
  });
113139
113181
  if (!dryRun) {
113140
- await Promise.all(staleVersions.map((version3) => rm25(join114(pluginDir, version3), { recursive: true, force: true })));
113182
+ await Promise.all(staleVersions.map((version3) => rm26(join115(pluginDir, version3), { recursive: true, force: true })));
113141
113183
  }
113142
113184
  }
113143
113185
  function enableCodexPluginConfig(content3) {
@@ -113201,7 +113243,7 @@ source = ${JSON.stringify(root2)}
113201
113243
  `;
113202
113244
  }
113203
113245
  async function ensureCodexPluginEnabled() {
113204
- const configPath = join114(codexHome(), "config.toml");
113246
+ const configPath = join115(codexHome(), "config.toml");
113205
113247
  await mkdir37(dirname47(configPath), { recursive: true });
113206
113248
  const current2 = await readFile95(configPath, "utf8").catch(() => "");
113207
113249
  const next2 = enableCodexPluginConfig(current2);
@@ -113210,7 +113252,7 @@ async function ensureCodexPluginEnabled() {
113210
113252
  }
113211
113253
  }
113212
113254
  async function ensureCodexLocalMarketplace(root2) {
113213
- const configPath = join114(codexHome(), "config.toml");
113255
+ const configPath = join115(codexHome(), "config.toml");
113214
113256
  await mkdir37(dirname47(configPath), { recursive: true });
113215
113257
  const current2 = await readFile95(configPath, "utf8").catch(() => "");
113216
113258
  const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
@@ -113219,7 +113261,7 @@ async function ensureCodexLocalMarketplace(root2) {
113219
113261
  }
113220
113262
  }
113221
113263
  async function codexPluginVersion(root2) {
113222
- const manifestPath = join114(root2, "codex", ".codex-plugin", "plugin.json");
113264
+ const manifestPath = join115(root2, "codex", ".codex-plugin", "plugin.json");
113223
113265
  const manifest = JSON.parse(await readFile95(manifestPath, "utf8"));
113224
113266
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
113225
113267
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
@@ -113227,13 +113269,13 @@ async function codexPluginVersion(root2) {
113227
113269
  return manifest.version;
113228
113270
  }
113229
113271
  function codexPluginCacheDir(version3) {
113230
- return join114(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
113272
+ return join115(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
113231
113273
  }
113232
113274
  async function replaceDirectoryFromSource(source2, target) {
113233
113275
  await mkdir37(dirname47(target), { recursive: true });
113234
113276
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
113235
113277
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
113236
- await rm25(temporary, { recursive: true, force: true });
113278
+ await rm26(temporary, { recursive: true, force: true });
113237
113279
  await cp3(source2, temporary, { recursive: true, force: true });
113238
113280
  const hadPrevious = existsSync34(target);
113239
113281
  try {
@@ -113241,16 +113283,16 @@ async function replaceDirectoryFromSource(source2, target) {
113241
113283
  await rename10(target, previous3);
113242
113284
  await rename10(temporary, target);
113243
113285
  if (hadPrevious)
113244
- await rm25(previous3, { recursive: true, force: true });
113286
+ await rm26(previous3, { recursive: true, force: true });
113245
113287
  } catch (error) {
113246
- await rm25(temporary, { recursive: true, force: true });
113288
+ await rm26(temporary, { recursive: true, force: true });
113247
113289
  if (hadPrevious && !existsSync34(target) && existsSync34(previous3))
113248
113290
  await rename10(previous3, target);
113249
113291
  throw error;
113250
113292
  }
113251
113293
  }
113252
113294
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
113253
- const source2 = join114(root2, "codex");
113295
+ const source2 = join115(root2, "codex");
113254
113296
  const target = codexPluginCacheDir(version3);
113255
113297
  steps.push({
113256
113298
  agent: "codex",
@@ -113262,13 +113304,13 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
113262
113304
  await replaceDirectoryFromSource(source2, target);
113263
113305
  }
113264
113306
  async function bundledProviderSkillNames(root2) {
113265
- const skillsRoot = join114(root2, "skills");
113266
- const entries2 = await readdir30(skillsRoot, { withFileTypes: true });
113307
+ const skillsRoot = join115(root2, "skills");
113308
+ const entries2 = await readdir31(skillsRoot, { withFileTypes: true });
113267
113309
  const names = [];
113268
113310
  for (const entry of entries2) {
113269
113311
  if (!entry.isDirectory() || entry.name === "context")
113270
113312
  continue;
113271
- const skillPath = join114(skillsRoot, entry.name, "SKILL.md");
113313
+ const skillPath = join115(skillsRoot, entry.name, "SKILL.md");
113272
113314
  if (!existsSync34(skillPath))
113273
113315
  continue;
113274
113316
  const skill = await readFile95(skillPath, "utf8");
@@ -113283,10 +113325,10 @@ async function bundledProviderSkillNames(root2) {
113283
113325
  return names;
113284
113326
  }
113285
113327
  async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
113286
- const sourceRoot2 = join114(root2, "skills");
113328
+ const sourceRoot2 = join115(root2, "skills");
113287
113329
  for (const name3 of await bundledProviderSkillNames(root2)) {
113288
- const source2 = join114(sourceRoot2, name3);
113289
- const target = join114(targetRoot, name3);
113330
+ const source2 = join115(sourceRoot2, name3);
113331
+ const target = join115(targetRoot, name3);
113290
113332
  steps.push({
113291
113333
  agent,
113292
113334
  command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
@@ -113297,7 +113339,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
113297
113339
  }
113298
113340
  }
113299
113341
  async function installCursor(root2, dryRun, steps) {
113300
- const source2 = join114(root2, "cursor");
113342
+ const source2 = join115(root2, "cursor");
113301
113343
  const target = cursorPluginRoot();
113302
113344
  steps.push({
113303
113345
  agent: "cursor",
@@ -113352,12 +113394,12 @@ async function installCodex(root2, dryRun, steps) {
113352
113394
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
113353
113395
  steps.push({
113354
113396
  agent: "codex",
113355
- command: `ensure ${shellQuote8(join114(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
113397
+ command: `ensure ${shellQuote8(join115(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
113356
113398
  status: dryRun ? "planned" : "ran"
113357
113399
  });
113358
113400
  steps.push({
113359
113401
  agent: "codex",
113360
- command: `ensure ${shellQuote8(join114(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
113402
+ command: `ensure ${shellQuote8(join115(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
113361
113403
  status: dryRun ? "planned" : "ran"
113362
113404
  });
113363
113405
  if (dryRun) {
@@ -113412,13 +113454,13 @@ function pluginRootCandidates() {
113412
113454
  return [resolve42(envRoot)];
113413
113455
  const candidates = [];
113414
113456
  for (const dir of packageCandidateDirs()) {
113415
- candidates.push(join115(dir, "plugins"));
113416
- candidates.push(join115(dir, "dist", "plugins"));
113457
+ candidates.push(join116(dir, "plugins"));
113458
+ candidates.push(join116(dir, "dist", "plugins"));
113417
113459
  }
113418
113460
  return [...new Set(candidates)];
113419
113461
  }
113420
113462
  function isInstallablePluginRoot(root2) {
113421
- return existsSync35(join115(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join115(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join115(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join115(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join115(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join115(root2, "skills"));
113463
+ return existsSync35(join116(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join116(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join116(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join116(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join116(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join116(root2, "skills"));
113422
113464
  }
113423
113465
  function resolveBundledPluginsRoot() {
113424
113466
  const candidates = pluginRootCandidates();
@@ -113665,10 +113707,10 @@ function readQuickstartPath() {
113665
113707
  try {
113666
113708
  let dir = dirname49(fileURLToPath11(import.meta.url));
113667
113709
  for (let i2 = 0;i2 < 8; i2++) {
113668
- const candidate = join116(dir, "docs", "quickstart.md");
113710
+ const candidate = join117(dir, "docs", "quickstart.md");
113669
113711
  if (existsSync36(candidate))
113670
113712
  return candidate;
113671
- const pkg = join116(dir, "package.json");
113713
+ const pkg = join117(dir, "package.json");
113672
113714
  if (existsSync36(pkg))
113673
113715
  return candidate;
113674
113716
  const parent = dirname49(dir);
@@ -113677,7 +113719,7 @@ function readQuickstartPath() {
113677
113719
  dir = parent;
113678
113720
  }
113679
113721
  } catch {}
113680
- return join116(dirname49(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
113722
+ return join117(dirname49(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
113681
113723
  }
113682
113724
  var GREEN = "\x1B[32m";
113683
113725
  var RESET = "\x1B[0m";