@c4a/context-cli 0.7.10 → 0.7.11

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.
Files changed (37) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +3 -3
  3. package/cli.js +1111 -402
  4. package/indexers/bundles/context-code-indexer/references/indexer.md +11 -1
  5. package/indexers/bundles/context-markdown-indexer/references/indexer.md +7 -2
  6. package/indexers/bundles/context-markdown-indexer/references/semantic-planning.md +9 -6
  7. package/indexers/contracts/profile-contract.json +245 -245
  8. package/indexers/release-manifest.json +6 -6
  9. package/package.json +12 -12
  10. package/parserEntryWorker.js +26 -2
  11. package/plugins/README.md +1 -1
  12. package/plugins/README_CN.md +1 -1
  13. package/plugins/VERSION +1 -1
  14. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  15. package/plugins/codex/.codex-plugin/plugin.json +2 -2
  16. package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
  17. package/plugins/skills/context-code-indexer/references/indexer.md +11 -1
  18. package/plugins/skills/context-markdown-indexer/references/indexer.md +7 -2
  19. package/plugins/skills/context-markdown-indexer/references/semantic-planning.md +9 -6
  20. package/providers/context/graphs/workspace.yaml +1 -22
  21. package/providers/context/manifest.json +26 -62
  22. package/providers/context/provider.yaml +1 -1
  23. package/providers/context/resources/manuals/guides/knowledge-updates.md +80 -3
  24. package/providers/context/resources/manuals/guides/package-outputs.md +39 -1
  25. package/providers/context/resources/manuals/reference/project-api.md +21 -2
  26. package/providers/context/resources/procedures/knowledge-review.md +18 -2
  27. package/providers/context/resources/procedures/knowledge-updates.md +80 -3
  28. package/providers/context/resources/procedures/package-output.md +18 -0
  29. package/providers/context/resources/procedures/production-stage-files.md +21 -0
  30. package/providers/context/resources/procedures/repository-source-recovery.md +5 -3
  31. package/providers/context/resources/procedures/task-recovery.md +6 -0
  32. package/providers/context/resources/procedures/work-start-report.md +14 -7
  33. package/providers/context/resources/templates/work-start-report.md +11 -6
  34. package/providers/context/actions/inspect-repository-recovery.yaml +0 -6
  35. package/providers/context/actions/restore-repository-sources.yaml +0 -7
  36. package/providers/context/resources/dialogue/repository-source-recovery.md +0 -23
  37. package/providers/context/schemas/repository-source-recovery.schema.json +0 -40
package/cli.js CHANGED
@@ -32029,7 +32029,17 @@ ${end.comment}` : end.comment;
32029
32029
  });
32030
32030
 
32031
32031
  // ../../node_modules/.bun/zod-to-json-schema@3.25.2+27912429049419a2/node_modules/zod-to-json-schema/dist/esm/Options.js
32032
- var ignoreOverride, defaultOptions, getDefaultOptions = (options) => typeof options === "string" ? {
32032
+ var ignoreOverride, jsonDescription = (jsonSchema, def) => {
32033
+ if (def.description) {
32034
+ try {
32035
+ return {
32036
+ ...jsonSchema,
32037
+ ...JSON.parse(def.description)
32038
+ };
32039
+ } catch {}
32040
+ }
32041
+ return jsonSchema;
32042
+ }, defaultOptions, getDefaultOptions = (options) => typeof options === "string" ? {
32033
32043
  ...defaultOptions,
32034
32044
  name: options
32035
32045
  } : {
@@ -33397,6 +33407,54 @@ var init_zodToJsonSchema = __esm(() => {
33397
33407
  });
33398
33408
 
33399
33409
  // ../../node_modules/.bun/zod-to-json-schema@3.25.2+27912429049419a2/node_modules/zod-to-json-schema/dist/esm/index.js
33410
+ var exports_esm = {};
33411
+ __export(exports_esm, {
33412
+ zodToJsonSchema: () => zodToJsonSchema,
33413
+ zodPatterns: () => zodPatterns,
33414
+ setResponseValueAndErrors: () => setResponseValueAndErrors,
33415
+ selectParser: () => selectParser,
33416
+ primitiveMappings: () => primitiveMappings,
33417
+ parseUnknownDef: () => parseUnknownDef,
33418
+ parseUnionDef: () => parseUnionDef,
33419
+ parseUndefinedDef: () => parseUndefinedDef,
33420
+ parseTupleDef: () => parseTupleDef,
33421
+ parseStringDef: () => parseStringDef,
33422
+ parseSetDef: () => parseSetDef,
33423
+ parseRecordDef: () => parseRecordDef,
33424
+ parseReadonlyDef: () => parseReadonlyDef,
33425
+ parsePromiseDef: () => parsePromiseDef,
33426
+ parsePipelineDef: () => parsePipelineDef,
33427
+ parseOptionalDef: () => parseOptionalDef,
33428
+ parseObjectDef: () => parseObjectDef,
33429
+ parseNumberDef: () => parseNumberDef,
33430
+ parseNullableDef: () => parseNullableDef,
33431
+ parseNullDef: () => parseNullDef,
33432
+ parseNeverDef: () => parseNeverDef,
33433
+ parseNativeEnumDef: () => parseNativeEnumDef,
33434
+ parseMapDef: () => parseMapDef,
33435
+ parseLiteralDef: () => parseLiteralDef,
33436
+ parseIntersectionDef: () => parseIntersectionDef,
33437
+ parseEnumDef: () => parseEnumDef,
33438
+ parseEffectsDef: () => parseEffectsDef,
33439
+ parseDefaultDef: () => parseDefaultDef,
33440
+ parseDef: () => parseDef,
33441
+ parseDateDef: () => parseDateDef,
33442
+ parseCatchDef: () => parseCatchDef,
33443
+ parseBrandedDef: () => parseBrandedDef,
33444
+ parseBooleanDef: () => parseBooleanDef,
33445
+ parseBigintDef: () => parseBigintDef,
33446
+ parseArrayDef: () => parseArrayDef,
33447
+ parseAnyDef: () => parseAnyDef,
33448
+ jsonDescription: () => jsonDescription,
33449
+ ignoreOverride: () => ignoreOverride,
33450
+ getRelativePath: () => getRelativePath,
33451
+ getRefs: () => getRefs,
33452
+ getDefaultOptions: () => getDefaultOptions,
33453
+ defaultOptions: () => defaultOptions,
33454
+ default: () => esm_default,
33455
+ addErrorMessage: () => addErrorMessage
33456
+ });
33457
+ var esm_default;
33400
33458
  var init_esm = __esm(() => {
33401
33459
  init_zodToJsonSchema();
33402
33460
  init_Options();
@@ -33430,17 +33488,42 @@ var init_esm = __esm(() => {
33430
33488
  init_unknown();
33431
33489
  init_selectParser();
33432
33490
  init_zodToJsonSchema();
33491
+ esm_default = zodToJsonSchema;
33433
33492
  });
33434
33493
 
33435
33494
  // ../context/src/packageSite.ts
33436
- var packageSiteSchema;
33495
+ var siteHrefSchema, packageSiteHomeActionSchema, packageSiteHomeResourceSchema, packageSiteHomeSchema, packageSiteSchema;
33437
33496
  var init_packageSite = __esm(() => {
33438
33497
  init_zod();
33498
+ siteHrefSchema = exports_external.string().trim().min(1).refine((value) => /^(?:https?:\/\/|mailto:|\/(?!\/)|#)/u.test(value), "Use an https URL, mailto URL, root-relative path, or page anchor");
33499
+ packageSiteHomeActionSchema = exports_external.object({
33500
+ text: exports_external.string().trim().min(1),
33501
+ link: siteHrefSchema,
33502
+ theme: exports_external.enum(["brand", "alt"]).optional()
33503
+ }).strict();
33504
+ packageSiteHomeResourceSchema = exports_external.object({
33505
+ title: exports_external.string().trim().min(1),
33506
+ description: exports_external.string().trim().min(1).optional(),
33507
+ href: siteHrefSchema.optional(),
33508
+ action: exports_external.string().trim().min(1).optional(),
33509
+ command: exports_external.string().trim().min(1).optional(),
33510
+ featured: exports_external.boolean().optional()
33511
+ }).strict().refine((value) => value.href !== undefined || value.command !== undefined, {
33512
+ message: "A homepage resource requires href or command"
33513
+ });
33514
+ packageSiteHomeSchema = exports_external.object({
33515
+ title: exports_external.string().trim().min(1).optional(),
33516
+ slogan: exports_external.string().trim().min(1).optional(),
33517
+ description: exports_external.string().trim().min(1).optional(),
33518
+ actions: exports_external.array(packageSiteHomeActionSchema).optional(),
33519
+ resources: exports_external.array(packageSiteHomeResourceSchema).optional()
33520
+ }).strict();
33439
33521
  packageSiteSchema = exports_external.object({
33440
33522
  title: exports_external.string().trim().min(1).optional(),
33441
33523
  description: exports_external.string().optional(),
33442
33524
  lang: exports_external.string().min(1).default("en-US"),
33443
- base: exports_external.string().regex(/^\/(?:[a-zA-Z0-9_-]+\/)*$/, "Use / or a slash-delimited deployment path, such as /docs/").default("/")
33525
+ base: exports_external.string().regex(/^\/(?:[a-zA-Z0-9_-]+\/)*$/, "Use / or a slash-delimited deployment path, such as /docs/").default("/"),
33526
+ home: packageSiteHomeSchema.optional()
33444
33527
  }).strict();
33445
33528
  });
33446
33529
 
@@ -55119,6 +55202,7 @@ async function withProjectWriteLock(projectRoot, name, action) {
55119
55202
  owner: lockOwnerDetail(owner),
55120
55203
  next_action: {
55121
55204
  kind: processState === "running" ? "wait-for-active-context-command" : "inspect-project-write-lock",
55205
+ ...processState === "not-running" ? { command: "context task recover --format json" } : {},
55122
55206
  message: processState === "running" ? "Keep polling the existing Context command until it returns an exit code and receipt; do not start another write command." : "No active owner could be confirmed. Inspect the runtime lock and the previous Context process before retrying; do not delete a lock owned by a running process."
55123
55207
  },
55124
55208
  next: processState === "running" ? "Wait for the running context command to finish, then retry." : "Inspect the workspace runtime lock and previous Context process before retrying."
@@ -55673,6 +55757,40 @@ function inlineLinksFromTree(content3, tree) {
55673
55757
  }
55674
55758
  function replaceMarkdownInlineLinkTargets(content3, replacement) {
55675
55759
  const links = markdownInlineLinks(content3);
55760
+ if (content3.includes("]:")) {
55761
+ const tree = unified().use(remarkParse).parse(content3);
55762
+ const visit2 = (node3) => {
55763
+ if (node3.type === "definition" && node3.url !== undefined) {
55764
+ const start = node3.position?.start?.offset;
55765
+ const end = node3.position?.end?.offset;
55766
+ if (start !== undefined && end !== undefined) {
55767
+ const raw = content3.slice(start, end);
55768
+ const prefix = /^\[[^\n]+\]:\s*/u.exec(raw);
55769
+ if (prefix) {
55770
+ const offset = prefix[0].length;
55771
+ const angle = raw[offset] === "<";
55772
+ const match = angle ? /^<([^>]*)>/u.exec(raw.slice(offset)) : /^((?:\\.|[^\s])+)/u.exec(raw.slice(offset));
55773
+ if (match) {
55774
+ const targetStart = start + offset + (angle ? 1 : 0);
55775
+ links.push({
55776
+ image: false,
55777
+ label: node3.identifier ?? "",
55778
+ target: match[1],
55779
+ start,
55780
+ end,
55781
+ targetStart,
55782
+ targetEnd: targetStart + match[1].length
55783
+ });
55784
+ }
55785
+ }
55786
+ }
55787
+ }
55788
+ for (const child of node3.children ?? [])
55789
+ visit2(child);
55790
+ };
55791
+ visit2(tree);
55792
+ links.sort((a, b) => a.targetStart - b.targetStart);
55793
+ }
55676
55794
  let cursor = 0;
55677
55795
  let output = "";
55678
55796
  for (const link of links) {
@@ -63603,8 +63721,9 @@ function validateProductionStage(value) {
63603
63721
  throw new TypeError("An unavailable source requires an explicit gap and pending investigation");
63604
63722
  }
63605
63723
  for (const usage of stage.indexer_usage) {
63606
- if (usage.scopes.some((scope2) => !scopes.has(scope2)))
63607
- throw new TypeError("Indexer usage cannot extend the authorized stage scope");
63724
+ const invalid = usage.scopes.filter((scope2) => !scopes.has(scope2));
63725
+ if (invalid.length)
63726
+ throw new TypeError(`indexer_usage.scopes contains unauthorized source refs: ${invalid.join(", ")}. Use stage.scopes source refs (${[...scopes.keys()].join(", ")}), not collection names. This is not an Indexer registration error.`);
63608
63727
  }
63609
63728
  const visited = new Set;
63610
63729
  const visiting = new Set;
@@ -63624,7 +63743,9 @@ function validateProductionStage(value) {
63624
63743
  visited.add(task.id);
63625
63744
  }
63626
63745
  for (const task of stage.tasks) {
63627
- indexerKnowledgeCollectionSchema2.parse(task.path.split("/")[0]);
63746
+ if (!indexerKnowledgeCollectionSchema2.safeParse(task.path.split("/")[0]).success) {
63747
+ throw new TypeError(`Article path "${task.path}" must be relative to knowledge/, e.g. business/example.md (without the knowledge/ prefix). Valid collections: ${TOP_LEVEL_NAMESPACES.join(", ")}. Correct the article path, not indexer_usage.scopes.`);
63748
+ }
63628
63749
  if (!isSafeKnowledgeTargetPath(task.path.split("/")[0], task.path))
63629
63750
  throw new TypeError(`Unsafe article target for ${task.id}`);
63630
63751
  if (task.input !== productionTaskInput(task))
@@ -63712,7 +63833,7 @@ var init_productionStage = __esm(() => {
63712
63833
  skills: exports_external.array(exports_external.object({ name, entry: name.optional() }).strict()).default([])
63713
63834
  }).strict();
63714
63835
  productionIndexerUsageSchema = exports_external.object({
63715
- scopes: exports_external.array(name).min(1),
63836
+ scopes: exports_external.array(name).min(1).describe("Authorized source refs from stage.scopes, e.g. note:20260913/decision.md; not knowledge collection names"),
63716
63837
  skills: exports_external.array(name).min(1),
63717
63838
  purpose: name
63718
63839
  }).strict();
@@ -64632,12 +64753,14 @@ Restore the authorized source and retry preparation.
64632
64753
  "",
64633
64754
  ...scopes.map((scope2) => `- ${scope2.scope}: ${join25(directory, productionSourceFile(scope2.scope))}`),
64634
64755
  "",
64635
- "Use code skeletons and document outlines first; selectively read full material to decide reader topics and batches. Multiple skills may investigate one module. Do not parse all code or maintain per-symbol disposition just to plan.",
64756
+ "Use code skeletons and document outlines to identify the authorized capability families and document tasks, then selectively read full material to decide reader topics. Navigation is not a complete feature inventory. Keep unchecked scope pending; do not parse all code or maintain per-symbol disposition just to plan.",
64636
64757
  "Scale planning to the current request. For one or two documents or a clearly bounded module, decide which articles to add or revise and where they belong; do not redesign the whole knowledge base. Start with related existing topics, expand reading only when needed, and reuse applicable decisions. A large module may need several topics, but not investigation of unrelated modules.",
64637
- "Use one writing batch unless actual dependencies or useful parallel work justify more. Do not invent dependencies, taxonomy, page counts or extra investigation to fill plan fields. Leave unrelated unfinished scope pending rather than treating it as completed.",
64758
+ "Separate the whole requested outcome from the current writing batch. Use one batch unless actual dependencies or useful parallel work justify more; do not invent page counts or dependencies. A first useful delivery does not settle remaining authorized work.",
64759
+ "Use question and brief to describe the reader task and useful depth: a checked file/symbol or document section with a concrete next step for navigation, or the behavior, conditions and steps needed for explanation. Reuse or revise existing articles without replacing valid detail with generic summaries; split distinct tasks, not sources or symbols.",
64638
64760
  ...request.reassess.length ? [`Reassess earlier content exclusions: ${request.reassess.join(", ")}. Their source material changed or is unavailable. The stored decisions were preserved but no longer suppress investigation.`] : [],
64639
64761
  "Keep user-confirmed long-term exclusions in the existing requirements file. For a content-based exclusion, retain source_baselines from the supplied stage scopes for the material actually read; changed material is investigated again. Do not turn a temporary failure or an unapproved suggestion into a permanent exclusion.",
64640
64762
  "Declare available relevant skills and whether you can coordinate multiple Agents. Article sources may cross registered source and skill boundaries. Batch dependencies in after name article paths.",
64763
+ "Article path is relative to knowledge/ (for example business/example.md, not knowledge/business/example.md). indexer_usage.scopes names authorized source refs from the stage, not knowledge collections. Declare skills here; no separate Indexer registry is required.",
64641
64764
  "List remaining investigation in pending_scopes when submitting a partial plan. This is source/module-level progress, not a per-file ledger. Omit it on a writing amendment to preserve the remaining scope; submit an explicit list to update it. Unresolved material gaps cannot be cleared by declaring their investigation complete.",
64642
64765
  `Write the plan to ${productionAgentDirectory(stage.id)}/submissions/plan.yaml and use the current action command. This does not approve the work-start report.`,
64643
64766
  ""
@@ -64784,7 +64907,7 @@ var init_productionPlanning = __esm(() => {
64784
64907
  stage: text5,
64785
64908
  capabilities: productionCapabilitiesSchema,
64786
64909
  articles: exports_external.array(exports_external.object({
64787
- path: text5,
64910
+ path: text5.describe("Relative to knowledge/, e.g. business/example.md; do not prefix knowledge/"),
64788
64911
  question: text5,
64789
64912
  sources: exports_external.array(text5).min(1),
64790
64913
  batch: text5,
@@ -66152,6 +66275,77 @@ var init_knowledgeAssetRepair = __esm(() => {
66152
66275
  init_assetSourceRegistry();
66153
66276
  });
66154
66277
 
66278
+ // src/project/reviewApplyIndexer.ts
66279
+ var exports_reviewApplyIndexer = {};
66280
+ __export(exports_reviewApplyIndexer, {
66281
+ renderApprovedIndexerMarkdown: () => renderApprovedIndexerMarkdown
66282
+ });
66283
+ function escapeHtmlAttribute(value) {
66284
+ return value.replace(/&/gu, "&amp;").replace(/"/gu, "&quot;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
66285
+ }
66286
+ function sectionMarkdown(section) {
66287
+ return [
66288
+ `<!-- context:section id="${escapeHtmlAttribute(section.section_key)}" -->`,
66289
+ "",
66290
+ section.markdown.trimEnd(),
66291
+ "",
66292
+ "<!-- /context:section -->"
66293
+ ].join(`
66294
+ `);
66295
+ }
66296
+ function renderApprovedIndexerMarkdown(input) {
66297
+ if (input.record.approved_revision !== undefined) {
66298
+ const content3 = compactApprovedKnowledgeMarkdown(ensureApprovedKnowledgePresentation(input.record.body));
66299
+ return content3.replace(/^---\r?\n([\s\S]*?)\r?\n---/u, (_match, header) => {
66300
+ const metadata = import_yaml25.default.parse(header);
66301
+ const reclassified = input.record.approved_revision?.previous_path !== undefined && input.record.approved_revision.previous_path.split("/")[0] !== input.record.collection;
66302
+ return ["---", import_yaml25.default.stringify({
66303
+ ...metadata,
66304
+ type: reclassified ? okfTypeForCollection(input.record.collection) : metadata.type ?? okfTypeForCollection(input.record.collection),
66305
+ timestamp: input.timestamp
66306
+ }).trimEnd(), "---"].join(`
66307
+ `);
66308
+ });
66309
+ }
66310
+ const binding = input.record.indexer_candidate;
66311
+ if (input.record.candidate_type !== "indexer-artifact" || binding === undefined) {
66312
+ throw new TypeError("Indexer approved renderer requires an indexer-artifact Candidate");
66313
+ }
66314
+ const title = input.record.review.title;
66315
+ const body = binding.sections.flatMap((section, index2) => [
66316
+ ...index2 === 0 ? [] : [""],
66317
+ sectionMarkdown(section)
66318
+ ]).join(`
66319
+ `);
66320
+ const description = readerKnowledgeDescription({
66321
+ description: input.record.review.summary,
66322
+ markdown: body,
66323
+ title
66324
+ });
66325
+ const frontmatter = import_yaml25.default.stringify({
66326
+ title,
66327
+ type: okfTypeForCollection(input.record.collection),
66328
+ description,
66329
+ timestamp: input.timestamp
66330
+ }).trimEnd();
66331
+ return [
66332
+ "---",
66333
+ frontmatter,
66334
+ "---",
66335
+ "",
66336
+ ensureMarkdownPageTitle(body, title),
66337
+ ""
66338
+ ].join(`
66339
+ `);
66340
+ }
66341
+ var import_yaml25;
66342
+ var init_reviewApplyIndexer = __esm(() => {
66343
+ init_okfTypes();
66344
+ init_packageKnowledgeProjection();
66345
+ init_approvedKnowledgeMetadata();
66346
+ import_yaml25 = __toESM(require_dist(), 1);
66347
+ });
66348
+
66155
66349
  // src/project/approvedRevisionBatch.ts
66156
66350
  var exports_approvedRevisionBatch = {};
66157
66351
  __export(exports_approvedRevisionBatch, {
@@ -66208,7 +66402,8 @@ async function approvedRevisionCandidateApplied(root, candidate, applied, closed
66208
66402
  return false;
66209
66403
  if (!closed && applied === candidate.body)
66210
66404
  return true;
66211
- const expected = revisionComparableMarkdown(candidate.body);
66405
+ const { renderApprovedIndexerMarkdown: renderApprovedIndexerMarkdown2 } = await Promise.resolve().then(() => (init_reviewApplyIndexer(), exports_reviewApplyIndexer));
66406
+ const expected = revisionComparableMarkdown(renderApprovedIndexerMarkdown2({ record: candidate, timestamp: candidate.updated }));
66212
66407
  const approved = revisionComparableMarkdown(applied);
66213
66408
  if (expected === approved)
66214
66409
  return true;
@@ -66224,9 +66419,9 @@ async function approvedRevisionCandidateApplied(root, candidate, applied, closed
66224
66419
  function revisionComparableMarkdown(markdown) {
66225
66420
  const compact = compactApprovedKnowledgeMarkdown(ensureApprovedKnowledgePresentation(markdown));
66226
66421
  return compact.replace(/^---\r?\n([\s\S]*?)\r?\n---/u, (_match, header) => {
66227
- const metadata = import_yaml25.default.parse(header);
66422
+ const metadata = import_yaml26.default.parse(header);
66228
66423
  const { timestamp: _timestamp, ...content3 } = metadata;
66229
- return ["---", import_yaml25.default.stringify(content3).trimEnd(), "---"].join(`
66424
+ return ["---", import_yaml26.default.stringify(content3).trimEnd(), "---"].join(`
66230
66425
  `);
66231
66426
  });
66232
66427
  }
@@ -66266,7 +66461,7 @@ async function observeApprovedRevisionBatch(root, request) {
66266
66461
  ...candidates.some((candidate) => candidate.status === "rejected") ? { revision_pending: true } : {}
66267
66462
  };
66268
66463
  }
66269
- var import_yaml25;
66464
+ var import_yaml26;
66270
66465
  var init_approvedRevisionBatch = __esm(() => {
66271
66466
  init_src2();
66272
66467
  init_approvedRevision();
@@ -66275,7 +66470,7 @@ var init_approvedRevisionBatch = __esm(() => {
66275
66470
  init_approvedKnowledgeMetadata();
66276
66471
  init_durableSingleFileTransaction();
66277
66472
  init_knowledgeAssetRepair();
66278
- import_yaml25 = __toESM(require_dist(), 1);
66473
+ import_yaml26 = __toESM(require_dist(), 1);
66279
66474
  });
66280
66475
 
66281
66476
  // src/project/verifyFrontmatter.ts
@@ -66291,7 +66486,7 @@ function isDeprecatedApprovedMarkdown(content3) {
66291
66486
  if (end < 0)
66292
66487
  return false;
66293
66488
  try {
66294
- const parsed = import_yaml26.default.parse(content3.slice(4, end));
66489
+ const parsed = import_yaml27.default.parse(content3.slice(4, end));
66295
66490
  return isRecord7(parsed) && parsed.deprecated === true;
66296
66491
  } catch {
66297
66492
  return false;
@@ -66310,7 +66505,7 @@ function parseFrontmatter3(content3, path2, issues) {
66310
66505
  return;
66311
66506
  }
66312
66507
  try {
66313
- const parsed = import_yaml26.default.parse(content3.slice(4, end));
66508
+ const parsed = import_yaml27.default.parse(content3.slice(4, end));
66314
66509
  if (!isRecord7(parsed)) {
66315
66510
  issues.push({ severity: "error", code: "frontmatter-invalid", path: path2, line: 1, message: "frontmatter must be a YAML object" });
66316
66511
  return;
@@ -66336,7 +66531,7 @@ function parseFrontmatterLoose(content3) {
66336
66531
  if (end < 0)
66337
66532
  return {};
66338
66533
  try {
66339
- const parsed = import_yaml26.default.parse(content3.slice(4, end));
66534
+ const parsed = import_yaml27.default.parse(content3.slice(4, end));
66340
66535
  return isRecord7(parsed) ? parsed : {};
66341
66536
  } catch {
66342
66537
  return {};
@@ -66406,10 +66601,10 @@ async function validateApprovedMarkdown(input) {
66406
66601
  });
66407
66602
  }
66408
66603
  }
66409
- var import_yaml26;
66604
+ var import_yaml27;
66410
66605
  var init_verifyFrontmatter = __esm(() => {
66411
66606
  init_okfTypes();
66412
- import_yaml26 = __toESM(require_dist(), 1);
66607
+ import_yaml27 = __toESM(require_dist(), 1);
66413
66608
  });
66414
66609
 
66415
66610
  // src/project/indexerTemplateSnapshots.ts
@@ -67297,7 +67492,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67297
67492
  if (error.code !== "ENOENT")
67298
67493
  throw error;
67299
67494
  }
67300
- const structure = before === undefined ? {} : import_yaml27.default.parse(before);
67495
+ const structure = before === undefined ? {} : import_yaml28.default.parse(before);
67301
67496
  if (!structure || typeof structure !== "object" || Array.isArray(structure))
67302
67497
  throw new TypeError("Invalid knowledge structure");
67303
67498
  const articles = new Map(approvedKnowledgeSnapshotsFromStructure(structure).map((article) => [article.article_id, article]));
@@ -67321,7 +67516,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67321
67516
  articles.set(article.article_id, article);
67322
67517
  }
67323
67518
  const entries2 = validateArticleStructureEntries([...articles.values()]);
67324
- const content3 = import_yaml27.default.stringify({
67519
+ const content3 = import_yaml28.default.stringify({
67325
67520
  ...structure,
67326
67521
  articles: entries2.sort((a, b) => a.article_id.localeCompare(b.article_id))
67327
67522
  });
@@ -67335,12 +67530,12 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67335
67530
  content: content3
67336
67531
  };
67337
67532
  }
67338
- var import_yaml27, STRUCTURE_PATH2 = "knowledge/structure.yaml";
67533
+ var import_yaml28, STRUCTURE_PATH2 = "knowledge/structure.yaml";
67339
67534
  var init_approvedKnowledgeSnapshots = __esm(() => {
67340
67535
  init_src2();
67341
67536
  init_approvedKnowledgeMetadata();
67342
67537
  init_durableSingleFileTransaction();
67343
- import_yaml27 = __toESM(require_dist(), 1);
67538
+ import_yaml28 = __toESM(require_dist(), 1);
67344
67539
  });
67345
67540
 
67346
67541
  // src/runtimeEventOutbox.ts
@@ -69378,7 +69573,7 @@ function parseFrontmatter4(content3) {
69378
69573
  const match = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(content3);
69379
69574
  if (match?.[1] === undefined)
69380
69575
  return {};
69381
- const parsed = import_yaml28.default.parse(match[1]);
69576
+ const parsed = import_yaml29.default.parse(match[1]);
69382
69577
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
69383
69578
  }
69384
69579
  function isDeprecated(content3) {
@@ -69439,7 +69634,7 @@ async function writeApprovedStructureProjection(projectRoot) {
69439
69634
  const { inputHash, structure, compactFiles } = await deriveApprovedStructure(projectRoot);
69440
69635
  const outputPath = join48(projectRoot, STRUCTURE_PATH4);
69441
69636
  await mkdir17(dirname21(outputPath), { recursive: true });
69442
- await writeFile11(outputPath, import_yaml28.default.stringify(structure), "utf8");
69637
+ await writeFile11(outputPath, import_yaml29.default.stringify(structure), "utf8");
69443
69638
  await Promise.all(compactFiles.map((file) => writeFile11(file.absPath, file.content, "utf8")));
69444
69639
  return { inputHash, articles: structure.articles.length, structure: STRUCTURE_PATH4 };
69445
69640
  }
@@ -69507,7 +69702,7 @@ async function closeProjectWorkspace(projectRoot) {
69507
69702
  }
69508
69703
  const outputPath = join48(projectRoot, STRUCTURE_PATH4);
69509
69704
  await mkdir17(dirname21(outputPath), { recursive: true });
69510
- await writeFile11(outputPath, `${import_yaml28.default.stringify(structure)}`, "utf8");
69705
+ await writeFile11(outputPath, `${import_yaml29.default.stringify(structure)}`, "utf8");
69511
69706
  await Promise.all(compactFiles.map((file) => writeFile11(file.absPath, file.content, "utf8")));
69512
69707
  const { readTaskRollback } = await Promise.resolve().then(() => (init_taskRollback(), exports_taskRollback));
69513
69708
  if (!production && !await readTaskRollback(projectRoot))
@@ -69558,7 +69753,7 @@ async function runProjectCloseCommand(input) {
69558
69753
  }
69559
69754
  return true;
69560
69755
  }
69561
- var import_yaml28, KNOWLEDGE_ROOT = "knowledge", STRUCTURE_PATH4, STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
69756
+ var import_yaml29, KNOWLEDGE_ROOT = "knowledge", STRUCTURE_PATH4, STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
69562
69757
  var init_close = __esm(() => {
69563
69758
  init_indexerRequiredArticleReview();
69564
69759
  init_approvedFileRead();
@@ -69579,7 +69774,7 @@ var init_close = __esm(() => {
69579
69774
  init_candidateLedger();
69580
69775
  init_knowledgeAssetRepair();
69581
69776
  init_approvedKnowledgeMetadata();
69582
- import_yaml28 = __toESM(require_dist(), 1);
69777
+ import_yaml29 = __toESM(require_dist(), 1);
69583
69778
  STRUCTURE_PATH4 = join48(KNOWLEDGE_ROOT, "structure.yaml");
69584
69779
  });
69585
69780
 
@@ -69843,7 +70038,7 @@ async function optionalText(root, path2) {
69843
70038
  }
69844
70039
  async function readKnowledgeMap(root) {
69845
70040
  const content3 = await optionalText(root, KNOWLEDGE_MAP_PATH);
69846
- return content3 === undefined ? undefined : validateKnowledgeMap(import_yaml29.parse(content3));
70041
+ return content3 === undefined ? undefined : validateKnowledgeMap(import_yaml30.parse(content3));
69847
70042
  }
69848
70043
  async function applyKnowledgeMapUpdate(projectRoot, update) {
69849
70044
  return withProjectWriteLock(projectRoot, "adjust-knowledge-map", async () => {
@@ -69855,7 +70050,7 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
69855
70050
  const preview = previewText === undefined ? undefined : JSON.parse(previewText);
69856
70051
  const planned = preview?.topics?.flatMap((topic) => topic.article_targets ?? []) ?? [];
69857
70052
  assertKnowledgeMapCoverage(next, approved, { known: [...approved, ...planned], current_revision: current?.revision ?? null });
69858
- const content3 = import_yaml29.stringify(next);
70053
+ const content3 = import_yaml30.stringify(next);
69859
70054
  const previous2 = await optionalText(projectRoot, KNOWLEDGE_MAP_PATH);
69860
70055
  await runDurableMultiFileTransaction({
69861
70056
  projectRoot,
@@ -69876,14 +70071,14 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
69876
70071
  };
69877
70072
  });
69878
70073
  }
69879
- var import_yaml29, KNOWLEDGE_MAP_PATH = "src/knowledge-map.yaml";
70074
+ var import_yaml30, KNOWLEDGE_MAP_PATH = "src/knowledge-map.yaml";
69880
70075
  var init_knowledgeMap2 = __esm(() => {
69881
70076
  init_knowledgeMapCoverage();
69882
70077
  init_src2();
69883
70078
  init_durableSingleFileTransaction();
69884
70079
  init_durableMultiFileTransaction();
69885
70080
  init_writeLock();
69886
- import_yaml29 = __toESM(require_dist(), 1);
70081
+ import_yaml30 = __toESM(require_dist(), 1);
69887
70082
  });
69888
70083
 
69889
70084
  // src/project/packageKnowledgeMap.ts
@@ -70157,7 +70352,7 @@ async function optionalWorkspaceText(root, path2) {
70157
70352
  }
70158
70353
  async function readWorkspaceChangelog(root) {
70159
70354
  const value = await optionalWorkspaceText(root, "changelog.yaml");
70160
- return value === undefined ? [] : ledgerSchema.parse(import_yaml30.parse(value)).entries;
70355
+ return value === undefined ? [] : ledgerSchema.parse(import_yaml31.parse(value)).entries;
70161
70356
  }
70162
70357
  async function workspaceVersion(root) {
70163
70358
  const manifest = JSON.parse(await readFile45(join55(root, "package.json"), "utf8"));
@@ -70299,7 +70494,7 @@ async function recordWorkspaceVersion(root, value) {
70299
70494
  const writes = {
70300
70495
  "package.json": JSON.stringify(manifest, null, 2) + `
70301
70496
  `,
70302
- "changelog.yaml": import_yaml30.stringify({ entries: entries2 }),
70497
+ "changelog.yaml": import_yaml31.stringify({ entries: entries2 }),
70303
70498
  "CHANGELOG.md": renderChangelog(entries2),
70304
70499
  ".context-version.json": JSON.stringify({ version: entry.version, files: status.files }) + `
70305
70500
  `
@@ -70313,13 +70508,13 @@ async function recordWorkspaceVersion(root, value) {
70313
70508
  return { version: entry.version, next_action: { command: "context status --format json" } };
70314
70509
  });
70315
70510
  }
70316
- var import_yaml30, exec, semver, text6, changelogEntrySchema, changelogInputSchema, ledgerSchema, baselineSchema, hash2 = (value) => createHash15("sha256").update(JSON.stringify(value)).digest("hex");
70511
+ var import_yaml31, exec, semver, text6, changelogEntrySchema, changelogInputSchema, ledgerSchema, baselineSchema, hash2 = (value) => createHash15("sha256").update(JSON.stringify(value)).digest("hex");
70317
70512
  var init_workspaceChangelog = __esm(() => {
70318
70513
  init_zod();
70319
70514
  init_writeLock();
70320
70515
  init_durableSingleFileTransaction();
70321
70516
  init_durableMultiFileTransaction();
70322
- import_yaml30 = __toESM(require_dist(), 1);
70517
+ import_yaml31 = __toESM(require_dist(), 1);
70323
70518
  exec = promisify6(execFile6);
70324
70519
  semver = exports_external.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u);
70325
70520
  text6 = exports_external.string().trim().min(1);
@@ -70452,17 +70647,22 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70452
70647
  }
70453
70648
  .VPNavBar .wrapper { padding: 0 24px !important; }
70454
70649
  .VPNavBar .container { max-width: none !important; }
70650
+ .VPNav, .VPNavBar, .VPNavBar .wrapper { background: var(--vp-c-bg) !important; }
70455
70651
  .VPNavBar .title { position: static !important; padding: 0 !important; width: var(--vp-sidebar-width) !important; flex-shrink: 0; }
70456
70652
  .VPNavBarTitle .title { font-size: 15px; font-weight: 650; border: 0 !important; }
70457
70653
  .VPNavBar .content { flex: 1; min-width: 0; padding-left: 0 !important; }
70458
70654
  .VPNavBar .content-body { background: var(--vp-c-bg) !important; gap: 8px; }
70459
70655
  .VPNavBarMenu { order: -1; flex: 1; min-width: 0; }
70460
- .context-language { display: flex; align-items: center; gap: 4px; white-space: nowrap; font-size: 12px; }
70461
- .context-language button { padding: 4px; color: var(--vp-c-text-2); }
70462
- .context-language button[aria-pressed='true'] { color: var(--vp-c-brand-1); font-weight: 600; }
70656
+ .context-language { display: inline-flex; align-items: center; padding: 5px 7px; border: 0; border-radius: 6px; color: var(--vp-c-text-2);
70657
+ background: transparent; white-space: nowrap; font-size: 12px; font-weight: 550; cursor: pointer; }
70658
+ .context-language:hover { color: var(--vp-c-brand-1); background: var(--vp-c-brand-soft); }
70463
70659
  .VPNavBarMenuLink { font-size: 13px !important; font-weight: 550 !important; padding: 0 16px !important; }
70464
70660
  .VPNavBarMenuLink.active { box-shadow: inset 0 -2px var(--vp-c-brand-1); }
70465
- .VPNavBarSearch { flex-grow: 0 !important; padding: 0 12px !important; }
70661
+ .VPNavBarSearch { flex: 0 0 376px !important; width: 376px; padding: 0 12px !important; }
70662
+ .VPNavBarSearch #local-search, .VPNavBarSearch .DocSearch-Button { width: 352px; }
70663
+ .VPNavBarSearch .DocSearch-Button { display: flex; align-items: center; }
70664
+ .VPNavBarSearch .DocSearch-Button-Container { display: flex; flex: 1; min-width: 0; align-items: center; }
70665
+ .VPNavBarSearch .DocSearch-Button-Keys { margin-left: auto; }
70466
70666
  .VPSidebar { border-top: 1px solid var(--vp-c-divider); border-right: 1px solid var(--vp-c-divider); scrollbar-width: thin; }
70467
70667
  .VPSidebar .group + .group { border: 0; padding-top: 8px; }
70468
70668
  .VPSidebarItem .link { min-width: 0; overflow: hidden; }
@@ -70508,16 +70708,84 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70508
70708
  .vp-doc details { margin: 20px 0; border: 1px solid var(--vp-c-divider); border-radius: 6px; padding: 12px 16px; }
70509
70709
  .vp-doc summary { cursor: pointer; font-size: 14px; font-weight: 550; }
70510
70710
  .vp-doc img { max-width: 100%; height: auto; }
70711
+ .context-home { max-width: 100%; min-width: 0; overflow-x: clip; }
70712
+ .context-home .VPContent, .context-home .VPHome, .context-home .VPHero { max-width: 100%; min-width: 0; }
70713
+ .context-home .VPHome { padding-bottom: 0; }
70714
+ .context-home .VPHero { position: relative; padding: 132px 0 62px; }
70715
+ .context-home .VPHero::before { content: ''; position: absolute; top: -1px; right: 0; bottom: 0; left: calc(0px - var(--vp-sidebar-width)); pointer-events: none;
70716
+ background: linear-gradient(to bottom, transparent 58%, var(--vp-c-bg) 100%),
70717
+ radial-gradient(ellipse 58% 145% at 8% 18%, rgba(37,99,235,.16), transparent 72%),
70718
+ radial-gradient(ellipse 58% 150% at 68% 24%, rgba(0,190,200,.11), transparent 72%),
70719
+ linear-gradient(90deg, rgba(37,99,235,.045), rgba(0,190,200,.025) 68%, transparent); }
70720
+ .context-home .VPHero .container { position: relative; box-sizing: border-box; width: min(1180px, calc(100% - 104px)); max-width: none; min-width: 0; margin-left: 52px; margin-right: auto; }
70721
+ .context-home .VPHero .main { width: 100%; max-width: 980px; min-width: 0; }
70722
+ .context-home .VPHero .heading { display: block; width: 100%; min-width: 0; max-width: 100%; }
70723
+ .context-home .VPHero .name { display: block; width: 100%; max-width: 100%; overflow-wrap: anywhere; white-space: normal; color: transparent;
70724
+ background: linear-gradient(112deg, var(--vp-c-brand-1), var(--context-accent)); background-clip: text; -webkit-background-clip: text; }
70725
+ .context-home .VPHero .text { display: block; width: 100%; max-width: 100%; overflow-wrap: anywhere; word-break: break-word; white-space: normal;
70726
+ font-size: clamp(38px, 4.2vw, 60px); line-height: 1.08; letter-spacing: -.045em; }
70727
+ .context-home .VPHero .tagline { max-width: 820px; font-size: 18px; line-height: 1.75; }
70728
+ .context-home .VPHero .actions { width: 100%; min-width: 0; padding-top: 38px; flex-wrap: wrap; }
70729
+ .context-home .VPFeatures { display: none; }
70730
+ .context-home-section { width: min(1180px, calc(100% - 104px)); margin: 0 auto 0 52px; padding: 36px 0 44px; }
70731
+ .context-home-section + .context-home-section { border-top: 1px solid var(--vp-c-divider); }
70732
+ .context-home-map { padding-top: 0; }
70733
+ .context-home-resources { padding-top: 6px; border-top: 0 !important; }
70734
+ .context-home-section-heading { max-width: 700px; margin-bottom: 24px; }
70735
+ .context-home-section-heading h2 { margin: 2px 0 8px; border: 0; font-size: 28px; line-height: 1.3; letter-spacing: -.02em; }
70736
+ .context-home-section-heading > p:last-child { color: var(--vp-c-text-2); line-height: 1.7; }
70737
+ .context-home-kicker { margin: 0; color: var(--vp-c-brand-1); font-size: 11px; font-weight: 700; letter-spacing: .16em; }
70738
+ .context-home-map-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); gap: 14px; }
70739
+ .context-home-map-card, .context-home-resource-card { border: 1px solid var(--vp-c-divider); background: color-mix(in srgb, var(--vp-c-bg) 88%, var(--vp-c-bg-soft));
70740
+ animation: context-home-rise .5s both; animation-delay: var(--context-home-delay); }
70741
+ .context-home-map-card { min-height: 224px; padding: 22px; border-radius: 14px; }
70742
+ .context-home-map-card:hover, .context-home-resource-card:hover { border-color: color-mix(in srgb, var(--vp-c-brand-1) 42%, var(--vp-c-divider));
70743
+ box-shadow: 0 14px 38px rgba(23,36,66,.08); transform: translateY(-2px); transition: border-color .18s, box-shadow .18s, transform .18s; }
70744
+ .context-home-map-card-heading { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding-bottom: 13px; border-bottom: 1px solid var(--vp-c-divider); }
70745
+ .context-home-map-card h3, .context-home-resource-card h3 { margin: 0; font-size: 17px; line-height: 1.45; }
70746
+ .context-home-map-card h3 a { color: var(--vp-c-text-1); }
70747
+ .context-home-map-card-heading span { flex: none; color: var(--vp-c-text-2); font-size: 11px; }
70748
+ .context-home-map-card ul { margin: 14px 0 0; padding: 0; list-style: none; }
70749
+ .context-home-map-card li { margin: 7px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
70750
+ .context-home-map-card li a { color: var(--vp-c-text-2); font-size: 13px; }
70751
+ .context-home-map-card li a:hover, .context-home-map-more:hover { color: var(--vp-c-brand-1); }
70752
+ .context-home-map-more { display: inline-block; margin-top: 12px; color: var(--vp-c-brand-1); font-size: 12px; font-weight: 600; }
70753
+ .context-home-resource-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
70754
+ .context-home-resource-card { min-height: 118px; padding: 16px 18px; border-radius: 12px; }
70755
+ .context-home-resource-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
70756
+ .context-home-resource-actions { display: flex; flex: none; align-items: center; gap: 6px; }
70757
+ .context-home-resource-action, .context-home-install-action { display: inline-flex; align-items: center; min-height: 28px; padding: 4px 8px; border: 1px solid var(--vp-c-divider); border-radius: 6px;
70758
+ color: var(--vp-c-text-2); background: var(--vp-c-bg); font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap; }
70759
+ .context-home-resource-action:hover, .context-home-install-action:hover { border-color: var(--vp-c-brand-1); color: var(--vp-c-brand-1); }
70760
+ .context-home-install-action { cursor: pointer; background: var(--vp-c-brand-soft); }
70761
+ .context-home-resource-card p { margin: 8px 0 0; color: var(--vp-c-text-2); font-size: 13px; line-height: 1.55; }
70762
+ .context-home-powered { width: min(1180px, calc(100% - 104px)); margin: 24px auto 0 52px; padding: 22px 0 30px; border-top: 1px solid var(--vp-c-divider);
70763
+ color: var(--vp-c-text-2); font-size: 11px; text-align: right; }
70764
+ .context-home-powered a { color: inherit; }
70765
+ @keyframes context-home-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
70511
70766
  @media (min-width: 960px) {
70512
70767
  .VPSidebar { top: var(--vp-nav-height) !important; width: var(--vp-sidebar-width) !important; padding: 12px 0 48px !important; }
70513
70768
  .VPSidebar .curtain { display: none; }
70514
70769
  .VPContent.has-sidebar { padding-left: var(--vp-sidebar-width) !important; padding-right: 0 !important; }
70515
70770
  .context-empty-sidebar .VPContent { padding-left: var(--vp-sidebar-width) !important; padding-right: 0 !important; }
70771
+ .context-home .VPContent { padding-left: var(--vp-sidebar-width) !important; padding-right: 0 !important; }
70516
70772
  .VPNavBar .content { padding-right: 32px !important; }
70517
70773
  .VPDoc { padding: 44px 36px 80px !important; }
70518
70774
  .VPDoc > .container > .content { padding: 0 24px 80px 0 !important; }
70519
70775
  }
70520
70776
  @media (min-width: 1600px) { .VPDoc { padding-left: 52px !important; padding-right: 36px !important; } }
70777
+ @media (min-width: 960px) and (max-width: 1279px) {
70778
+ .VPNavBar .title { width: 220px !important; }
70779
+ .VPNavBarMenuLink { padding: 0 9px !important; }
70780
+ .VPNavBarSearch { flex-basis: 168px !important; width: 168px; }
70781
+ .VPNavBarSearch .DocSearch-Button { width: 144px; }
70782
+ .context-home .VPHero .main { max-width: 100%; }
70783
+ .context-home-resource-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
70784
+ }
70785
+ @media (min-width: 1280px) and (max-width: 1599px) {
70786
+ .VPNavBarSearch { flex-basis: 248px !important; width: 248px; }
70787
+ .VPNavBarSearch #local-search, .VPNavBarSearch .DocSearch-Button { width: 224px; }
70788
+ }
70521
70789
  .context-mobile-directory { display: none; }
70522
70790
  @media (max-width: 959px) {
70523
70791
  .VPNavBar .wrapper { padding: 0 16px !important; }
@@ -70541,6 +70809,17 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70541
70809
  .vp-doc h2 { font-size: 22px; }
70542
70810
  .VPDoc { padding: 32px 36px 64px !important; }
70543
70811
  .vp-doc a.header-anchor { margin-left: -0.8em; }
70812
+ .context-home .VPHero { padding-top: 104px; padding-bottom: 66px; }
70813
+ .context-home .VPHero::before { left: 0; }
70814
+ .context-home .VPHero .container { width: min(calc(100% - 36px), 680px); margin-left: auto; margin-right: auto; }
70815
+ .context-home .VPHero .text { font-size: 40px; }
70816
+ .context-home .VPHero .tagline { font-size: 16px; }
70817
+ .context-home-section, .context-home-powered { width: min(calc(100% - 36px), 680px); margin-left: auto; margin-right: auto; }
70818
+ .context-home-resource-grid { grid-template-columns: 1fr; }
70819
+ }
70820
+ @media (prefers-reduced-motion: reduce) {
70821
+ .context-home-map-card, .context-home-resource-card { animation: none; }
70822
+ .context-home-map-card:hover, .context-home-resource-card:hover { transform: none; }
70544
70823
  }
70545
70824
  .context-sources { margin-top: 0; margin-bottom: 24px; padding: 16px 20px; border: 1px solid var(--vp-c-divider); border-radius: 8px; background: var(--vp-sidebar-bg-color); color: var(--vp-c-text-2); font-size: 12px; line-height: 1.7; overflow-wrap: anywhere; }
70546
70825
  .context-sources-header { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px 16px; margin-bottom: 8px; }
@@ -70626,9 +70905,12 @@ export default {
70626
70905
  const data = useData();
70627
70906
  const route = useRoute();
70628
70907
  const sections = computed(() => data.theme.value.contextSections || []);
70908
+ const home = computed(() => data.theme.value.contextHome || {});
70629
70909
  const selected = ref('');
70630
70910
  const mounted = ref(false);
70631
70911
  const language = ref('zh');
70912
+ const copiedCommand = ref('');
70913
+ let copyReset;
70632
70914
  const chinese = computed(() => language.value === 'zh');
70633
70915
  const languageKey = 'context-language:' + data.site.value.base;
70634
70916
  onMounted(() => {
@@ -70641,6 +70923,76 @@ export default {
70641
70923
  language.value = value;
70642
70924
  try { localStorage.setItem(languageKey, value); } catch {}
70643
70925
  };
70926
+ const href = value => value.startsWith('/') ? data.site.value.base + value.slice(1) : value;
70927
+ const external = value => /^https?:\/\//.test(value) || value.startsWith('mailto:');
70928
+ const copyCommand = async value => {
70929
+ try {
70930
+ await navigator.clipboard.writeText(value);
70931
+ copiedCommand.value = value;
70932
+ clearTimeout(copyReset);
70933
+ copyReset = setTimeout(() => { if (copiedCommand.value === value) copiedCommand.value = ''; }, 1600);
70934
+ } catch {}
70935
+ };
70936
+ const links = items => items.flatMap(item => [
70937
+ ...(item.link ? [{ text: item.text, link: item.link }] : []),
70938
+ ...links(item.items || []),
70939
+ ]);
70940
+ const siteMap = () => h('section', { class: 'context-home-section context-home-map', 'aria-labelledby': 'context-home-map-title' }, [
70941
+ h('div', { class: 'context-home-section-heading' }, [
70942
+ h('p', { class: 'context-home-kicker' }, chinese.value ? 'KNOWLEDGE MAP' : 'KNOWLEDGE MAP'),
70943
+ h('h2', { id: 'context-home-map-title' }, chinese.value ? '网站地图' : 'Site map'),
70944
+ h('p', chinese.value ? '从主题进入知识,也可以继续查看栏目中的具体页面。' :
70945
+ 'Start with a topic, then continue to the pages within each section.'),
70946
+ ]),
70947
+ h('div', { class: 'context-home-map-grid' }, sections.value.map((section, index) => {
70948
+ const pages = links(section.items || []);
70949
+ return h('article', { class: 'context-home-map-card', style: { '--context-home-delay': (index * 35) + 'ms' } }, [
70950
+ h('div', { class: 'context-home-map-card-heading' }, [
70951
+ h('h3', h('a', { href: href(section.href) }, section.title)),
70952
+ h('span', chinese.value ? section.pages.length + ' 页' : section.pages.length + ' pages'),
70953
+ ]),
70954
+ pages.length ? h('ul', pages.slice(0, 6).map(page => h('li',
70955
+ h('a', { href: href(page.link) }, page.text)))) : null,
70956
+ pages.length > 6 ? h('a', { class: 'context-home-map-more', href: href(section.href) },
70957
+ chinese.value ? '查看全部 ' + pages.length + ' 页 →' : 'View all ' + pages.length + ' pages →') : null,
70958
+ ]);
70959
+ })),
70960
+ ]);
70961
+ const resources = () => {
70962
+ const builtins = [
70963
+ { title: 'LLM Docs', description: chinese.value ? '面向 Agent 和模型的结构化知识入口。' :
70964
+ 'Structured knowledge entry points for agents and models.', href: '/llms/index.html', action: chinese.value ? '打开文档' : 'Open docs' },
70965
+ { title: 'Changelog', description: chinese.value ? '查看知识内容的版本变化与更新时间。' :
70966
+ 'Review knowledge versions and update history.', href: '/changelog.html', action: chinese.value ? '查看更新' : 'View updates' },
70967
+ ];
70968
+ const items = [...(home.value.resources || []), ...builtins];
70969
+ return h('section', { class: 'context-home-section context-home-resources', 'aria-labelledby': 'context-home-resources-title' }, [
70970
+ h('div', { class: 'context-home-section-heading' }, [
70971
+ h('p', { class: 'context-home-kicker' }, chinese.value ? 'RESOURCES' : 'RESOURCES'),
70972
+ h('h2', { id: 'context-home-resources-title' }, chinese.value ? '工具与资源' : 'Tools and resources'),
70973
+ ]),
70974
+ h('div', { class: 'context-home-resource-grid' }, items.map((item, index) => h('article', {
70975
+ class: 'context-home-resource-card', style: { '--context-home-delay': (index * 35) + 'ms' },
70976
+ }, [
70977
+ h('div', { class: 'context-home-resource-heading' }, [
70978
+ h('h3', item.title),
70979
+ h('div', { class: 'context-home-resource-actions' }, [
70980
+ item.command ? h('button', { class: 'context-home-install-action', type: 'button',
70981
+ title: (chinese.value ? '复制安装命令:' : 'Copy install command: ') + item.command,
70982
+ onClick: () => copyCommand(item.command) }, copiedCommand.value === item.command
70983
+ ? (chinese.value ? '已复制' : 'Copied') : (chinese.value ? '安装' : 'Install')) : null,
70984
+ item.href ? h('a', { class: 'context-home-resource-action', href: href(item.href), ...(external(item.href)
70985
+ ? { target: '_blank', rel: 'noopener noreferrer' } : {}) }, item.action || (chinese.value ? '访问' : 'Open')) : null,
70986
+ ]),
70987
+ ]),
70988
+ item.description ? h('p', item.description) : null,
70989
+ ]))),
70990
+ ]);
70991
+ };
70992
+ const poweredBy = () => home.value.branding ? h('footer', { class: 'context-home-powered' }, [
70993
+ home.value.branding.label + ' ',
70994
+ h('a', { href: home.value.branding.href, target: '_blank', rel: 'noopener noreferrer' }, home.value.branding.name),
70995
+ ]) : null;
70644
70996
  const history = computed(() => data.frontmatter.value.contextHistory
70645
70997
  ? JSON.parse(new TextDecoder().decode(Uint8Array.from(atob(data.frontmatter.value.contextHistory), char => char.charCodeAt(0)))) : null);
70646
70998
  onMounted(() => { mounted.value = true; });
@@ -70667,6 +71019,7 @@ export default {
70667
71019
  const active = computed(() => sections.value.find(section => section.key === selected.value));
70668
71020
  const inLlms = computed(() => route.path.startsWith(data.site.value.base + 'llms/'));
70669
71021
  const inHistory = computed(() => route.path === data.site.value.base + 'changelog.html');
71022
+ const inHome = computed(() => data.frontmatter.value.layout === 'home');
70670
71023
  provide(dataSymbol, { ...data, theme: computed(() => ({ ...data.theme.value,
70671
71024
  ...data.theme.value.contextUiLabels?.[language.value],
70672
71025
  sidebar: inLlms.value || inHistory.value ? [] : active.value?.items || [],
@@ -70678,9 +71031,12 @@ export default {
70678
71031
  activeMatch: inLlms.value || inHistory.value ? '^' : '(?!)' }],
70679
71032
  })) });
70680
71033
  const slots = {
70681
- 'nav-bar-content-after': () => h('div', { class: 'context-language', role: 'group', 'aria-label': '界面语言 / Interface language' },
70682
- ['zh', 'en'].map(value => h('button', { type: 'button', 'aria-pressed': language.value === value,
70683
- onClick: () => changeLanguage(value) }, value === 'zh' ? '中文' : 'EN'))),
71034
+ 'nav-bar-content-after': () => h('button', { class: 'context-language', type: 'button',
71035
+ 'aria-label': chinese.value ? 'Switch interface language to English' : '将界面语言切换为中文',
71036
+ title: chinese.value ? 'Switch to English' : '切换为中文',
71037
+ onClick: () => changeLanguage(chinese.value ? 'en' : 'zh') }, chinese.value ? 'EN' : '中文'),
71038
+ 'home-features-before': () => [siteMap(), resources()],
71039
+ 'home-features-after': poweredBy,
70684
71040
  'doc-after': () => history.value ? h('section', { class: 'context-history-cards' },
70685
71041
  history.value.length ? history.value.map((entry, index) =>
70686
71042
  h('details', { class: 'context-history-card', open: index < 3, key: entry.version }, [
@@ -70729,7 +71085,8 @@ export default {
70729
71085
  },
70730
71086
  };
70731
71087
  // History belongs between the page heading and footer metadata.
70732
- return () => h(DefaultTheme.Layout, { class: inLlms.value || inHistory.value ? 'context-empty-sidebar' : undefined }, { ...slots, 'doc-after': undefined,
71088
+ return () => h(DefaultTheme.Layout, { class: inHome.value ? 'context-home' :
71089
+ inLlms.value || inHistory.value ? 'context-empty-sidebar' : undefined }, { ...slots, 'doc-after': undefined,
70733
71090
  'doc-footer-before': () => [slots['doc-after'](), slots['doc-footer-before']()] });
70734
71091
  }
70735
71092
  },
@@ -70789,10 +71146,20 @@ export default {
70789
71146
  `;
70790
71147
  });
70791
71148
 
71149
+ // src/project/packageSiteBranding.ts
71150
+ var packageSiteBranding;
71151
+ var init_packageSiteBranding = __esm(() => {
71152
+ packageSiteBranding = {
71153
+ label: "Powered by",
71154
+ name: "context4ai/context",
71155
+ href: "https://github.com/context4ai/context"
71156
+ };
71157
+ });
71158
+
70792
71159
  // src/project/packageSite.ts
70793
71160
  import { createHash as createHash16 } from "node:crypto";
70794
71161
  import { spawn as spawn3 } from "node:child_process";
70795
- import { mkdir as mkdir19, mkdtemp, readFile as readFile46, writeFile as writeFile14, rm as rm11, symlink, cp, access as access5 } from "node:fs/promises";
71162
+ import { mkdir as mkdir19, mkdtemp, readFile as readFile46, writeFile as writeFile14, rm as rm11, symlink, cp, access as access5, stat as stat7 } from "node:fs/promises";
70796
71163
  import { createRequire as createRequire5 } from "node:module";
70797
71164
  import { dirname as dirname23, join as join56, posix as posix6 } from "node:path";
70798
71165
  function sitePagePath(identity) {
@@ -70986,6 +71353,7 @@ async function writePackageSite(input) {
70986
71353
  contextUpdated: historyDate,
70987
71354
  contextUiLabels: { zh: siteThemeLabels("zh"), en: siteThemeLabels("en") },
70988
71355
  contextSections: sections.map(({ key, title, href, pages, items }) => ({ key, title, href, pages, items })),
71356
+ contextHome: { resources: options.home?.resources ?? [], branding: packageSiteBranding },
70989
71357
  sidebar: sections[0]?.items ?? [],
70990
71358
  nav: [...sections.map((section) => ({ text: section.title, link: section.href })), { text: "更多", items: [{ text: "LLM Docs", link: "/llms/index.html" }, { text: "Changelog", link: "/changelog.html" }] }]
70991
71359
  }
@@ -71022,11 +71390,24 @@ ${body}`);
71022
71390
  `) + `
71023
71391
  `);
71024
71392
  }
71025
- const home = [`# ${mdLabel(options.title ?? pkg.name)}`, "", mdLabel(options.description ?? ""), ""];
71026
- for (const section of sections)
71027
- home.push(`- [${mdLabel(section.title)}](${section.href})`);
71028
- await writeFile14(join56(temporary, "index.md"), home.join(`
71029
- `) + `
71393
+ const chinese = (options.lang ?? "en-US").startsWith("zh");
71394
+ const firstSection = sections[0]?.href ?? "/llms/index.html";
71395
+ const featuredResources = (options.home?.resources ?? []).filter((resource) => resource.featured && resource.href);
71396
+ const hero = {
71397
+ name: options.home?.title ?? options.title ?? pkg.name,
71398
+ text: options.home?.slogan ?? (chinese ? "从知识地图开始探索" : "Explore from the knowledge map"),
71399
+ tagline: options.home?.description ?? options.description ?? "",
71400
+ actions: options.home?.actions ?? [
71401
+ { theme: "brand", text: chinese ? "浏览知识" : "Browse knowledge", link: firstSection },
71402
+ ...featuredResources.map((resource) => ({ theme: "alt", text: resource.title, link: resource.href })),
71403
+ { theme: "alt", text: "LLM Docs", link: "/llms/index.html" }
71404
+ ]
71405
+ };
71406
+ await writeFile14(join56(temporary, "index.md"), `---
71407
+ layout: home
71408
+ title: ${JSON.stringify(options.home?.title ?? options.title ?? pkg.name)}
71409
+ hero: ${JSON.stringify(hero)}
71410
+ ---
71030
71411
  `);
71031
71412
  await writeFile14(join56(temporary, "changelog.md"), `---
71032
71413
  title: Changelog
@@ -71068,6 +71449,15 @@ title: LLM Docs
71068
71449
  await cp(join56(root, path2), destination);
71069
71450
  }
71070
71451
  await compileSite(temporary, output);
71452
+ for (const file of await walkPackageFiles(output)) {
71453
+ const extension2 = posix6.extname(file.relPath).toLowerCase();
71454
+ const placeholder = [".css", ".js", ".mjs", ".cjs"].includes(extension2) ? `/* Intentionally empty. */
71455
+ ` : [".html", ".htm"].includes(extension2) ? `<!-- Intentionally empty. -->
71456
+ ` : null;
71457
+ if (placeholder !== null && (await stat7(file.absPath)).size === 0) {
71458
+ await writeFile14(file.absPath, placeholder);
71459
+ }
71460
+ }
71071
71461
  await writeFile14(join56(output, "context-site-map.json"), JSON.stringify({
71072
71462
  protocol: "context.site-output/v1",
71073
71463
  knowledge_map_revision: structure?.revision ?? null,
@@ -71084,7 +71474,7 @@ title: LLM Docs
71084
71474
  await rm11(temporary, { recursive: true, force: true });
71085
71475
  }
71086
71476
  }
71087
- var PACKAGE_SITE_VERSION = "vitepress-site-v22-llms-new-tab", require2, encodePath = (path2) => path2.split("/").map(encodeURIComponent).join("/"), mdLabel = (value) => value.replace(/[\\[\]<>`*]/gu, "\\$&").replace(/[\r\n]/gu, " ");
71477
+ var PACKAGE_SITE_VERSION = "vitepress-site-v41-home-safe-spacing", require2, encodePath = (path2) => path2.split("/").map(encodeURIComponent).join("/"), mdLabel = (value) => value.replace(/[\\[\]<>`*]/gu, "\\$&").replace(/[\r\n]/gu, " ");
71088
71478
  var init_packageSite2 = __esm(() => {
71089
71479
  init_packageOutputPaths();
71090
71480
  init_workspaceChangelog();
@@ -71096,6 +71486,7 @@ var init_packageSite2 = __esm(() => {
71096
71486
  init_packageKnowledgeMap();
71097
71487
  init_markdownLinks();
71098
71488
  init_packageSiteTheme();
71489
+ init_packageSiteBranding();
71099
71490
  require2 = createRequire5(import.meta.url);
71100
71491
  });
71101
71492
 
@@ -72274,7 +72665,7 @@ function validateRenderedSkillDefinition(input) {
72274
72665
  }
72275
72666
  let frontmatter;
72276
72667
  try {
72277
- frontmatter = import_yaml31.parse(frontmatterMatch[1]);
72668
+ frontmatter = import_yaml33.parse(frontmatterMatch[1]);
72278
72669
  } catch {
72279
72670
  frontmatter = null;
72280
72671
  }
@@ -72301,7 +72692,7 @@ function validateRenderedSkillDefinition(input) {
72301
72692
  });
72302
72693
  }
72303
72694
  }
72304
- var import_yaml31, OKF_OUTPUT_ROOTS2, SKILL_NAME_PATTERN;
72695
+ var import_yaml33, OKF_OUTPUT_ROOTS2, SKILL_NAME_PATTERN;
72305
72696
  var init_packageTemplateGuard = __esm(() => {
72306
72697
  init_cliFeedback();
72307
72698
  init_errors3();
@@ -72309,7 +72700,7 @@ var init_packageTemplateGuard = __esm(() => {
72309
72700
  init_packageIndexes();
72310
72701
  init_packageDistribution();
72311
72702
  init_packageTemplateUtils();
72312
- import_yaml31 = __toESM(require_dist(), 1);
72703
+ import_yaml33 = __toESM(require_dist(), 1);
72313
72704
  OKF_OUTPUT_ROOTS2 = new Set(["wikis", "guides", "rules", "feats"]);
72314
72705
  SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
72315
72706
  });
@@ -72370,7 +72761,7 @@ function isDeprecatedKnowledge(content3) {
72370
72761
  if (match?.[1] === undefined)
72371
72762
  return false;
72372
72763
  try {
72373
- const frontmatter = import_yaml33.parse(match[1]);
72764
+ const frontmatter = import_yaml35.parse(match[1]);
72374
72765
  return frontmatter !== null && typeof frontmatter === "object" && !Array.isArray(frontmatter) && frontmatter.deprecated === true;
72375
72766
  } catch {
72376
72767
  return false;
@@ -72901,7 +73292,7 @@ async function runProjectBuildCommand(input) {
72901
73292
  process.stdout.write(formatProjectBuildResult(result, input.format ?? "text", input.verbose === true));
72902
73293
  return true;
72903
73294
  }
72904
- var import_yaml33, PACKAGE_FINGERPRINT_ROOT, PACKAGE_BUILDER_PROTOCOL_VERSION = "v23-sibling-site-output";
73295
+ var import_yaml35, PACKAGE_FINGERPRINT_ROOT, PACKAGE_BUILDER_PROTOCOL_VERSION = "v23-sibling-site-output";
72905
73296
  var init_packageBuilder = __esm(() => {
72906
73297
  init_knowledgeMap2();
72907
73298
  init_approvedFileRead();
@@ -72938,7 +73329,7 @@ var init_packageBuilder = __esm(() => {
72938
73329
  init_workspace();
72939
73330
  init_packageTemplateReview();
72940
73331
  init_approvedKnowledgeMetadata();
72941
- import_yaml33 = __toESM(require_dist(), 1);
73332
+ import_yaml35 = __toESM(require_dist(), 1);
72942
73333
  PACKAGE_FINGERPRINT_ROOT = join62(".tmp", "context-runtime", "packages");
72943
73334
  });
72944
73335
 
@@ -73709,7 +74100,7 @@ function parseApprovedRevision(value) {
73709
74100
  if (!value || typeof value !== "object" || !("protocol" in value) || value.protocol !== "context.approved-revision/v1")
73710
74101
  return;
73711
74102
  const parsed = requestSchema2.parse(value);
73712
- if (!isSafeKnowledgeTargetPath(parsed.target.collection, parsed.target.path) || parsed.revision !== requestDigest(parsed) || parsed.target.previous_path !== undefined && !isSafeKnowledgeTargetPath(parsed.target.collection, parsed.target.previous_path))
74103
+ if (!isSafeKnowledgeTargetPath(parsed.target.collection, parsed.target.path) || parsed.revision !== requestDigest(parsed) || parsed.target.previous_path !== undefined && (!indexerKnowledgeCollectionSchema2.safeParse(parsed.target.previous_path.split("/")[0]).success || !isSafeKnowledgeTargetPath(parsed.target.previous_path.split("/")[0], parsed.target.previous_path)))
73713
74104
  throw new TypeError("Approved revision target or digest is invalid");
73714
74105
  const { candidate: raw, batch_candidates: batch, ...rest } = parsed;
73715
74106
  const request = { ...rest, ...batch === undefined ? {} : { batch_candidates: batch.map((item, index2) => parseCandidateRecord(item, index2 + 1)) } };
@@ -73902,12 +74293,15 @@ async function prepareApprovedRevision(input) {
73902
74293
  };
73903
74294
  }
73904
74295
  if (input.move_to !== undefined) {
73905
- if (input.create || !isSafeKnowledgeTargetPath(target.collection, input.move_to) || input.move_to === target.path) {
73906
- throw new TypeError("Move requires a different safe path in the same knowledge collection.");
74296
+ const destinationCollection = indexerKnowledgeCollectionSchema2.safeParse(input.move_to.split("/")[0]);
74297
+ if (input.create || !destinationCollection.success || !isSafeKnowledgeTargetPath(destinationCollection.data, input.move_to) || input.move_to.includes("\\") || input.move_to === target.path) {
74298
+ throw new TypeError("Move requires a different safe path in a supported knowledge collection.");
73907
74299
  }
73908
74300
  const { moveKnowledgeLinkTargets: moveKnowledgeLinkTargets2 } = await Promise.resolve().then(() => (init_approvedPageMove(), exports_approvedPageMove));
73909
- const movedMarkdown = moveKnowledgeLinkTargets2(target.markdown, input.move_to, target.path, new Map([[target.path, input.move_to]])).replace(/^resource:.*$/mu, `resource: knowledge:${input.move_to.replace(/\.md$/u, "")}`);
73910
- target = { ...target, previous_path: target.path, path: input.move_to, markdown: movedMarkdown };
74301
+ const movedMarkdown = moveKnowledgeLinkTargets2(target.markdown, input.move_to, target.path, new Map([[target.path, input.move_to]])).replace(/^resource:.*$/mu, `resource: knowledge:${input.move_to.replace(/\.md$/u, "")}`).replace(/^---\r?\n([\s\S]*?)\r?\n---/u, (header, fields) => target.collection === destinationCollection.data ? header : `---
74302
+ ${import_yaml36.default.stringify({ ...import_yaml36.default.parse(fields), type: okfTypeForCollection(destinationCollection.data) }).trimEnd()}
74303
+ ---`);
74304
+ target = { ...target, collection: destinationCollection.data, previous_path: target.path, path: input.move_to, markdown: movedMarkdown };
73911
74305
  await assertApprovedRevisionBase(input.projectRoot, { target });
73912
74306
  }
73913
74307
  if (input.supporting_sources) {
@@ -73958,7 +74352,7 @@ async function prepareApprovedRevision(input) {
73958
74352
  }
73959
74353
  function frontmatter(markdown) {
73960
74354
  const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(markdown);
73961
- const parsed = match ? import_yaml35.default.parse(match[1]) : undefined;
74355
+ const parsed = match ? import_yaml36.default.parse(match[1]) : undefined;
73962
74356
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
73963
74357
  throw new TypeError("Revision must retain the approved page frontmatter");
73964
74358
  return parsed;
@@ -74246,7 +74640,7 @@ async function reopenApprovedRevision(input) {
74246
74640
  };
74247
74641
  });
74248
74642
  }
74249
- var import_yaml35, digest5, revisionTargetSchema, requestSchema2;
74643
+ var import_yaml36, digest5, revisionTargetSchema, requestSchema2;
74250
74644
  var init_approvedRevision = __esm(() => {
74251
74645
  init_productionRequirements();
74252
74646
  init_approvedRevisionEdits();
@@ -74263,8 +74657,9 @@ var init_approvedRevision = __esm(() => {
74263
74657
  init_durableSingleFileTransaction();
74264
74658
  init_durableMultiFileTransaction();
74265
74659
  init_processedScopeStorage();
74660
+ init_okfTypes();
74266
74661
  init_maintenanceStorage();
74267
- import_yaml35 = __toESM(require_dist(), 1);
74662
+ import_yaml36 = __toESM(require_dist(), 1);
74268
74663
  digest5 = exports_external.string().regex(/^sha256:[a-f0-9]{64}$/u);
74269
74664
  revisionTargetSchema = exports_external.object({
74270
74665
  path: exports_external.string().min(1),
@@ -81718,7 +82113,7 @@ async function approveProductionReport(input) {
81718
82113
  throw new TypeError("The report's plan changed. Read and present the current proposal before confirming it.");
81719
82114
  }
81720
82115
  const file = input.manifest ?? await readProductionFile(input);
81721
- const decision = productionReportInputSchema.extend({ stage: exports_external.literal(stage.id) }).parse(import_yaml38.default.parse(file.text));
82116
+ const decision = productionReportInputSchema.extend({ stage: exports_external.literal(stage.id) }).parse(import_yaml39.default.parse(file.text));
81722
82117
  if (!stage.report_approved)
81723
82118
  await assertProductionPlanRequirementsCurrent(input.projectRoot, stage);
81724
82119
  if (decision.decision === "approved")
@@ -81734,7 +82129,7 @@ async function approveProductionReport(input) {
81734
82129
  }
81735
82130
  }));
81736
82131
  }
81737
- var import_yaml38, productionReportInputSchema;
82132
+ var import_yaml39, productionReportInputSchema;
81738
82133
  var init_productionReport = __esm(() => {
81739
82134
  init_zod();
81740
82135
  init_src2();
@@ -81744,7 +82139,7 @@ var init_productionReport = __esm(() => {
81744
82139
  init_productionStagePreparation();
81745
82140
  init_productionPlanning();
81746
82141
  init_productionFeedback();
81747
- import_yaml38 = __toESM(require_dist(), 1);
82142
+ import_yaml39 = __toESM(require_dist(), 1);
81748
82143
  productionReportInputSchema = exports_external.object({ stage: exports_external.string().min(1), decision: exports_external.literal("approved") }).strict();
81749
82144
  });
81750
82145
 
@@ -88328,6 +88723,355 @@ var init_actionInputWorkspace = __esm(() => {
88328
88723
  init_workspace();
88329
88724
  });
88330
88725
 
88726
+ // src/project/articleRetirement.ts
88727
+ var exports_articleRetirement = {};
88728
+ __export(exports_articleRetirement, {
88729
+ retireArticles: () => retireArticles,
88730
+ articleRetirementSchema: () => articleRetirementSchema
88731
+ });
88732
+ import { readFile as readFile74, readdir as readdir20 } from "node:fs/promises";
88733
+ import { posix as posix10 } from "node:path";
88734
+ function invalid(reason, message, details = {}) {
88735
+ throw new ContextError(ExitCode.UserError, message, {
88736
+ category: ErrorCategory.UserInputInvalid,
88737
+ reason_code: reason,
88738
+ ...details,
88739
+ next_action: {
88740
+ command: next,
88741
+ message: "Keep the retirement input. Resolve the listed page/reference or finish the active revision, then preview it again; no retirement was applied."
88742
+ }
88743
+ });
88744
+ }
88745
+ async function text9(root2, path3) {
88746
+ try {
88747
+ return await readFile74(await safeProjectTarget(root2, path3), "utf8");
88748
+ } catch (error) {
88749
+ if (error.code === "ENOENT")
88750
+ return;
88751
+ throw error;
88752
+ }
88753
+ }
88754
+ async function retireArticles(input) {
88755
+ const parsed = articleRetirementSchema.safeParse(input.value);
88756
+ if (!parsed.success)
88757
+ invalid("article-retirement-input-invalid", "Provide reason and targets with exact approved paths and optional replacement paths.", { input_schema: { reason: "string", targets: [{ path: "collection/old.md", replacement: "collection/approved-successor.md (optional)" }] } });
88758
+ const value = parsed.data;
88759
+ return withProjectWriteLock(input.projectRoot, "retire-articles", async () => {
88760
+ if (input.apply)
88761
+ await recoverDurableMultiFileTransactions(input.projectRoot);
88762
+ if (input.apply && input.plan_digest && /^sha256:[a-f0-9]{64}$/u.test(input.plan_digest)) {
88763
+ const receipt3 = await text9(input.projectRoot, `.tmp/context-runtime/retirements/${input.plan_digest.slice(7)}/receipt.json`);
88764
+ if (receipt3) {
88765
+ const saved = JSON.parse(receipt3);
88766
+ if (saved.request !== indexerProtocolDigest(value))
88767
+ invalid("article-retirement-input-changed", "The retirement input differs from the applied request.");
88768
+ for (const file of saved.files) {
88769
+ const current2 = await text9(input.projectRoot, file.path);
88770
+ if ((current2 === undefined ? null : durableContentDigest(current2)) !== file.digest)
88771
+ invalid("article-retirement-result-changed", "Retirement was applied but a resulting file has since changed; inspect the current workspace.", { path: file.path });
88772
+ }
88773
+ return { action: "already-applied", revision: input.plan_digest, next_action: { command: next } };
88774
+ }
88775
+ }
88776
+ const maintenance = await readMaintenance(input.projectRoot);
88777
+ if ((await readCandidateRecords(input.projectRoot)).length || await readApprovedRevision(input.projectRoot) || await readKnowledgeUpdate(input.projectRoot) || await readTaskRollback(input.projectRoot) || maintenance.active) {
88778
+ invalid("article-retirement-active-review", "Finish the active candidate/revision delivery before retiring approved pages.");
88779
+ }
88780
+ const before = await text9(input.projectRoot, "knowledge/structure.yaml");
88781
+ const structure = before === undefined ? {} : import_yaml41.default.parse(before);
88782
+ const articles = validateArticleStructureEntries(structure.articles ?? []);
88783
+ const byPath = new Map(articles.map((article) => [article.path, article]));
88784
+ const selected = new Set(value.targets.map((target) => target.path));
88785
+ if (selected.size !== value.targets.length)
88786
+ invalid("article-retirement-duplicate", "Select each approved article once.");
88787
+ if (maintenance.pending.some((request) => request.targets.some((target) => selected.has(target.path)))) {
88788
+ invalid("article-retirement-pending-maintenance", "Cancel or finish queued maintenance for the selected pages before retirement.");
88789
+ }
88790
+ const stage = await readProductionStage(input.projectRoot);
88791
+ if (stage?.tasks.some((task) => selected.has(task.path) && !["accepted", "excluded", "replaced"].includes(task.status))) {
88792
+ invalid("article-retirement-pending-task", "A selected article still has unfinished production; finish or amend that task first.");
88793
+ }
88794
+ const replacements = new Map;
88795
+ for (const target of value.targets) {
88796
+ if (!byPath.has(target.path))
88797
+ invalid("article-retirement-target-missing", "Select an exact approved article path from knowledge/structure.yaml.", { path: target.path });
88798
+ if (target.replacement !== undefined && (!byPath.has(target.replacement) || selected.has(target.replacement))) {
88799
+ invalid("article-retirement-replacement-invalid", "Replacement must be an already-approved article outside the retirement set.", { path: target.path, replacement: target.replacement });
88800
+ }
88801
+ replacements.set(target.path, target.replacement);
88802
+ }
88803
+ const targets = [];
88804
+ const restore = [];
88805
+ function change(path3, old, content3) {
88806
+ if (old === content3)
88807
+ return;
88808
+ targets.push(content3 === undefined ? { path: path3, operation: "delete", base_digest: durableContentDigest(old), target_digest: null } : { path: path3, operation: "write", base_digest: old === undefined ? null : durableContentDigest(old), target_digest: durableContentDigest(content3), content: content3 });
88809
+ restore.push({ path: path3, base_digest: content3 === undefined ? null : durableContentDigest(content3), content: old ?? null });
88810
+ }
88811
+ const blockers = [];
88812
+ const readDigests = [];
88813
+ for (const article of articles) {
88814
+ const path3 = `knowledge/${article.path}`;
88815
+ const bytes = await text9(input.projectRoot, path3);
88816
+ if (bytes === undefined)
88817
+ invalid("article-retirement-article-missing", "Approved article bytes are missing; recover the workspace before retirement.", { path: path3 });
88818
+ readDigests.push({ path: path3, digest: durableContentDigest(bytes) });
88819
+ if (selected.has(article.path)) {
88820
+ change(path3, bytes);
88821
+ continue;
88822
+ }
88823
+ const content3 = replaceMarkdownInlineLinkTargets(bytes, (link2) => {
88824
+ if (link2.target.startsWith("#") || link2.target.startsWith("//"))
88825
+ return;
88826
+ const knowledge = link2.target.startsWith("knowledge:");
88827
+ if (!knowledge && /^[a-z][a-z0-9+.-]*:/iu.test(link2.target))
88828
+ return;
88829
+ const match = /^([^#?]*)(.*)$/u.exec(knowledge ? link2.target.slice(10) : link2.target);
88830
+ let target;
88831
+ try {
88832
+ target = decodeURI(match[1]);
88833
+ } catch {
88834
+ return;
88835
+ }
88836
+ const rooted = /^\/?knowledge\//u.test(target);
88837
+ if (target.startsWith("/") && !rooted)
88838
+ return;
88839
+ let resolved = knowledge ? target : rooted ? target.replace(/^\/?knowledge\//u, "") : posix10.normalize(posix10.join(posix10.dirname(article.path), target));
88840
+ if (knowledge && !resolved.endsWith(".md"))
88841
+ resolved += ".md";
88842
+ if (!selected.has(resolved))
88843
+ return;
88844
+ const replacement = replacements.get(resolved);
88845
+ if (!replacement || match[2].includes("#")) {
88846
+ blockers.push({ path: path3, target: link2.target, reason: replacement ? "Repair fragment links explicitly before retirement." : "Repair this incoming link or supply an approved replacement." });
88847
+ return;
88848
+ }
88849
+ return knowledge ? `knowledge:${target.endsWith(".md") ? replacement : replacement.replace(/\.md$/u, "")}${match[2]}` : `${encodeURI(rooted ? `${target.startsWith("/") ? "/" : ""}knowledge/${replacement}` : posix10.relative(posix10.dirname(article.path), replacement))}${match[2]}`;
88850
+ });
88851
+ change(path3, bytes, content3);
88852
+ }
88853
+ async function inspectTemplates(directory2) {
88854
+ const absolute = await safeProjectTarget(input.projectRoot, directory2);
88855
+ const entries2 = await readdir20(absolute, { withFileTypes: true }).catch((error) => {
88856
+ if (error.code === "ENOENT")
88857
+ return [];
88858
+ throw error;
88859
+ });
88860
+ for (const entry of entries2) {
88861
+ const path3 = `${directory2}/${entry.name}`;
88862
+ if (entry.isDirectory()) {
88863
+ await inspectTemplates(path3);
88864
+ continue;
88865
+ }
88866
+ if (!entry.isFile() || !entry.name.endsWith(".md"))
88867
+ continue;
88868
+ const bytes = await text9(input.projectRoot, path3);
88869
+ readDigests.push({ path: path3, digest: durableContentDigest(bytes) });
88870
+ replaceMarkdownInlineLinkTargets(bytes, (link2) => {
88871
+ if (/^(?!knowledge:)[a-z][a-z0-9+.-]*:/iu.test(link2.target))
88872
+ return;
88873
+ let destination;
88874
+ try {
88875
+ destination = decodeURI(link2.target.split(/[?#]/u)[0]);
88876
+ } catch {
88877
+ return;
88878
+ }
88879
+ if (destination.startsWith("knowledge:") && !destination.endsWith(".md"))
88880
+ destination += ".md";
88881
+ if ([...selected].some((old) => destination === old || destination.endsWith(`/${old}`) || destination === `knowledge:${old}`)) {
88882
+ blockers.push({ path: path3, target: link2.target, reason: "Update this custom package-template link before retirement." });
88883
+ }
88884
+ return;
88885
+ });
88886
+ }
88887
+ }
88888
+ await inspectTemplates("src/package-templates");
88889
+ const map4 = await readKnowledgeMap(input.projectRoot);
88890
+ if (map4) {
88891
+ const retiredIds = new Map(value.targets.map((target) => [byPath.get(target.path).article_id, target]));
88892
+ const upsert = map4.entries.flatMap((entry) => {
88893
+ const target = entry.target && retiredIds.get(entry.target.artifact_ref);
88894
+ if (!target)
88895
+ return [];
88896
+ if (target.replacement && entry.target?.section_key) {
88897
+ blockers.push({ path: KNOWLEDGE_MAP_PATH, target: entry.key, reason: "Rebind this fragment navigation entry explicitly before retirement." });
88898
+ return [];
88899
+ }
88900
+ const { target: _old, ...group } = entry;
88901
+ return [target.replacement ? { ...group, target: { artifact_ref: byPath.get(target.replacement).article_id } } : group];
88902
+ });
88903
+ const updated = updateKnowledgeMap(map4, { expected_revision: map4.revision, upsert, remove: [] });
88904
+ change(KNOWLEDGE_MAP_PATH, await text9(input.projectRoot, KNOWLEDGE_MAP_PATH), import_yaml41.default.stringify(updated));
88905
+ }
88906
+ change("knowledge/structure.yaml", before, import_yaml41.default.stringify({ ...structure, articles: articles.filter((article) => !selected.has(article.path)) }));
88907
+ targets.sort((a, b) => a.path.localeCompare(b.path));
88908
+ const revision = indexerProtocolDigest({ value, readDigests, targets });
88909
+ const preview = {
88910
+ action: "preview",
88911
+ revision,
88912
+ reason: value.reason,
88913
+ retired: value.targets,
88914
+ changed_files: targets.map((target) => ({ path: target.path, operation: target.operation })),
88915
+ blockers,
88916
+ next_action: { command: blockers.length ? next : `context task retire --input <same-file> --apply --plan-digest '${revision}' --format json` }
88917
+ };
88918
+ if (!input.apply)
88919
+ return preview;
88920
+ if (input.plan_digest !== revision)
88921
+ invalid("article-retirement-preview-stale", "Preview this retirement input again; the selected pages, links or navigation changed.");
88922
+ if (blockers.length)
88923
+ invalid("article-retirement-references-unresolved", "Resolve incoming fragment links before applying retirement.", { blockers });
88924
+ const directory = `.tmp/context-runtime/retirements/${revision.slice(7)}`;
88925
+ const recovery = `${directory}/restore.json`;
88926
+ const receipt2 = `${directory}/receipt.json`;
88927
+ change(recovery, await text9(input.projectRoot, recovery), JSON.stringify({ summary: `Restore retired articles: ${value.reason}`, discard_unfinished: true, files: [...restore] }));
88928
+ change(receipt2, await text9(input.projectRoot, receipt2), JSON.stringify({
88929
+ request: indexerProtocolDigest(value),
88930
+ files: targets.map((target) => ({ path: target.path, digest: target.target_digest }))
88931
+ }));
88932
+ await runDurableMultiFileTransaction({
88933
+ projectRoot: input.projectRoot,
88934
+ kind: "retire-articles",
88935
+ proposal_digest: revision,
88936
+ targets: targets.sort((a, b) => a.path.localeCompare(b.path)),
88937
+ ...input.inject_failure ? { inject_failure: input.inject_failure } : {}
88938
+ });
88939
+ return {
88940
+ action: "applied",
88941
+ revision,
88942
+ retired: [...selected],
88943
+ recovery,
88944
+ next_action: { command: next, message: "Retired pages and references were updated together. Follow the current close/version/build Route before delivering outputs. The restore input is temporary; retain it or a Git baseline if later restoration is needed." }
88945
+ };
88946
+ });
88947
+ }
88948
+ var import_yaml41, articleRetirementSchema, next = "context status --format json";
88949
+ var init_articleRetirement = __esm(() => {
88950
+ init_zod();
88951
+ init_src2();
88952
+ init_errors3();
88953
+ init_cliFeedback();
88954
+ init_exitCode();
88955
+ init_candidateLedger();
88956
+ init_approvedRevision();
88957
+ init_knowledgeUpdate();
88958
+ init_taskRollback();
88959
+ init_maintenanceStorage();
88960
+ init_productionStageStore();
88961
+ init_knowledgeMap2();
88962
+ init_markdownLinks();
88963
+ init_durableSingleFileTransaction();
88964
+ init_durableMultiFileTransaction();
88965
+ init_writeLock();
88966
+ import_yaml41 = __toESM(require_dist(), 1);
88967
+ articleRetirementSchema = exports_external.object({
88968
+ reason: exports_external.string().trim().min(1),
88969
+ targets: exports_external.array(exports_external.object({ path: exports_external.string().min(1), replacement: exports_external.string().min(1).optional() }).strict()).min(1)
88970
+ }).strict();
88971
+ });
88972
+
88973
+ // src/lib/schemaOutput.ts
88974
+ var exports_schemaOutput = {};
88975
+ __export(exports_schemaOutput, {
88976
+ writeSchemaOutput: () => writeSchemaOutput,
88977
+ schemaOutputFormat: () => schemaOutputFormat
88978
+ });
88979
+ function schemaOutputFormat(value) {
88980
+ if (value === "text" || value === "yaml" || value === "json")
88981
+ return value;
88982
+ throw new ContextError(ExitCode.UserError, "Expected schema format text, json, or yaml", { category: ErrorCategory.UserInputInvalid });
88983
+ }
88984
+ function writeSchemaOutput(value, format2) {
88985
+ process.stdout.write(format2 === "json" ? `${JSON.stringify(value, null, 2)}
88986
+ ` : import_yaml42.default.stringify(value));
88987
+ }
88988
+ var import_yaml42;
88989
+ var init_schemaOutput = __esm(() => {
88990
+ init_errors3();
88991
+ init_cliFeedback();
88992
+ init_exitCode();
88993
+ import_yaml42 = __toESM(require_dist(), 1);
88994
+ });
88995
+
88996
+ // src/project/writeLockRecovery.ts
88997
+ var exports_writeLockRecovery = {};
88998
+ __export(exports_writeLockRecovery, {
88999
+ recoverWriterLock: () => recoverWriterLock,
89000
+ inspectWriterLock: () => inspectWriterLock
89001
+ });
89002
+ import { lstat as lstat9, mkdir as mkdir32, readFile as readFile75, readdir as readdir21, rename as rename7, rmdir as rmdir2 } from "node:fs/promises";
89003
+ import { join as join94 } from "node:path";
89004
+ import { createHash as createHash28, randomUUID as randomUUID7 } from "node:crypto";
89005
+ async function inspectWriterLock(root2) {
89006
+ const path3 = await safeProjectTarget(root2, lockRelative);
89007
+ let stat11;
89008
+ try {
89009
+ stat11 = await lstat9(path3);
89010
+ } catch (error) {
89011
+ if (error.code === "ENOENT")
89012
+ return null;
89013
+ throw error;
89014
+ }
89015
+ if (!stat11.isDirectory() || stat11.isSymbolicLink())
89016
+ throw new Error("Writer lock must be a real directory.");
89017
+ const ownerPath = await safeProjectTarget(root2, `${lockRelative}/owner.json`);
89018
+ const bytes = await readFile75(ownerPath, "utf8");
89019
+ const owner = JSON.parse(bytes);
89020
+ if (owner.protocol !== "context.project-write-lock.v1" || !Number.isSafeInteger(owner.pid) || owner.pid <= 0) {
89021
+ throw new Error("Writer lock owner is invalid; preserve the lock for diagnosis.");
89022
+ }
89023
+ let processState = "running";
89024
+ try {
89025
+ process.kill(owner.pid, 0);
89026
+ } catch (error) {
89027
+ const code3 = error.code;
89028
+ processState = code3 === "ESRCH" ? "not-running" : code3 === "EPERM" ? "running" : "unknown";
89029
+ }
89030
+ const digest6 = `sha256:${createHash28("sha256").update(`${stat11.dev}:${stat11.ino}:${stat11.birthtimeMs}:${bytes}`).digest("hex")}`;
89031
+ return { ...owner, process_state: processState, digest: digest6, path: lockRelative };
89032
+ }
89033
+ async function recoverWriterLock(input) {
89034
+ const before = await inspectWriterLock(input.projectRoot);
89035
+ if (!before)
89036
+ return { action: "writer-lock-absent", next: "context task recover --format json" };
89037
+ if (before.process_state !== "not-running")
89038
+ throw new Error("Writer is running or cannot be identified as stopped; keep the lock.");
89039
+ if (!input.apply)
89040
+ return {
89041
+ action: "preview",
89042
+ operation: "writer-lock",
89043
+ revision: before.digest,
89044
+ owner: before,
89045
+ effect: "Archive only this orphan lock. Before applying, stop new workspace commands and confirm no surviving child writer or other host/container uses this workspace. This does not complete interrupted captures or transactions.",
89046
+ next: `${command2} --apply --plan-digest '${before.digest}'`
89047
+ };
89048
+ if (input.plan_digest !== before.digest)
89049
+ throw new Error("Writer lock changed; preview recovery again.");
89050
+ const path3 = join94(input.projectRoot, lockRelative);
89051
+ const guard = join94(path3, ".recovery");
89052
+ await mkdir32(guard);
89053
+ let archived = false;
89054
+ try {
89055
+ const current2 = await inspectWriterLock(input.projectRoot);
89056
+ if (current2?.digest !== before.digest || current2.process_state !== "not-running")
89057
+ throw new Error("Writer lock changed or owner resumed; keep the lock.");
89058
+ const names = await readdir21(path3);
89059
+ if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
89060
+ throw new Error("Unexpected lock contents; preserve for diagnosis.");
89061
+ const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
89062
+ await rename7(path3, join94(input.projectRoot, archive));
89063
+ archived = true;
89064
+ return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
89065
+ } finally {
89066
+ if (!archived)
89067
+ await rmdir2(guard);
89068
+ }
89069
+ }
89070
+ var lockRelative = ".tmp/context-runtime/locks/project-write.lock", command2 = "context task recover --operation writer-lock --format json";
89071
+ var init_writeLockRecovery = __esm(() => {
89072
+ init_durableMultiFileTransaction();
89073
+ });
89074
+
88331
89075
  // src/project/taskRecovery.ts
88332
89076
  var exports_taskRecovery = {};
88333
89077
  __export(exports_taskRecovery, {
@@ -88339,12 +89083,12 @@ __export(exports_taskRecovery, {
88339
89083
  RECOVERY_COMMAND: () => RECOVERY_COMMAND
88340
89084
  });
88341
89085
  import { existsSync as existsSync26 } from "node:fs";
88342
- import { dirname as dirname40, join as join94 } from "node:path";
88343
- import { lstat as lstat9, readdir as readdir20, readFile as readFile74 } from "node:fs/promises";
89086
+ import { dirname as dirname40, join as join95 } from "node:path";
89087
+ import { lstat as lstat10, readdir as readdir22, readFile as readFile76 } from "node:fs/promises";
88344
89088
  async function recoveryText(root2, path3) {
88345
89089
  const target = await safeProjectTarget(root2, path3);
88346
89090
  try {
88347
- return await readFile74(target, "utf8");
89091
+ return await readFile76(target, "utf8");
88348
89092
  } catch (error) {
88349
89093
  if (error.code === "ENOENT")
88350
89094
  return;
@@ -88355,22 +89099,22 @@ async function recoveryJournals(root2) {
88355
89099
  const entries2 = [];
88356
89100
  async function visit4(path3, depth) {
88357
89101
  await safeProjectTarget(root2, path3);
88358
- let stat10;
89102
+ let stat11;
88359
89103
  try {
88360
- stat10 = await lstat9(join94(root2, path3));
89104
+ stat11 = await lstat10(join95(root2, path3));
88361
89105
  } catch (error) {
88362
89106
  if (error.code === "ENOENT")
88363
89107
  return;
88364
89108
  throw error;
88365
89109
  }
88366
- if (stat10.isSymbolicLink())
89110
+ if (stat11.isSymbolicLink())
88367
89111
  throw new TypeError("Recovery does not follow transaction symlinks.");
88368
- if (stat10.isDirectory()) {
89112
+ if (stat11.isDirectory()) {
88369
89113
  if (depth > 3)
88370
89114
  throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
88371
- for (const name3 of (await readdir20(join94(root2, path3))).sort())
89115
+ for (const name3 of (await readdir22(join95(root2, path3))).sort())
88372
89116
  await visit4(`${path3}/${name3}`, depth + 1);
88373
- } else if (stat10.isFile())
89117
+ } else if (stat11.isFile())
88374
89118
  entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
88375
89119
  }
88376
89120
  await visit4(TRANSACTIONS_PATH, 0);
@@ -88380,8 +89124,8 @@ function recoveryResources() {
88380
89124
  try {
88381
89125
  const root2 = dirname40(contextWorkflowProviderPath());
88382
89126
  const resources = {
88383
- skill: join94(root2, "skills/recover-workspace/SKILL.md"),
88384
- issue_template: join94(root2, "resources/templates/recovery-issue.md")
89127
+ skill: join95(root2, "skills/recover-workspace/SKILL.md"),
89128
+ issue_template: join95(root2, "resources/templates/recovery-issue.md")
88385
89129
  };
88386
89130
  if (!Object.values(resources).every((path3) => existsSync26(path3)))
88387
89131
  throw new Error("Recovery resources are absent from this Provider.");
@@ -88402,10 +89146,7 @@ async function inspectTaskRecovery(root2) {
88402
89146
  }
88403
89147
  const stage = await probe("production-stage", () => readProductionStage(root2));
88404
89148
  const journals = await probe("transactions", () => recoveryJournals(root2));
88405
- const lock = await probe("writer-lock", async () => {
88406
- const text9 = await recoveryText(root2, ".tmp/context-runtime/locks/project-write.lock/owner.json");
88407
- return text9 === undefined ? null : JSON.parse(text9);
88408
- });
89149
+ const lock = await probe("writer-lock", () => inspectWriterLock(root2));
88409
89150
  return {
88410
89151
  action: "recovery-inspected",
88411
89152
  resources: recoveryResources(),
@@ -88415,6 +89156,7 @@ async function inspectTaskRecovery(root2) {
88415
89156
  transactions: journals,
88416
89157
  writer_lock: lock,
88417
89158
  actions: [
89159
+ ...lock?.process_state === "not-running" ? [{ operation: "writer-lock", command: `${RECOVERY_COMMAND} --operation writer-lock` }] : [],
88418
89160
  ...journals?.length ? [{ operation: "transactions", command: `${RECOVERY_COMMAND} --operation transactions` }] : [],
88419
89161
  ...stage ? [{ operation: "continue", command: "context status --format json" }] : []
88420
89162
  ],
@@ -88460,6 +89202,7 @@ var init_taskRecovery = __esm(() => {
88460
89202
  init_writeLock();
88461
89203
  init_durableMultiFileTransaction();
88462
89204
  init_workflowProvider();
89205
+ init_writeLockRecovery();
88463
89206
  });
88464
89207
 
88465
89208
  // src/project/taskLocalSourceAdjustment.ts
@@ -88467,8 +89210,8 @@ var exports_taskLocalSourceAdjustment = {};
88467
89210
  __export(exports_taskLocalSourceAdjustment, {
88468
89211
  adjustLocalRevisionSources: () => adjustLocalRevisionSources
88469
89212
  });
88470
- import { readFile as readFile75 } from "node:fs/promises";
88471
- import { join as join95 } from "node:path";
89213
+ import { readFile as readFile77 } from "node:fs/promises";
89214
+ import { join as join96 } from "node:path";
88472
89215
  async function adjustLocalRevisionSources(root2, input) {
88473
89216
  const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
88474
89217
  if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
@@ -88492,11 +89235,11 @@ async function adjustLocalRevisionSources(root2, input) {
88492
89235
  if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
88493
89236
  throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
88494
89237
  }
88495
- const raw = await readFile75(join95(root2, await revisionStoragePath(root2)), "utf8");
88496
- let next;
89238
+ const raw = await readFile77(join96(root2, await revisionStoragePath(root2)), "utf8");
89239
+ let next2;
88497
89240
  const discardIds = new Set;
88498
89241
  if (!input.refresh) {
88499
- next = { ...current2, refresh_sources: selected };
89242
+ next2 = { ...current2, refresh_sources: selected };
88500
89243
  } else {
88501
89244
  const oldScopes = [
88502
89245
  ...revision?.processed_scopes ?? update?.scopes ?? [],
@@ -88570,7 +89313,7 @@ ${input.instruction}`,
88570
89313
 
88571
89314
  ${input.instruction}` : revision.instruction
88572
89315
  };
88573
- next = { ...payload, revision: requestDigest(payload), ...!affected && candidate ? { candidate } : {} };
89316
+ next2 = { ...payload, revision: requestDigest(payload), ...!affected && candidate ? { candidate } : {} };
88574
89317
  if (affected && candidate)
88575
89318
  discardIds.add(candidate.candidate_id);
88576
89319
  } else {
@@ -88578,14 +89321,14 @@ ${input.instruction}` : revision.instruction
88578
89321
  const payload = { ...rest, scopes, requirements, changes: [rest.changes, input.instruction].filter(Boolean).join(`
88579
89322
 
88580
89323
  `) };
88581
- next = { ...payload, revision: indexerProtocolDigest(payload) };
89324
+ next2 = { ...payload, revision: indexerProtocolDigest(payload) };
88582
89325
  }
88583
89326
  }
88584
89327
  if (update && !input.refresh) {
88585
- const { revision: _revision, ...payload } = next;
88586
- next.revision = indexerProtocolDigest(payload);
89328
+ const { revision: _revision, ...payload } = next2;
89329
+ next2.revision = indexerProtocolDigest(payload);
88587
89330
  }
88588
- const content3 = `${JSON.stringify(next)}
89331
+ const content3 = `${JSON.stringify(next2)}
88589
89332
  `;
88590
89333
  const targets = [{
88591
89334
  path: await revisionStoragePath(root2),
@@ -88595,7 +89338,7 @@ ${input.instruction}` : revision.instruction
88595
89338
  content: content3
88596
89339
  }];
88597
89340
  if (discardIds.size > 0) {
88598
- const ledger = await readFile75(join95(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
89341
+ const ledger = await readFile77(join96(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
88599
89342
  if (error.code === "ENOENT")
88600
89343
  return;
88601
89344
  throw error;
@@ -88715,7 +89458,7 @@ var init_taskSourceAdjustment = __esm(() => {
88715
89458
  });
88716
89459
 
88717
89460
  // src/project/managedDocumentImport.ts
88718
- import { readFile as readFile81 } from "node:fs/promises";
89461
+ import { readFile as readFile83 } from "node:fs/promises";
88719
89462
  async function importManagedDocument(projectRoot, value) {
88720
89463
  const input = inputSchema.parse(value);
88721
89464
  if (input.type !== "sessions" && input.changes !== undefined)
@@ -88724,7 +89467,7 @@ async function importManagedDocument(projectRoot, value) {
88724
89467
  const path3 = await assertManagedDocumentPath(projectRoot, input.type, input.name);
88725
89468
  let previous3;
88726
89469
  try {
88727
- previous3 = await readFile81(path3, "utf8");
89470
+ previous3 = await readFile83(path3, "utf8");
88728
89471
  } catch (error) {
88729
89472
  if (!(error && typeof error === "object" && ("code" in error) && error.code === "ENOENT"))
88730
89473
  throw error;
@@ -88771,14 +89514,14 @@ var init_managedDocumentImport = __esm(() => {
88771
89514
  });
88772
89515
 
88773
89516
  // src/project/larkDocumentImport.ts
88774
- import { readFile as readFile82 } from "node:fs/promises";
89517
+ import { readFile as readFile84 } from "node:fs/promises";
88775
89518
  async function importLarkDocument(projectRoot, value) {
88776
89519
  const input = schema3.parse(value);
88777
89520
  const responsePages = [];
88778
89521
  for (const path3 of input.response_files) {
88779
89522
  assertActionInputWorkspace(projectRoot, path3);
88780
89523
  const { resolve: resolve8 } = await import("node:path");
88781
- responsePages.push(await readFile82(resolve8(projectRoot, path3), "utf8"));
89524
+ responsePages.push(await readFile84(resolve8(projectRoot, path3), "utf8"));
88782
89525
  }
88783
89526
  const mediaFiles = {};
88784
89527
  for (const [token, path3] of Object.entries(input.media_files ?? {})) {
@@ -88846,11 +89589,11 @@ var exports_managedDocumentRename = {};
88846
89589
  __export(exports_managedDocumentRename, {
88847
89590
  renameManagedDocument: () => renameManagedDocument
88848
89591
  });
88849
- import { readFile as readFile83 } from "node:fs/promises";
88850
- import { join as join103, posix as posix10 } from "node:path";
89592
+ import { readFile as readFile85 } from "node:fs/promises";
89593
+ import { join as join104, posix as posix11 } from "node:path";
88851
89594
  async function optionalText2(path3) {
88852
89595
  try {
88853
- return await readFile83(path3, "utf8");
89596
+ return await readFile85(path3, "utf8");
88854
89597
  } catch (error) {
88855
89598
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
88856
89599
  return;
@@ -88934,12 +89677,12 @@ async function renameManagedDocument(input) {
88934
89677
  if (path3.split("/").includes("..") || path3.startsWith("/"))
88935
89678
  throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
88936
89679
  await safeProjectTarget(input.projectRoot, path3);
88937
- const before = await optionalText2(join103(input.projectRoot, path3));
89680
+ const before = await optionalText2(join104(input.projectRoot, path3));
88938
89681
  if (before === undefined)
88939
89682
  continue;
88940
89683
  let after;
88941
89684
  if (path3.endsWith(".yaml")) {
88942
- const parsed = import_yaml46.default.parse(before);
89685
+ const parsed = import_yaml48.default.parse(before);
88943
89686
  const updated = replace2(parsed);
88944
89687
  if (path3 === "knowledge/structure.yaml") {
88945
89688
  const rewritten = articles.map((article) => ({ ...article, sections: article.sections.map((section) => ({
@@ -88947,14 +89690,14 @@ async function renameManagedDocument(input) {
88947
89690
  references: section.references.map((citation) => citation.source_ref !== input.source_ref ? citation : {
88948
89691
  ...citation,
88949
89692
  source_ref: nextRef,
88950
- locator: { ...citation.locator, path: posix10.basename(input.name) }
89693
+ locator: { ...citation.locator, path: posix11.basename(input.name) }
88951
89694
  })
88952
89695
  })) }));
88953
89696
  updated.articles = rewritten;
88954
89697
  }
88955
89698
  if (JSON.stringify(parsed) === JSON.stringify(updated))
88956
89699
  continue;
88957
- after = import_yaml46.default.stringify(updated);
89700
+ after = import_yaml48.default.stringify(updated);
88958
89701
  } else
88959
89702
  after = before.replace(reference2, nextRef);
88960
89703
  if (path3 === "src/index.ts")
@@ -88973,11 +89716,11 @@ async function renameManagedDocument(input) {
88973
89716
  return;
88974
89717
  }
88975
89718
  const rooted = destination.startsWith("sources/") || destination.startsWith("/sources/");
88976
- const resolved = rooted ? destination.replace(/^\//u, "") : posix10.normalize(posix10.join(posix10.dirname(path3), destination));
89719
+ const resolved = rooted ? destination.replace(/^\//u, "") : posix11.normalize(posix11.join(posix11.dirname(path3), destination));
88977
89720
  if (resolved !== `sources/${type}/${oldName}`)
88978
89721
  return;
88979
89722
  const renamed = `sources/${type}/${input.name}`;
88980
- return encodeURI(rooted ? `${destination.startsWith("/") ? "/" : ""}${renamed}` : posix10.relative(posix10.dirname(path3), renamed)) + match2[2];
89723
+ return encodeURI(rooted ? `${destination.startsWith("/") ? "/" : ""}${renamed}` : posix11.relative(posix11.dirname(path3), renamed)) + match2[2];
88981
89724
  });
88982
89725
  if (before === after)
88983
89726
  continue;
@@ -89006,7 +89749,7 @@ async function renameManagedDocument(input) {
89006
89749
  };
89007
89750
  });
89008
89751
  }
89009
- var import_yaml46;
89752
+ var import_yaml48;
89010
89753
  var init_managedDocumentRename = __esm(() => {
89011
89754
  init_markdownLinks();
89012
89755
  init_src2();
@@ -89018,12 +89761,12 @@ var init_managedDocumentRename = __esm(() => {
89018
89761
  init_durableSingleFileTransaction();
89019
89762
  init_durableMultiFileTransaction();
89020
89763
  init_writeLock();
89021
- import_yaml46 = __toESM(require_dist(), 1);
89764
+ import_yaml48 = __toESM(require_dist(), 1);
89022
89765
  });
89023
89766
 
89024
89767
  // src/cli.ts
89025
89768
  import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
89026
- import { dirname as dirname47, join as join107 } from "node:path";
89769
+ import { dirname as dirname47, join as join108 } from "node:path";
89027
89770
  import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL3 } from "node:url";
89028
89771
 
89029
89772
  // ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
@@ -89103,7 +89846,7 @@ init_cliFeedback();
89103
89846
  init_errors3();
89104
89847
  init_exitCode();
89105
89848
  import { createHash as createHash21 } from "node:crypto";
89106
- import { mkdir as mkdir26, readdir as readdir16, readFile as readFile60, rm as rm16, stat as stat9, writeFile as writeFile20 } from "node:fs/promises";
89849
+ import { mkdir as mkdir26, readdir as readdir16, readFile as readFile60, rm as rm16, stat as stat10, writeFile as writeFile20 } from "node:fs/promises";
89107
89850
  import { basename as basename8, dirname as dirname32, extname as extname12, join as join72, relative as relative22, resolve as resolve24 } from "node:path";
89108
89851
 
89109
89852
  // src/project/documentCaptureAssets.ts
@@ -89113,7 +89856,7 @@ init_errors3();
89113
89856
  init_exitCode();
89114
89857
  init_markdownLinks();
89115
89858
  import { readFileSync as readFileSync6 } from "node:fs";
89116
- import { mkdir as mkdir24, readFile as readFile57, stat as stat7, writeFile as writeFile18 } from "node:fs/promises";
89859
+ import { mkdir as mkdir24, readFile as readFile57, stat as stat8, writeFile as writeFile18 } from "node:fs/promises";
89117
89860
  import { dirname as dirname29, isAbsolute as isAbsolute13, join as join67, relative as relative20, resolve as resolve21 } from "node:path";
89118
89861
  function runtimeError(message, detail) {
89119
89862
  return new ContextError(ExitCode.UserError, message, {
@@ -89154,7 +89897,7 @@ async function writeCaptureAssetIfChanged(path2, content3) {
89154
89897
  await writeFile18(path2, content3);
89155
89898
  }
89156
89899
  async function readLinkedCaptureAssets(input) {
89157
- const rootStat = await stat7(input.localRoot);
89900
+ const rootStat = await stat8(input.localRoot);
89158
89901
  const boundaryRoot = rootStat.isFile() ? dirname29(input.localRoot) : input.localRoot;
89159
89902
  const bySnapshotPath = new Map;
89160
89903
  for (const file of input.files) {
@@ -89173,7 +89916,7 @@ async function readLinkedCaptureAssets(input) {
89173
89916
  }
89174
89917
  let bytes;
89175
89918
  try {
89176
- const assetStat = await stat7(absolutePath);
89919
+ const assetStat = await stat8(absolutePath);
89177
89920
  if (!assetStat.isFile())
89178
89921
  throw new TypeError("asset target is not a file");
89179
89922
  bytes = await readFile57(absolutePath);
@@ -96967,7 +97710,7 @@ async function readRouteMetadataFiles(input) {
96967
97710
  }
96968
97711
 
96969
97712
  // src/project/documentSiteDetection.ts
96970
- import { readdir as readdir15, stat as stat8 } from "node:fs/promises";
97713
+ import { readdir as readdir15, stat as stat9 } from "node:fs/promises";
96971
97714
  import { basename as basename7, extname as extname11, join as join68, relative as relative21, resolve as resolve22 } from "node:path";
96972
97715
  var SKIPPED_DIRS = new Set([
96973
97716
  ".cache",
@@ -97018,7 +97761,7 @@ async function detectDocumentSiteFiles(input) {
97018
97761
  const result = emptyDetection();
97019
97762
  let rootStats;
97020
97763
  try {
97021
- rootStats = await stat8(localRoot);
97764
+ rootStats = await stat9(localRoot);
97022
97765
  } catch {
97023
97766
  return result;
97024
97767
  }
@@ -97222,7 +97965,7 @@ function assignFlatSnapshotPaths(files, module) {
97222
97965
  });
97223
97966
  }
97224
97967
  async function walkMarkdownFiles(input) {
97225
- const rootStat = await stat9(input.localRoot);
97968
+ const rootStat = await stat10(input.localRoot);
97226
97969
  if (rootStat.isFile()) {
97227
97970
  const sourcePath = normalizeSnapshotRelativePath(basename8(input.localRoot));
97228
97971
  return {
@@ -97839,7 +98582,7 @@ init_cliFeedback();
97839
98582
  init_errors3();
97840
98583
  init_exitCode();
97841
98584
  init_atomicWrite();
97842
- var import_yaml36 = __toESM(require_dist(), 1);
98585
+ var import_yaml37 = __toESM(require_dist(), 1);
97843
98586
  import { existsSync as existsSync20 } from "node:fs";
97844
98587
  import { join as join75 } from "node:path";
97845
98588
  var SOURCE_NAME_PATTERN2 = /^[a-z0-9][a-z0-9._-]*$/u;
@@ -97916,7 +98659,7 @@ async function writeRepoRegistry(projectRoot, registry2) {
97916
98659
  modules.push(registryRecordToYaml(record4));
97917
98660
  namespaces.set(record4.namespace, modules);
97918
98661
  }
97919
- await atomicWriteFile(path2, import_yaml36.default.stringify({
98662
+ await atomicWriteFile(path2, import_yaml37.default.stringify({
97920
98663
  sources: [...namespaces].map(([name3, modules]) => ({ name: name3, modules }))
97921
98664
  }));
97922
98665
  }
@@ -98479,7 +99222,7 @@ init_errors3();
98479
99222
  init_exitCode();
98480
99223
  init_approvedKnowledgeMetadata();
98481
99224
  init_knowledgeAssets();
98482
- var import_yaml37 = __toESM(require_dist(), 1);
99225
+ var import_yaml38 = __toESM(require_dist(), 1);
98483
99226
  import { createHash as createHash22 } from "node:crypto";
98484
99227
  import { mkdir as mkdir28, writeFile as writeFile21 } from "node:fs/promises";
98485
99228
  import { dirname as dirname34, join as join77 } from "node:path";
@@ -98553,7 +99296,7 @@ async function buildApprovedArticleIndex(projectRoot) {
98553
99296
  const block = frontmatterBlock(content3);
98554
99297
  if (block === null)
98555
99298
  continue;
98556
- const parsed = import_yaml37.default.parse(block.yaml);
99299
+ const parsed = import_yaml38.default.parse(block.yaml);
98557
99300
  if (!isRecord14(parsed))
98558
99301
  continue;
98559
99302
  const frontmatter2 = hydrateApprovedFrontmatter({
@@ -98600,13 +99343,13 @@ function updateFrontmatter(content3, mutate) {
98600
99343
  next: "Fix approved Markdown frontmatter before running this review maintenance command."
98601
99344
  });
98602
99345
  }
98603
- const parsed = import_yaml37.default.parse(block.yaml);
99346
+ const parsed = import_yaml38.default.parse(block.yaml);
98604
99347
  if (!isRecord14(parsed)) {
98605
99348
  throw new ContextError(ExitCode.WorkspaceStateError, "approved page frontmatter must be a YAML object", {
98606
99349
  category: ErrorCategory.SchemaInvalid
98607
99350
  });
98608
99351
  }
98609
- const yaml3 = import_yaml37.default.stringify(mutate(parsed)).trimEnd();
99352
+ const yaml3 = import_yaml38.default.stringify(mutate(parsed)).trimEnd();
98610
99353
  return `---
98611
99354
  ${yaml3}
98612
99355
  ---${content3.slice(block.end)}`;
@@ -105437,76 +106180,12 @@ init_errors3();
105437
106180
  init_exitCode();
105438
106181
  init_candidateLedger();
105439
106182
  init_writeLock();
106183
+ init_reviewApplyIndexer();
106184
+ init_approvedKnowledgeSnapshots();
105440
106185
  import { existsSync as existsSync25 } from "node:fs";
105441
106186
  import { readFile as readFile69 } from "node:fs/promises";
105442
106187
  import { join as join91 } from "node:path";
105443
106188
 
105444
- // src/project/reviewApplyIndexer.ts
105445
- init_okfTypes();
105446
- init_packageKnowledgeProjection();
105447
- init_approvedKnowledgeMetadata();
105448
- var import_yaml39 = __toESM(require_dist(), 1);
105449
- function escapeHtmlAttribute(value) {
105450
- return value.replace(/&/gu, "&amp;").replace(/"/gu, "&quot;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
105451
- }
105452
- function sectionMarkdown(section) {
105453
- return [
105454
- `<!-- context:section id="${escapeHtmlAttribute(section.section_key)}" -->`,
105455
- "",
105456
- section.markdown.trimEnd(),
105457
- "",
105458
- "<!-- /context:section -->"
105459
- ].join(`
105460
- `);
105461
- }
105462
- function renderApprovedIndexerMarkdown(input) {
105463
- if (input.record.approved_revision !== undefined) {
105464
- const content3 = compactApprovedKnowledgeMarkdown(ensureApprovedKnowledgePresentation(input.record.body));
105465
- return content3.replace(/^---\r?\n([\s\S]*?)\r?\n---/u, (_match, header) => {
105466
- const metadata = import_yaml39.default.parse(header);
105467
- return ["---", import_yaml39.default.stringify({
105468
- ...metadata,
105469
- type: metadata.type ?? okfTypeForCollection(input.record.collection),
105470
- timestamp: input.timestamp
105471
- }).trimEnd(), "---"].join(`
105472
- `);
105473
- });
105474
- }
105475
- const binding = input.record.indexer_candidate;
105476
- if (input.record.candidate_type !== "indexer-artifact" || binding === undefined) {
105477
- throw new TypeError("Indexer approved renderer requires an indexer-artifact Candidate");
105478
- }
105479
- const title = input.record.review.title;
105480
- const body = binding.sections.flatMap((section, index2) => [
105481
- ...index2 === 0 ? [] : [""],
105482
- sectionMarkdown(section)
105483
- ]).join(`
105484
- `);
105485
- const description = readerKnowledgeDescription({
105486
- description: input.record.review.summary,
105487
- markdown: body,
105488
- title
105489
- });
105490
- const frontmatter2 = import_yaml39.default.stringify({
105491
- title,
105492
- type: okfTypeForCollection(input.record.collection),
105493
- description,
105494
- timestamp: input.timestamp
105495
- }).trimEnd();
105496
- return [
105497
- "---",
105498
- frontmatter2,
105499
- "---",
105500
- "",
105501
- ensureMarkdownPageTitle(body, title),
105502
- ""
105503
- ].join(`
105504
- `);
105505
- }
105506
-
105507
- // src/project/reviewApply.ts
105508
- init_approvedKnowledgeSnapshots();
105509
-
105510
106189
  // src/project/reviewCandidateAuthority.ts
105511
106190
  init_src2();
105512
106191
  init_approvedRevision();
@@ -105604,7 +106283,7 @@ async function prepareApprovedPage(input) {
105604
106283
  const relPath = join91("knowledge", input.record.path);
105605
106284
  const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
105606
106285
  const previousPath = input.record.approved_revision?.previous_path;
105607
- if (previousPath !== undefined && !isSafeKnowledgeTargetPath(input.record.collection, previousPath))
106286
+ if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
105608
106287
  throw new TypeError("Unsafe original page path in a move");
105609
106288
  if (existingView !== undefined && existingView.relPath !== relPath && existingView.relPath !== (previousPath === undefined ? undefined : `knowledge/${previousPath}`)) {
105610
106289
  throw new ContextError(ExitCode.WorkspaceStateError, `approved page already exists for view_ref at a different path: ${input.record.article_id}`, {
@@ -107326,22 +108005,52 @@ function requireProjectRoot2() {
107326
108005
  }
107327
108006
  function registerDocumentRevisionCommand(program2) {
107328
108007
  const task = program2.command("task").description("Explicit current-task recovery");
107329
- task.command("recover").description("Inspect or preview scoped recovery independently of the normal workflow Route").option("--operation <operation>", "inspect or transactions; use ordinary file submission/revise for article repair", "inspect").option("--apply", "apply the reviewed recovery scope within existing user authorization").option("--plan-digest <digest>", "exact current recovery preview").option("--format <format>", "output format: json", "json").action(async (options) => {
108008
+ task.command("retire").description("Preview or apply explicit approved-article retirement and reference cleanup").option("--input <file>", "YAML/JSON reason and targets with optional approved replacement; - for stdin").option("--schema", "show the retirement input schema").option("--apply", "apply the reviewed retirement within existing user authorization").option("--plan-digest <digest>", "exact current retirement preview").option("--format <format>", "output format: json", "json").action(async (options) => {
108009
+ const { retireArticles: retireArticles2, articleRetirementSchema: articleRetirementSchema2 } = await Promise.resolve().then(() => (init_articleRetirement(), exports_articleRetirement));
108010
+ if (options.schema) {
108011
+ const { zodToJsonSchema: zodToJsonSchema3 } = await Promise.resolve().then(() => (init_esm(), exports_esm));
108012
+ const { writeSchemaOutput: writeSchemaOutput2, schemaOutputFormat: schemaOutputFormat2 } = await Promise.resolve().then(() => (init_schemaOutput(), exports_schemaOutput));
108013
+ writeSchemaOutput2(zodToJsonSchema3(articleRetirementSchema2), schemaOutputFormat2(options.format));
108014
+ return;
108015
+ }
108016
+ if (options.format !== "json" || !options.input)
108017
+ throw new ContextError(ExitCode.UserError, "Use --input <file> --format json, or --schema.", { category: ErrorCategory.UserInputInvalid });
108018
+ assertActionInputWorkspace(process.cwd(), options.input);
108019
+ const value = await readYamlOrJsonInput({
108020
+ path: options.input,
108021
+ label: "article retirement",
108022
+ missingNext: "Provide reason and targets with exact approved paths and optional replacement paths.",
108023
+ readFailureNext: "Use an input file in this workspace.",
108024
+ parseFailureNext: "Provide valid YAML or JSON."
108025
+ });
108026
+ const result = await retireArticles2({
108027
+ projectRoot: requireProjectRoot2(),
108028
+ value,
108029
+ ...options.apply ? { apply: true } : {},
108030
+ ...options.planDigest ? { plan_digest: options.planDigest } : {}
108031
+ });
108032
+ if (result.action === "preview" && result.blockers.length === 0)
108033
+ result.next_action.command = `context task retire --input '${options.input.replace(/'/gu, "'\\''")}' --apply --plan-digest '${result.revision}' --format json`;
108034
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
108035
+ `);
108036
+ });
108037
+ task.command("recover").description("Inspect or preview scoped recovery independently of the normal workflow Route").option("--operation <operation>", "inspect, writer-lock or transactions; use ordinary file submission/revise for article repair", "inspect").option("--apply", "apply the reviewed recovery scope within existing user authorization").option("--plan-digest <digest>", "exact current recovery preview").option("--format <format>", "output format: json", "json").action(async (options) => {
107330
108038
  if (options.format !== "json")
107331
108039
  throw new TypeError("--format must be json");
107332
- if (!["inspect", "transactions"].includes(options.operation))
107333
- throw new TypeError("Use inspect or transactions. Repair current task files or use context revise for an accepted article; old workset/plan recovery is not supported.");
108040
+ if (!["inspect", "writer-lock", "transactions"].includes(options.operation))
108041
+ throw new TypeError("Use inspect, writer-lock or transactions. Repair current task files or use context revise for an accepted article; old workset/plan recovery is not supported.");
107334
108042
  if (options.operation === "inspect" && options.apply)
107335
108043
  throw new TypeError("Inspection is read-only; select a recovery operation to apply.");
107336
108044
  const projectRoot = requireProjectRoot2();
107337
108045
  const { inspectTaskRecovery: inspectTaskRecovery2, recoverTaskTransactions: recoverTaskTransactions2 } = await Promise.resolve().then(() => (init_taskRecovery(), exports_taskRecovery));
108046
+ const { recoverWriterLock: recoverWriterLock2 } = await Promise.resolve().then(() => (init_writeLockRecovery(), exports_writeLockRecovery));
107338
108047
  const base = {
107339
108048
  projectRoot,
107340
108049
  ...options.apply ? { apply: true } : {},
107341
108050
  ...options.planDigest ? { plan_digest: options.planDigest } : {}
107342
108051
  };
107343
108052
  try {
107344
- const result = options.operation === "inspect" ? await inspectTaskRecovery2(projectRoot) : await recoverTaskTransactions2(base);
108053
+ const result = options.operation === "inspect" ? await inspectTaskRecovery2(projectRoot) : options.operation === "writer-lock" ? await recoverWriterLock2(base) : await recoverTaskTransactions2(base);
107345
108054
  process.stdout.write(`${JSON.stringify(result, null, 2)}
107346
108055
  `);
107347
108056
  } catch (error) {
@@ -107465,7 +108174,7 @@ function registerDocumentRevisionCommand(program2) {
107465
108174
  process.stdout.write(`${JSON.stringify(await beginKnowledgeUpdate(requireProjectRoot2(), value), null, 2)}
107466
108175
  `);
107467
108176
  });
107468
- program2.command("revise <target>").description("Repair one current Candidate or approved knowledge page through the Indexer lifecycle").requiredOption("--instruction <feedback>", "reader-facing correction request").option("--regenerate", "regenerate program blocks for an approved page, even at the same source version").option("--timing <timing>", "after-batch or priority for approved pages; current Candidates are repaired in place", "after-batch").option("--move-to <path>", "explicit new approved path in the same collection; preserves page identity").option("--format <format>", "output format: json", "json").action(async (target, options) => {
108177
+ program2.command("revise <target>").description("Repair one current Candidate or approved knowledge page through the Indexer lifecycle").requiredOption("--instruction <feedback>", "reader-facing correction request").option("--regenerate", "regenerate program blocks for an approved page, even at the same source version").option("--timing <timing>", "after-batch or priority for approved pages; current Candidates are repaired in place", "after-batch").option("--move-to <path>", "explicit new approved path in any supported collection; preserves page identity").option("--format <format>", "output format: json", "json").action(async (target, options) => {
107469
108178
  if (options.format !== "json") {
107470
108179
  throw new ContextError(ExitCode.UserError, "--format must be json", {
107471
108180
  category: ErrorCategory.UserInputInvalid
@@ -107494,8 +108203,8 @@ function registerDocumentRevisionCommand(program2) {
107494
108203
  init_workspace();
107495
108204
  init_workspaceChangelog();
107496
108205
  function registerVersionCommands(program2) {
107497
- const command2 = program2.command("version").description("Inspect formal changes and record a knowledge workspace SemVer and changelog");
107498
- command2.command("inspect").option("--publish", "include same-version dist changes before publishing").option("--format <format>", "json", "json").action(async (options) => {
108206
+ const command3 = program2.command("version").description("Inspect formal changes and record a knowledge workspace SemVer and changelog");
108207
+ command3.command("inspect").option("--publish", "include same-version dist changes before publishing").option("--format <format>", "json", "json").action(async (options) => {
107499
108208
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107500
108209
  if (!root2)
107501
108210
  throw new TypeError("Run inside a Context workspace");
@@ -107507,7 +108216,7 @@ function registerVersionCommands(program2) {
107507
108216
  }, null, 2) + `
107508
108217
  `);
107509
108218
  });
107510
- command2.command("publish-check").option("--format <format>", "json", "json").action(async () => {
108219
+ command3.command("publish-check").option("--format <format>", "json", "json").action(async () => {
107511
108220
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107512
108221
  if (!root2)
107513
108222
  throw new TypeError("Run inside a Context workspace");
@@ -107515,7 +108224,7 @@ function registerVersionCommands(program2) {
107515
108224
  process.stdout.write(JSON.stringify(await inspectWorkspacePublish2(root2), null, 2) + `
107516
108225
  `);
107517
108226
  });
107518
- command2.command("published").requiredOption("--hash <hash>", "publish-check hash of uploaded artifacts").requiredOption("--receipt <receipt>", "successful external publication receipt").option("--format <format>", "json", "json").action(async (options) => {
108227
+ command3.command("published").requiredOption("--hash <hash>", "publish-check hash of uploaded artifacts").requiredOption("--receipt <receipt>", "successful external publication receipt").option("--format <format>", "json", "json").action(async (options) => {
107519
108228
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107520
108229
  if (!root2)
107521
108230
  throw new TypeError("Run inside a Context workspace");
@@ -107523,7 +108232,7 @@ function registerVersionCommands(program2) {
107523
108232
  process.stdout.write(JSON.stringify(await markWorkspacePublished2(root2, options.hash, options.receipt)) + `
107524
108233
  `);
107525
108234
  });
107526
- command2.command("record").requiredOption("--input <file>", "YAML/JSON file or -").option("--format <format>", "json", "json").action(async (options) => {
108235
+ command3.command("record").requiredOption("--input <file>", "YAML/JSON file or -").option("--format <format>", "json", "json").action(async (options) => {
107527
108236
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107528
108237
  if (!root2)
107529
108238
  throw new TypeError("Run inside a Context workspace");
@@ -107641,10 +108350,10 @@ init_actionInputWorkspace();
107641
108350
 
107642
108351
  // src/project/actionCompletionOutput.ts
107643
108352
  init_atomicWrite();
107644
- var import_yaml41 = __toESM(require_dist(), 1);
108353
+ var import_yaml43 = __toESM(require_dist(), 1);
107645
108354
  import { Buffer as Buffer4 } from "node:buffer";
107646
- import { createHash as createHash28 } from "node:crypto";
107647
- import { join as join96 } from "node:path";
108355
+ import { createHash as createHash29 } from "node:crypto";
108356
+ import { join as join97 } from "node:path";
107648
108357
  var INLINE_LIMIT = 16 * 1024;
107649
108358
  function record4(value) {
107650
108359
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
@@ -107657,7 +108366,7 @@ function shortText(value, limit = 400) {
107657
108366
  }
107658
108367
  function serializeActionCompletion(value, format2) {
107659
108368
  return format2 === "json" ? `${JSON.stringify(value, null, 2)}
107660
- ` : import_yaml41.default.stringify(value);
108369
+ ` : import_yaml43.default.stringify(value);
107661
108370
  }
107662
108371
  async function prepareActionCompletionOutput(input) {
107663
108372
  if (input.verbose)
@@ -107669,9 +108378,9 @@ async function prepareActionCompletionOutput(input) {
107669
108378
  const production = typeof result.stage_state === "string";
107670
108379
  if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
107671
108380
  return input.result;
107672
- const digest6 = createHash28("sha256").update(full).digest("hex");
107673
- const root2 = join96(input.projectRoot, ".tmp/context-runtime/action-results");
107674
- const resultFile = join96(root2, `${digest6}.json`);
108381
+ const digest6 = createHash29("sha256").update(full).digest("hex");
108382
+ const root2 = join97(input.projectRoot, ".tmp/context-runtime/action-results");
108383
+ const resultFile = join97(root2, `${digest6}.json`);
107675
108384
  await atomicWriteFile(resultFile, full);
107676
108385
  if (production)
107677
108386
  return {
@@ -107681,10 +108390,10 @@ async function prepareActionCompletionOutput(input) {
107681
108390
  details: resultFile,
107682
108391
  ...pick(result, ["next", "next_preparation"])
107683
108392
  };
107684
- const next = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
107685
- const nextFile = next === undefined ? undefined : join96(root2, `${digest6}.next.json`);
108393
+ const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
108394
+ const nextFile = next2 === undefined ? undefined : join97(root2, `${digest6}.next.json`);
107686
108395
  if (nextFile !== undefined)
107687
- await atomicWriteFile(nextFile, serializeActionCompletion(next, "json"));
108396
+ await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
107688
108397
  const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
107689
108398
  const counts2 = {};
107690
108399
  for (const item of outcomes) {
@@ -107721,12 +108430,12 @@ async function prepareActionCompletionOutput(input) {
107721
108430
  "task_completion",
107722
108431
  "pages"
107723
108432
  ]),
107724
- next_route: next === undefined ? null : {
108433
+ next_route: next2 === undefined ? null : {
107725
108434
  file: nextFile,
107726
- digest: `sha256:${createHash28("sha256").update(serializeActionCompletion(next, "json")).digest("hex")}`,
107727
- ...pick(next, ["revision", "node", "availability"]),
107728
- commands: next.commands,
107729
- gate: next.gate === undefined ? undefined : pick(record4(next.gate), ["id", "resolution", "delegatable"])
108435
+ digest: `sha256:${createHash29("sha256").update(serializeActionCompletion(next2, "json")).digest("hex")}`,
108436
+ ...pick(next2, ["revision", "node", "availability"]),
108437
+ commands: next2.commands,
108438
+ gate: next2.gate === undefined ? undefined : pick(record4(next2.gate), ["id", "resolution", "delegatable"])
107730
108439
  },
107731
108440
  ...failure2 === undefined ? {} : { next_preparation: {
107732
108441
  outcome: failure2.outcome,
@@ -107740,7 +108449,7 @@ async function prepareActionCompletionOutput(input) {
107740
108449
  summary.outcomes.pop();
107741
108450
  summary.outcomes_omitted++;
107742
108451
  }
107743
- summary.details_required = summary.outcomes_omitted > 0 || failure2?.outcome === "failed" || outcomes.some((item) => !["accepted", "material-expanded"].includes(String(item.outcome))) || outcomes.length === 0 && result.outcome === undefined && result.workflow_summary === undefined || next === undefined && result.workflow_summary === undefined;
108452
+ summary.details_required = summary.outcomes_omitted > 0 || failure2?.outcome === "failed" || outcomes.some((item) => !["accepted", "material-expanded"].includes(String(item.outcome))) || outcomes.length === 0 && result.outcome === undefined && result.workflow_summary === undefined || next2 === undefined && result.workflow_summary === undefined;
107744
108453
  return summary;
107745
108454
  }
107746
108455
 
@@ -107770,34 +108479,34 @@ init_errors3();
107770
108479
  init_cliFeedback();
107771
108480
  init_exitCode();
107772
108481
  init_productionFeedback();
107773
- var import_yaml42 = __toESM(require_dist(), 1);
108482
+ var import_yaml44 = __toESM(require_dist(), 1);
107774
108483
  import { relative as relative24, resolve as resolve32 } from "node:path";
107775
108484
  async function completeCurrentProductionAction(input) {
107776
108485
  return withProductionFeedback({ operation: "action", file: input.submissionPath }, () => withProjectWriteLock(input.projectRoot, "production-action", async () => {
107777
108486
  await recoverDurableMultiFileTransactions(input.projectRoot);
107778
108487
  const stage = await readProductionStage(input.projectRoot);
107779
- const invalid = (message) => new ContextError(ExitCode.UserError, message, {
108488
+ const invalid2 = (message) => new ContextError(ExitCode.UserError, message, {
107780
108489
  category: ErrorCategory.UserInputInvalid,
107781
108490
  reason_code: "invalid-production-submission",
107782
108491
  next_action: { command: "context status --format json" }
107783
108492
  });
107784
108493
  if (!stage)
107785
- throw invalid("The production stage expired. Read the current route; do not restore a previous process.");
108494
+ throw invalid2("The production stage expired. Read the current route; do not restore a previous process.");
107786
108495
  if (input.preview)
107787
- throw invalid("Stage files do not use the retired Author preview. Submit the current task files.");
108496
+ throw invalid2("Stage files do not use the retired Author preview. Submit the current task files.");
107788
108497
  if (!input.submissionPath || input.submissionPath === "-")
107789
- throw invalid("Production requires a stage-local manifest file, not stdin.");
108498
+ throw invalid2("Production requires a stage-local manifest file, not stdin.");
107790
108499
  const path3 = relative24(resolve32(input.projectRoot, productionAgentDirectory(stage.id)), resolve32(input.cwd, input.submissionPath));
107791
108500
  const manifest = await readProductionFile({ projectRoot: input.projectRoot, stage: stage.id, path: path3 });
107792
- const value = import_yaml42.default.parse(manifest.text, { uniqueKeys: true });
108501
+ const value = import_yaml44.default.parse(manifest.text, { uniqueKeys: true });
107793
108502
  if (!value || typeof value !== "object" || !("stage" in value) || value.stage !== stage.id) {
107794
- throw invalid("The manifest must identify the current production stage. No tasks were saved.");
108503
+ throw invalid2("The manifest must identify the current production stage. No tasks were saved.");
107795
108504
  }
107796
108505
  const submission = { projectRoot: input.projectRoot, stage: stage.id, path: path3, manifest, multiAgent: input.multiAgent === true };
107797
108506
  if ("decision" in value)
107798
108507
  return approveProductionReport({ ...submission, revision: input.revision });
107799
108508
  if (input.revision !== stage.id)
107800
- throw invalid("Use the current stage revision; task input handles protect independent submissions.");
108509
+ throw invalid2("Use the current stage revision; task input handles protect independent submissions.");
107801
108510
  if (!stage.planning_complete || "articles" in value)
107802
108511
  return submitProductionPlan(submission);
107803
108512
  return completeProductionSubmission(submission);
@@ -107936,7 +108645,7 @@ init_errors3();
107936
108645
  init_cliFeedback();
107937
108646
  init_exitCode();
107938
108647
  init_productionFeedback();
107939
- var import_yaml43 = __toESM(require_dist(), 1);
108648
+ var import_yaml45 = __toESM(require_dist(), 1);
107940
108649
  import { relative as relative25, resolve as resolve33 } from "node:path";
107941
108650
  var productionKnownTasksSchema = productionPlanInputSchema.omit({ stage: true });
107942
108651
  async function prepareKnownProductionTasks(input) {
@@ -107944,29 +108653,29 @@ async function prepareKnownProductionTasks(input) {
107944
108653
  await recoverDurableMultiFileTransactions(input.projectRoot);
107945
108654
  const path3 = relative25(resolve33(input.projectRoot, ".tmp/agent-work"), resolve33(input.cwd, input.path));
107946
108655
  const fixed2 = await readProductionPlanningFile({ projectRoot: input.projectRoot, path: path3 });
107947
- const invalid = (message) => new ContextError(ExitCode.UserError, message, {
108656
+ const invalid2 = (message) => new ContextError(ExitCode.UserError, message, {
107948
108657
  category: ErrorCategory.UserInputInvalid,
107949
108658
  reason_code: "invalid-known-production-tasks",
107950
108659
  file: input.path,
107951
108660
  input_schema: zodToJsonSchema(productionKnownTasksSchema, { $refStrategy: "none" }),
107952
108661
  next_action: { command: "context status --format json" }
107953
108662
  });
107954
- const plan = productionKnownTasksSchema.parse(import_yaml43.default.parse(fixed2.text, { uniqueKeys: true }));
108663
+ const plan = productionKnownTasksSchema.parse(import_yaml45.default.parse(fixed2.text, { uniqueKeys: true }));
107955
108664
  const request = await productionPlanningRequest(input.projectRoot);
107956
108665
  let stage = await readProductionStage(input.projectRoot);
107957
108666
  if (!request || stage?.report_approved || (stage ? ![stage.id, request.revision].includes(input.revision) : request.revision !== input.revision)) {
107958
- throw invalid("Use known tasks before report approval, with the current preparation revision. Approved stages use ordinary task amendments.");
108667
+ throw invalid2("Use known tasks before report approval, with the current preparation revision. Approved stages use ordinary task amendments.");
107959
108668
  }
107960
108669
  if (!stage) {
107961
108670
  await prepareCurrentProductionStage({ projectRoot: input.projectRoot, revision: input.revision });
107962
108671
  stage = await readProductionStage(input.projectRoot);
107963
108672
  }
107964
- const text9 = import_yaml43.default.stringify({ ...plan, stage: stage.id });
108673
+ const text10 = import_yaml45.default.stringify({ ...plan, stage: stage.id });
107965
108674
  const result = await submitProductionPlan({
107966
108675
  projectRoot: input.projectRoot,
107967
108676
  stage: stage.id,
107968
108677
  path: fixed2.path,
107969
- manifest: { path: fixed2.path, text: text9, bytes: Buffer.byteLength(text9), digest: durableContentDigest(text9) }
108678
+ manifest: { path: fixed2.path, text: text10, bytes: Buffer.byteLength(text10), digest: durableContentDigest(text10) }
107970
108679
  });
107971
108680
  return { ...result, next_action: { command: "context status --format json" } };
107972
108681
  }));
@@ -108083,9 +108792,9 @@ function registerProjectActionCommands(program2) {
108083
108792
  // src/commands/cleanClaudePluginCache.ts
108084
108793
  init_cliFeedback();
108085
108794
  import { existsSync as existsSync27 } from "node:fs";
108086
- import { readdir as readdir21, rm as rm19 } from "node:fs/promises";
108795
+ import { readdir as readdir23, rm as rm19 } from "node:fs/promises";
108087
108796
  import { homedir } from "node:os";
108088
- import { join as join97 } from "node:path";
108797
+ import { join as join98 } from "node:path";
108089
108798
  var ORPHAN_MARKER = ".orphaned_at";
108090
108799
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
108091
108800
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -108098,23 +108807,23 @@ async function cleanClaudePluginCache(opts = {}) {
108098
108807
  lines.push("· claude plugin cache: missing — nothing to clean");
108099
108808
  return { lines, removed, scanned };
108100
108809
  }
108101
- const marketplaces = await readdir21(cacheRoot, { withFileTypes: true });
108810
+ const marketplaces = await readdir23(cacheRoot, { withFileTypes: true });
108102
108811
  for (const mp of marketplaces) {
108103
108812
  if (!mp.isDirectory())
108104
108813
  continue;
108105
- const mpDir = join97(cacheRoot, mp.name);
108106
- const plugins = await readdir21(mpDir, { withFileTypes: true });
108814
+ const mpDir = join98(cacheRoot, mp.name);
108815
+ const plugins = await readdir23(mpDir, { withFileTypes: true });
108107
108816
  for (const pl of plugins) {
108108
108817
  if (!pl.isDirectory())
108109
108818
  continue;
108110
- const plDir = join97(mpDir, pl.name);
108111
- const versions = await readdir21(plDir, { withFileTypes: true });
108819
+ const plDir = join98(mpDir, pl.name);
108820
+ const versions = await readdir23(plDir, { withFileTypes: true });
108112
108821
  for (const ver of versions) {
108113
108822
  if (!ver.isDirectory())
108114
108823
  continue;
108115
108824
  scanned += 1;
108116
- const verDir = join97(plDir, ver.name);
108117
- const markerPath = join97(verDir, ORPHAN_MARKER);
108825
+ const verDir = join98(plDir, ver.name);
108826
+ const markerPath = join98(verDir, ORPHAN_MARKER);
108118
108827
  if (!existsSync27(markerPath))
108119
108828
  continue;
108120
108829
  const label2 = `${mp.name}/${pl.name}/${ver.name}`;
@@ -108146,11 +108855,11 @@ function resolveClaudePluginCacheRoot(opts) {
108146
108855
  if (explicitRoot)
108147
108856
  return explicitRoot;
108148
108857
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
108149
- return join97(home, ".claude", "plugins", "cache");
108858
+ return join98(home, ".claude", "plugins", "cache");
108150
108859
  }
108151
108860
  async function isEmptyDir(dir) {
108152
108861
  try {
108153
- const entries2 = await readdir21(dir);
108862
+ const entries2 = await readdir23(dir);
108154
108863
  return entries2.length === 0;
108155
108864
  } catch {
108156
108865
  return false;
@@ -108178,13 +108887,13 @@ init_exitCode();
108178
108887
 
108179
108888
  // src/lib/packageVersion.ts
108180
108889
  import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
108181
- import { dirname as dirname41, join as join98 } from "node:path";
108890
+ import { dirname as dirname41, join as join99 } from "node:path";
108182
108891
  import { fileURLToPath as fileURLToPath7 } from "node:url";
108183
108892
  function readPackageVersion() {
108184
108893
  try {
108185
108894
  let dir = dirname41(fileURLToPath7(import.meta.url));
108186
108895
  for (let depth = 0;depth < 8; depth += 1) {
108187
- const packagePath = join98(dir, "package.json");
108896
+ const packagePath = join99(dir, "package.json");
108188
108897
  if (existsSync28(packagePath)) {
108189
108898
  const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
108190
108899
  if (typeof parsed.version === "string" && parsed.version.length > 0) {
@@ -108207,12 +108916,12 @@ function readPackageVersion() {
108207
108916
 
108208
108917
  // src/project/sourceCommands.ts
108209
108918
  init_src2();
108210
- import { readFile as readFile84 } from "node:fs/promises";
108919
+ import { readFile as readFile86 } from "node:fs/promises";
108211
108920
  import { isAbsolute as isAbsolute22, resolve as resolve37 } from "node:path";
108212
108921
  init_cliFeedback();
108213
108922
  init_errors3();
108214
108923
  init_exitCode();
108215
- var import_yaml47 = __toESM(require_dist(), 1);
108924
+ var import_yaml49 = __toESM(require_dist(), 1);
108216
108925
 
108217
108926
  // src/project/repoSourceRecovery.ts
108218
108927
  init_cliFeedback();
@@ -108220,7 +108929,7 @@ init_errors3();
108220
108929
  init_exitCode();
108221
108930
  import { execFile as execFile10 } from "node:child_process";
108222
108931
  import { existsSync as existsSync29 } from "node:fs";
108223
- import { lstat as lstat10, mkdir as mkdir32, readlink as readlink2, realpath as realpath8, rm as rm20, symlink as symlink3 } from "node:fs/promises";
108932
+ import { lstat as lstat11, mkdir as mkdir33, readlink as readlink2, realpath as realpath8, rm as rm20, symlink as symlink3 } from "node:fs/promises";
108224
108933
  import { basename as basename11, dirname as dirname42, isAbsolute as isAbsolute19, relative as relative26, resolve as resolve34 } from "node:path";
108225
108934
  import { promisify as promisify10 } from "node:util";
108226
108935
  init_writeLock();
@@ -108404,7 +109113,7 @@ async function cloneCheckout(input) {
108404
109113
  next: `Use local mode with path ${JSON.stringify(target)} after inspecting the existing checkout.`
108405
109114
  });
108406
109115
  }
108407
- await mkdir32(dirname42(target), { recursive: true });
109116
+ await mkdir33(dirname42(target), { recursive: true });
108408
109117
  const cloneArgs = ["clone", "--no-checkout", "--depth=1", "--filter=blob:none", input.remote, target];
108409
109118
  try {
108410
109119
  await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
@@ -108450,7 +109159,7 @@ async function bindLocalAlias(input) {
108450
109159
  return;
108451
109160
  const projectRoot = await realpath8(input.projectRoot);
108452
109161
  const alias = resolve34(projectRoot, input.declaredLocal);
108453
- const stats = await lstat10(alias).catch(() => null);
109162
+ const stats = await lstat11(alias).catch(() => null);
108454
109163
  if (stats !== null) {
108455
109164
  if (stats.isSymbolicLink()) {
108456
109165
  const actual = resolve34(dirname42(alias), await readlink2(alias));
@@ -108469,7 +109178,7 @@ async function bindLocalAlias(input) {
108469
109178
  });
108470
109179
  }
108471
109180
  }
108472
- await mkdir32(dirname42(alias), { recursive: true });
109181
+ await mkdir33(dirname42(alias), { recursive: true });
108473
109182
  await symlink3(relative26(dirname42(alias), input.checkout) || ".", alias);
108474
109183
  }
108475
109184
  function selectPhysicalGroup(sources, selector) {
@@ -108559,11 +109268,11 @@ async function restoreRepositorySources(input) {
108559
109268
  // src/project/sourceDocumentStatus.ts
108560
109269
  init_src2();
108561
109270
  import { existsSync as existsSync30 } from "node:fs";
108562
- import { readFile as readFile77 } from "node:fs/promises";
108563
- import { join as join100 } from "node:path";
109271
+ import { readFile as readFile79 } from "node:fs/promises";
109272
+ import { join as join101 } from "node:path";
108564
109273
  // src/project/sourceCommandViews.ts
108565
- import { readFile as readFile76 } from "node:fs/promises";
108566
- import { join as join99 } from "node:path";
109274
+ import { readFile as readFile78 } from "node:fs/promises";
109275
+ import { join as join100 } from "node:path";
108567
109276
  init_workspace();
108568
109277
  init_documentBatchManifest();
108569
109278
  function repoSourceAgentView(source2) {
@@ -108626,7 +109335,7 @@ async function fileSourceAgentViewWithNextAction(input) {
108626
109335
  };
108627
109336
  }
108628
109337
  function documentSourceManifestPath(source2) {
108629
- return source2.snapshot?.manifest ?? join99(source2.materializedAt, "manifest.json");
109338
+ return source2.snapshot?.manifest ?? join100(source2.materializedAt, "manifest.json");
108630
109339
  }
108631
109340
  async function fileSourceDocumentSiteHint(input) {
108632
109341
  const detection = await detectDocumentSiteFiles({
@@ -108636,7 +109345,7 @@ async function fileSourceDocumentSiteHint(input) {
108636
109345
  let snapshotConfigured = false;
108637
109346
  const manifest = documentSourceManifestPath(input.source);
108638
109347
  try {
108639
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile76(join99(input.projectRoot, manifest), "utf8")), input.source.name);
109348
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile78(join100(input.projectRoot, manifest), "utf8")), input.source.name);
108640
109349
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
108641
109350
  } catch {
108642
109351
  snapshotConfigured = false;
@@ -108668,11 +109377,11 @@ async function larkSourceAgentViewWithNextAction(input) {
108668
109377
  // src/project/sourceDocumentStatus.ts
108669
109378
  init_documentBatchManifest();
108670
109379
  function documentSourceManifestPath2(source2) {
108671
- return source2.snapshot?.manifest ?? join100(source2.materializedAt, "manifest.json");
109380
+ return source2.snapshot?.manifest ?? join101(source2.materializedAt, "manifest.json");
108672
109381
  }
108673
109382
  async function documentSnapshotState(input) {
108674
109383
  const manifest = documentSourceManifestPath2(input.source);
108675
- const manifestPath = join100(input.projectRoot, manifest);
109384
+ const manifestPath = join101(input.projectRoot, manifest);
108676
109385
  if (!existsSync30(manifestPath)) {
108677
109386
  return {
108678
109387
  snapshotReady: false,
@@ -108683,7 +109392,7 @@ async function documentSnapshotState(input) {
108683
109392
  };
108684
109393
  }
108685
109394
  try {
108686
- const parsed = findDocumentSnapshotForSource(JSON.parse(await readFile77(manifestPath, "utf8")), input.source.name);
109395
+ const parsed = findDocumentSnapshotForSource(JSON.parse(await readFile79(manifestPath, "utf8")), input.source.name);
108687
109396
  if (parsed === null) {
108688
109397
  return {
108689
109398
  snapshotReady: false,
@@ -108751,7 +109460,7 @@ async function documentSnapshotState(input) {
108751
109460
  const missing = [
108752
109461
  ...parsed.files.map((file) => file.path),
108753
109462
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
108754
- ].find((path3) => !existsSync30(join100(input.projectRoot, input.source.materializedAt, path3)));
109463
+ ].find((path3) => !existsSync30(join101(input.projectRoot, input.source.materializedAt, path3)));
108755
109464
  if (missing !== undefined) {
108756
109465
  return {
108757
109466
  snapshotReady: false,
@@ -108850,10 +109559,10 @@ init_atomicWrite();
108850
109559
  init_cliFeedback();
108851
109560
  init_errors3();
108852
109561
  init_exitCode();
108853
- var import_yaml44 = __toESM(require_dist(), 1);
108854
- import { createHash as createHash29 } from "node:crypto";
108855
- import { readFile as readFile78, realpath as realpath9 } from "node:fs/promises";
108856
- import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join101, relative as relative27, resolve as resolve35 } from "node:path";
109562
+ var import_yaml46 = __toESM(require_dist(), 1);
109563
+ import { createHash as createHash30 } from "node:crypto";
109564
+ import { readFile as readFile80, realpath as realpath9 } from "node:fs/promises";
109565
+ import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join102, relative as relative27, resolve as resolve35 } from "node:path";
108857
109566
  init_writeLock();
108858
109567
  var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
108859
109568
  function isDateSourceNamespace(value) {
@@ -108882,7 +109591,7 @@ function defaultLarkModule(input) {
108882
109591
  if (titleSlug.length > 0)
108883
109592
  return titleSlug;
108884
109593
  }
108885
- const opaqueSlug = (kind, identity) => `${kind}-${createHash29("sha256").update(identity).digest("hex").slice(0, 12)}`;
109594
+ const opaqueSlug = (kind, identity) => `${kind}-${createHash30("sha256").update(identity).digest("hex").slice(0, 12)}`;
108886
109595
  if (input.url !== undefined) {
108887
109596
  try {
108888
109597
  const parsed = new URL(input.url);
@@ -108949,8 +109658,8 @@ function assertSafeFileInclude(value) {
108949
109658
  }
108950
109659
  async function readRegistryDocument(projectRoot, registryPath2) {
108951
109660
  try {
108952
- const content3 = await readFile78(join101(projectRoot, registryPath2), "utf8");
108953
- return content3.trim().length === 0 ? { sources: [] } : import_yaml44.default.parse(content3);
109661
+ const content3 = await readFile80(join102(projectRoot, registryPath2), "utf8");
109662
+ return content3.trim().length === 0 ? { sources: [] } : import_yaml46.default.parse(content3);
108954
109663
  } catch (error) {
108955
109664
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
108956
109665
  return { sources: [] };
@@ -109067,7 +109776,7 @@ async function addFileSourceUnlocked(input) {
109067
109776
  const record6 = entry2;
109068
109777
  return record6.name !== input.name && record6.id !== input.name;
109069
109778
  }), nextEntry];
109070
- await atomicWriteFile(join101(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml44.default.stringify({ sources: nextSources }));
109779
+ await atomicWriteFile(join102(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml46.default.stringify({ sources: nextSources }));
109071
109780
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
109072
109781
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
109073
109782
  if (entry === undefined) {
@@ -109123,7 +109832,7 @@ async function addLarkSourceUnlocked(input) {
109123
109832
  const record6 = entry2;
109124
109833
  return record6.name !== input.name && record6.id !== input.name;
109125
109834
  }), nextEntry];
109126
- await atomicWriteFile(join101(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml44.default.stringify({ sources: nextSources }));
109835
+ await atomicWriteFile(join102(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml46.default.stringify({ sources: nextSources }));
109127
109836
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
109128
109837
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
109129
109838
  if (entry === undefined) {
@@ -109323,11 +110032,11 @@ init_candidateLedger();
109323
110032
  init_documentBatchManifest();
109324
110033
  init_workspace();
109325
110034
  init_writeLock();
109326
- var import_yaml45 = __toESM(require_dist(), 1);
110035
+ var import_yaml47 = __toESM(require_dist(), 1);
109327
110036
  import { existsSync as existsSync31 } from "node:fs";
109328
- import { createHash as createHash30 } from "node:crypto";
109329
- import { readFile as readFile79, readdir as readdir22, rm as rm21 } from "node:fs/promises";
109330
- import { isAbsolute as isAbsolute21, join as join102, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
110037
+ import { createHash as createHash31 } from "node:crypto";
110038
+ import { readFile as readFile81, readdir as readdir24, rm as rm21 } from "node:fs/promises";
110039
+ import { isAbsolute as isAbsolute21, join as join103, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
109331
110040
  function sourceIdentity(source2) {
109332
110041
  if (source2.kind === "source.collection")
109333
110042
  return;
@@ -109359,10 +110068,10 @@ function collectStrings(value, output) {
109359
110068
  }
109360
110069
  }
109361
110070
  async function yamlReferences(input) {
109362
- const absolutePath = join102(input.projectRoot, input.path);
110071
+ const absolutePath = join103(input.projectRoot, input.path);
109363
110072
  if (!existsSync31(absolutePath))
109364
110073
  return false;
109365
- const parsed = import_yaml45.default.parse(await readFile79(absolutePath, "utf8"));
110074
+ const parsed = import_yaml47.default.parse(await readFile81(absolutePath, "utf8"));
109366
110075
  const strings = [];
109367
110076
  collectStrings(parsed, strings);
109368
110077
  return strings.some((value) => stringReferencesSource(value, input.source));
@@ -109488,11 +110197,11 @@ async function registryRemovalWrite(projectRoot, source2) {
109488
110197
  const path3 = registryPath2(source2.type);
109489
110198
  if (path3 === null)
109490
110199
  return;
109491
- const absolutePath = join102(projectRoot, path3);
109492
- const document4 = existsSync31(absolutePath) ? import_yaml45.default.parse(await readFile79(absolutePath, "utf8")) : { sources: [] };
110200
+ const absolutePath = join103(projectRoot, path3);
110201
+ const document4 = existsSync31(absolutePath) ? import_yaml47.default.parse(await readFile81(absolutePath, "utf8")) : { sources: [] };
109493
110202
  return {
109494
110203
  path: absolutePath,
109495
- bytes: import_yaml45.default.stringify(removeDocumentEntry(document4, source2))
110204
+ bytes: import_yaml47.default.stringify(removeDocumentEntry(document4, source2))
109496
110205
  };
109497
110206
  }
109498
110207
  function safeManagedMaterializedPath(projectRoot, source2) {
@@ -109507,7 +110216,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
109507
110216
  return absolute;
109508
110217
  }
109509
110218
  function safeManagedManifestPath(projectRoot, source2) {
109510
- const manifest = source2.manifest ?? join102(source2.materializedAt, "manifest.json");
110219
+ const manifest = source2.manifest ?? join103(source2.materializedAt, "manifest.json");
109511
110220
  if (isAbsolute21(manifest))
109512
110221
  throw unsafeOwnership(source2, manifest);
109513
110222
  const absolute = resolve36(projectRoot, manifest);
@@ -109542,7 +110251,7 @@ function projectRelative(projectRoot, path3) {
109542
110251
  return relative28(projectRoot, path3).split(sep8).join("/");
109543
110252
  }
109544
110253
  function digest6(value) {
109545
- return `sha256:${createHash30("sha256").update(JSON.stringify(value)).digest("hex")}`;
110254
+ return `sha256:${createHash31("sha256").update(JSON.stringify(value)).digest("hex")}`;
109546
110255
  }
109547
110256
  async function sharedMaterializedOwners(projectRoot, source2) {
109548
110257
  const target = safeManagedMaterializedPath(projectRoot, source2);
@@ -109636,12 +110345,12 @@ async function createRemovalPlan(projectRoot, selector) {
109636
110345
  source: source2,
109637
110346
  registry: registryPath2(source2.type),
109638
110347
  registryBytes: registryWrite?.bytes ?? null,
109639
- managedBytes: source2.type === "note" || source2.type === "sessions" ? await readFile79(absoluteRemovals[0], "utf8") : null,
110348
+ managedBytes: source2.type === "note" || source2.type === "sessions" ? await readFile81(absoluteRemovals[0], "utf8") : null,
109640
110349
  references,
109641
110350
  cleanup,
109642
110351
  manifestBytes: manifestWrite?.bytes ?? null
109643
110352
  });
109644
- const next = references.length > 0 ? `Remove all listed references, then preview context source remove '${source2.id}' --format json again.` : `context source remove '${source2.id}' --yes --plan-digest '${planDigest}' --format json`;
110353
+ const next2 = references.length > 0 ? `Remove all listed references, then preview context source remove '${source2.id}' --format json again.` : `context source remove '${source2.id}' --yes --plan-digest '${planDigest}' --format json`;
109645
110354
  return {
109646
110355
  action: "preview",
109647
110356
  source: source2,
@@ -109650,7 +110359,7 @@ async function createRemovalPlan(projectRoot, selector) {
109650
110359
  references,
109651
110360
  plan_digest: planDigest,
109652
110361
  cleanup,
109653
- next,
110362
+ next: next2,
109654
110363
  ...registryWrite === undefined ? {} : { registryWrite },
109655
110364
  ...manifestWrite !== undefined ? { manifestWrite } : {},
109656
110365
  absoluteRemovals: [...new Set(absoluteRemovals)].sort()
@@ -109669,12 +110378,12 @@ function publicRemovalResult(plan, action) {
109669
110378
  };
109670
110379
  }
109671
110380
  async function pruneExtractRuntime(projectRoot, source2) {
109672
- const fingerprintPath = join102(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
110381
+ const fingerprintPath = join103(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
109673
110382
  const removedPhaseIds = new Set;
109674
110383
  if (existsSync31(fingerprintPath)) {
109675
- const parsed = JSON.parse(await readFile79(fingerprintPath, "utf8"));
110384
+ const parsed = JSON.parse(await readFile81(fingerprintPath, "utf8"));
109676
110385
  const phases = parsed.phases ?? {};
109677
- const next = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
110386
+ const next2 = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
109678
110387
  if (raw === null || typeof raw !== "object" || Array.isArray(raw))
109679
110388
  return true;
109680
110389
  const sources = raw.sources;
@@ -109683,30 +110392,30 @@ async function pruneExtractRuntime(projectRoot, source2) {
109683
110392
  removedPhaseIds.add(phaseId);
109684
110393
  return keep;
109685
110394
  }));
109686
- await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next }, null, 2)}
110395
+ await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
109687
110396
  `);
109688
110397
  }
109689
- const phaseOwnershipPath = join102(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
110398
+ const phaseOwnershipPath = join103(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
109690
110399
  if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
109691
- const parsed = JSON.parse(await readFile79(phaseOwnershipPath, "utf8"));
110400
+ const parsed = JSON.parse(await readFile81(phaseOwnershipPath, "utf8"));
109692
110401
  const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
109693
110402
  await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
109694
110403
  `);
109695
110404
  }
109696
- const symbolPath = join102(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
110405
+ const symbolPath = join103(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
109697
110406
  if (existsSync31(symbolPath)) {
109698
- const parsed = JSON.parse(await readFile79(symbolPath, "utf8"));
110407
+ const parsed = JSON.parse(await readFile81(symbolPath, "utf8"));
109699
110408
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
109700
110409
  const phaseFingerprints = Object.fromEntries(Object.entries(parsed.phaseFingerprints ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
109701
110410
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
109702
110411
  `);
109703
110412
  }
109704
- const snapshotRoot = join102(projectRoot, ".tmp/context-runtime/extract/candidates");
110413
+ const snapshotRoot = join103(projectRoot, ".tmp/context-runtime/extract/candidates");
109705
110414
  const visit4 = async (directory) => {
109706
110415
  if (!existsSync31(directory))
109707
110416
  return;
109708
- for (const entry of await readdir22(directory, { withFileTypes: true })) {
109709
- const path3 = join102(directory, entry.name);
110417
+ for (const entry of await readdir24(directory, { withFileTypes: true })) {
110418
+ const path3 = join103(directory, entry.name);
109710
110419
  if (entry.isDirectory()) {
109711
110420
  await visit4(path3);
109712
110421
  continue;
@@ -109714,7 +110423,7 @@ async function pruneExtractRuntime(projectRoot, source2) {
109714
110423
  if (!entry.isFile() || !entry.name.endsWith(".json"))
109715
110424
  continue;
109716
110425
  try {
109717
- const parsed = JSON.parse(await readFile79(path3, "utf8"));
110426
+ const parsed = JSON.parse(await readFile81(path3, "utf8"));
109718
110427
  const refs = Array.isArray(parsed.source_refs) ? parsed.source_refs : [];
109719
110428
  if (parsed.source === source2.name || refs.some((ref2) => typeof ref2 === "string" && stringReferencesSource(ref2, source2))) {
109720
110429
  await rm21(path3, { force: true });
@@ -109756,7 +110465,7 @@ async function removeProjectSource(input) {
109756
110465
  });
109757
110466
  }
109758
110467
  await applyAtomicFileBatch({
109759
- transactionRoot: join102(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
110468
+ transactionRoot: join103(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
109760
110469
  writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
109761
110470
  removals: plan.absoluteRemovals
109762
110471
  });
@@ -109772,11 +110481,11 @@ init_workspace();
109772
110481
  init_writeLock();
109773
110482
  init_durableMultiFileTransaction();
109774
110483
  init_durableSingleFileTransaction();
109775
- import { readFile as readFile80 } from "node:fs/promises";
110484
+ import { readFile as readFile82 } from "node:fs/promises";
109776
110485
  import ts from "typescript";
109777
- function generateSourceConfiguration(text9, selected) {
109778
- const file = ts.createSourceFile("index.ts", text9, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
109779
- if (ts.transpileModule(text9, { reportDiagnostics: true }).diagnostics?.some((item) => item.category === ts.DiagnosticCategory.Error))
110486
+ function generateSourceConfiguration(text10, selected) {
110487
+ const file = ts.createSourceFile("index.ts", text10, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
110488
+ if (ts.transpileModule(text10, { reportDiagnostics: true }).diagnostics?.some((item) => item.category === ts.DiagnosticCategory.Error))
109780
110489
  return;
109781
110490
  const imports = file.statements.filter(ts.isImportDeclaration).filter((node3) => ts.isStringLiteral(node3.moduleSpecifier) && node3.moduleSpecifier.text === "@c4a/context");
109782
110491
  if (imports.length !== 1)
@@ -109887,7 +110596,7 @@ function generateSourceConfiguration(text9, selected) {
109887
110596
  }
109888
110597
  }
109889
110598
  if (!additions.length && !captures.length)
109890
- return text9;
110599
+ return text10;
109891
110600
  const identifiers = new Set;
109892
110601
  const visit4 = (node3) => {
109893
110602
  if (ts.isIdentifier(node3))
@@ -109907,12 +110616,12 @@ function generateSourceConfiguration(text9, selected) {
109907
110616
  }
109908
110617
  if (needed.size)
109909
110618
  edits.push({ start: bindings.getStart(file) + 1, end: bindings.getStart(file) + 1, value: ` ${[...needed].join(", ")},` });
109910
- return edits.sort((a, b) => b.start - a.start).reduce((result, edit) => result.slice(0, edit.start) + edit.value + result.slice(edit.end), text9);
110619
+ return edits.sort((a, b) => b.start - a.start).reduce((result, edit) => result.slice(0, edit.start) + edit.value + result.slice(edit.end), text10);
109911
110620
  }
109912
110621
  async function configureRegisteredSources(projectRoot, selected) {
109913
110622
  return withProjectWriteLock(projectRoot, "source-project-configuration", async () => {
109914
110623
  const path3 = "src/index.ts";
109915
- const config = JSON.parse(await readFile80(await safeProjectTarget(projectRoot, "package.json"), "utf8"));
110624
+ const config = JSON.parse(await readFile82(await safeProjectTarget(projectRoot, "package.json"), "utf8"));
109916
110625
  if (config.context?.entry !== path3)
109917
110626
  return {
109918
110627
  status: "manual",
@@ -109921,8 +110630,8 @@ async function configureRegisteredSources(projectRoot, selected) {
109921
110630
  sources: selected
109922
110631
  };
109923
110632
  const target = await safeProjectTarget(projectRoot, path3);
109924
- const text9 = await readFile80(target, "utf8");
109925
- const updated = generateSourceConfiguration(text9, selected);
110633
+ const text10 = await readFile82(target, "utf8");
110634
+ const updated = generateSourceConfiguration(text10, selected);
109926
110635
  if (updated === undefined)
109927
110636
  return {
109928
110637
  status: "manual",
@@ -109930,15 +110639,15 @@ async function configureRegisteredSources(projectRoot, selected) {
109930
110639
  message: "Registration is saved. Preserve the custom project entry and configure only these sources manually.",
109931
110640
  sources: selected
109932
110641
  };
109933
- if (updated !== text9)
110642
+ if (updated !== text10)
109934
110643
  await runDurableSingleFileTransaction({
109935
110644
  projectRoot,
109936
110645
  kind: "source-project-configuration",
109937
110646
  target_path: path3,
109938
- expected_base_digest: durableContentDigest(text9),
110647
+ expected_base_digest: durableContentDigest(text10),
109939
110648
  target_content: updated
109940
110649
  });
109941
- return { status: updated === text9 ? "unchanged" : "configured", file: path3 };
110650
+ return { status: updated === text10 ? "unchanged" : "configured", file: path3 };
109942
110651
  });
109943
110652
  }
109944
110653
 
@@ -110001,7 +110710,7 @@ async function readIncludeList(projectRoot, path3) {
110001
110710
  }
110002
110711
  let content3;
110003
110712
  try {
110004
- content3 = await readFile84(isAbsolute22(trimmed) ? resolve37(trimmed) : resolve37(projectRoot, trimmed), "utf8");
110713
+ content3 = await readFile86(isAbsolute22(trimmed) ? resolve37(trimmed) : resolve37(projectRoot, trimmed), "utf8");
110005
110714
  } catch (error) {
110006
110715
  throw new ContextError(ExitCode.UserError, `cannot read include list: ${trimmed}`, {
110007
110716
  category: ErrorCategory.UserInputInvalid,
@@ -110042,7 +110751,7 @@ function rowsFromValue(value) {
110042
110751
  return value.map((item) => item && typeof item === "object" && !Array.isArray(item) ? item : { value: item });
110043
110752
  }
110044
110753
  if (value && typeof value === "object") {
110045
- return Object.entries(value).map(([key, next]) => ({ key, value: next }));
110754
+ return Object.entries(value).map(([key, next2]) => ({ key, value: next2 }));
110046
110755
  }
110047
110756
  return [{ value }];
110048
110757
  }
@@ -110069,7 +110778,7 @@ function writeFormatted(value, format2) {
110069
110778
  return;
110070
110779
  }
110071
110780
  if (format2 === "yaml") {
110072
- process.stdout.write(import_yaml47.default.stringify(value));
110781
+ process.stdout.write(import_yaml49.default.stringify(value));
110073
110782
  return;
110074
110783
  }
110075
110784
  process.stdout.write(renderTable2(value));
@@ -110390,16 +111099,16 @@ report shown above. A direct maintenance call outside that Route may omit it.
110390
111099
  init_cliFeedback();
110391
111100
  init_errors3();
110392
111101
  init_exitCode();
110393
- var import_yaml49 = __toESM(require_dist(), 1);
111102
+ var import_yaml51 = __toESM(require_dist(), 1);
110394
111103
 
110395
111104
  // src/project/productionSkillCatalog.ts
110396
111105
  init_errors3();
110397
111106
  init_cliFeedback();
110398
111107
  init_exitCode();
110399
- var import_yaml48 = __toESM(require_dist(), 1);
111108
+ var import_yaml50 = __toESM(require_dist(), 1);
110400
111109
  import { constants as constants6, existsSync as existsSync32 } from "node:fs";
110401
- import { lstat as lstat11, open as open5, readdir as readdir23 } from "node:fs/promises";
110402
- import { dirname as dirname43, join as join104, resolve as resolve38 } from "node:path";
111110
+ import { lstat as lstat12, open as open5, readdir as readdir25 } from "node:fs/promises";
111111
+ import { dirname as dirname43, join as join105, resolve as resolve38 } from "node:path";
110403
111112
  import { fileURLToPath as fileURLToPath8 } from "node:url";
110404
111113
  function bundledSkillRoot() {
110405
111114
  const directory = dirname43(fileURLToPath8(import.meta.url));
@@ -110426,11 +111135,11 @@ async function listProductionSkills(root2) {
110426
111135
  }
110427
111136
  }
110428
111137
  async function readProductionSkills(root2) {
110429
- const entries2 = (await readdir23(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
111138
+ const entries2 = (await readdir25(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
110430
111139
  const skills = [];
110431
111140
  for (const directory of entries2) {
110432
- const entry = join104(root2, directory.name, "SKILL.md");
110433
- if (!(await lstat11(entry)).isFile())
111141
+ const entry = join105(root2, directory.name, "SKILL.md");
111142
+ if (!(await lstat12(entry)).isFile())
110434
111143
  throw new TypeError(`Skill entry must be a regular file: ${entry}`);
110435
111144
  const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
110436
111145
  let header;
@@ -110446,7 +111155,7 @@ async function readProductionSkills(root2) {
110446
111155
  const frontmatter2 = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(header);
110447
111156
  if (!frontmatter2)
110448
111157
  throw new TypeError(`Skill entry needs complete frontmatter within 64 KiB: ${entry}`);
110449
- const value = import_yaml48.default.parse(frontmatter2[1], { uniqueKeys: true });
111158
+ const value = import_yaml50.default.parse(frontmatter2[1], { uniqueKeys: true });
110450
111159
  if (!value || typeof value !== "object" || !("name" in value) || typeof value.name !== "string" || !value.name.trim() || !("description" in value) || typeof value.description !== "string" || !value.description.trim()) {
110451
111160
  throw new TypeError(`Skill entry needs a name and description: ${entry}`);
110452
111161
  }
@@ -110509,7 +111218,7 @@ function outputFormat2(options) {
110509
111218
  }
110510
111219
  function writeOutput(value, format2) {
110511
111220
  process.stdout.write(format2 === "json" ? `${JSON.stringify(value, null, 2)}
110512
- ` : import_yaml49.default.stringify(value));
111221
+ ` : import_yaml51.default.stringify(value));
110513
111222
  }
110514
111223
  function registerProjectIndexerCommands(program2) {
110515
111224
  const indexer = program2.command("indexer").description("Discover bundled skills or inspect a benchmark result");
@@ -110593,7 +111302,7 @@ function initCommand2(input, projectDir) {
110593
111302
  return args.map(shellQuote7).join(" ");
110594
111303
  }
110595
111304
  function readyResult(input, projectRoot, relocation) {
110596
- const command2 = workflowCommand(input);
111305
+ const command3 = workflowCommand(input);
110597
111306
  return {
110598
111307
  schema: "context.entry.v1",
110599
111308
  guidance: {
@@ -110610,7 +111319,7 @@ function readyResult(input, projectRoot, relocation) {
110610
111319
  },
110611
111320
  next_action: {
110612
111321
  kind: relocation ? "enter-workspace" : "evaluate-workflow",
110613
- command: relocation ? `cd ${shellQuote7(projectRoot)} && ${command2}` : command2,
111322
+ command: relocation ? `cd ${shellQuote7(projectRoot)} && ${command3}` : command3,
110614
111323
  effect: "read",
110615
111324
  confirmation: "not-required"
110616
111325
  }
@@ -110837,7 +111546,7 @@ init_cliFeedback();
110837
111546
  init_errors3();
110838
111547
  init_exitCode();
110839
111548
  import { existsSync as existsSync35 } from "node:fs";
110840
- import { dirname as dirname46, join as join106, resolve as resolve40 } from "node:path";
111549
+ import { dirname as dirname46, join as join107, resolve as resolve40 } from "node:path";
110841
111550
  import { fileURLToPath as fileURLToPath9 } from "node:url";
110842
111551
 
110843
111552
  // src/project/pluginInstallTargets.ts
@@ -110846,9 +111555,9 @@ init_errors3();
110846
111555
  init_exitCode();
110847
111556
  import { execFile as execFile11 } from "node:child_process";
110848
111557
  import { existsSync as existsSync34 } from "node:fs";
110849
- import { cp as cp2, mkdir as mkdir33, readdir as readdir24, readFile as readFile85, rename as rename7, rm as rm22, writeFile as writeFile25 } from "node:fs/promises";
111558
+ import { cp as cp2, mkdir as mkdir34, readdir as readdir26, readFile as readFile87, rename as rename8, rm as rm22, writeFile as writeFile25 } from "node:fs/promises";
110850
111559
  import { homedir as homedir2 } from "node:os";
110851
- import { dirname as dirname45, join as join105 } from "node:path";
111560
+ import { dirname as dirname45, join as join106 } from "node:path";
110852
111561
  import { promisify as promisify11 } from "node:util";
110853
111562
  var execFileAsync7 = promisify11(execFile11);
110854
111563
  var MARKETPLACE_NAME = "c4a";
@@ -110864,31 +111573,31 @@ var CURSOR_PLUGIN_ROOT_ENV = "CONTEXT_CURSOR_PLUGIN_ROOT";
110864
111573
  function shellQuote8(value) {
110865
111574
  return `'${value.replace(/'/g, "'\\''")}'`;
110866
111575
  }
110867
- function commandLine(command2, args) {
110868
- return [command2, ...args.map((arg) => shellQuote8(arg))].join(" ");
111576
+ function commandLine(command3, args) {
111577
+ return [command3, ...args.map((arg) => shellQuote8(arg))].join(" ");
110869
111578
  }
110870
- async function runExternal(command2, args) {
111579
+ async function runExternal(command3, args) {
110871
111580
  try {
110872
- await execFileAsync7(command2, args, {
111581
+ await execFileAsync7(command3, args, {
110873
111582
  maxBuffer: 1024 * 1024
110874
111583
  });
110875
111584
  } catch (error) {
110876
111585
  const message = error instanceof Error ? error.message : String(error);
110877
- throw new ContextError(ExitCode.ExternalToolError, `${commandLine(command2, args)} failed: ${message}`, {
111586
+ throw new ContextError(ExitCode.ExternalToolError, `${commandLine(command3, args)} failed: ${message}`, {
110878
111587
  category: ErrorCategory.ExternalToolFailed
110879
111588
  });
110880
111589
  }
110881
111590
  }
110882
- async function runExternalOptional(command2, args) {
111591
+ async function runExternalOptional(command3, args) {
110883
111592
  try {
110884
- await runExternal(command2, args);
111593
+ await runExternal(command3, args);
110885
111594
  return true;
110886
111595
  } catch {
110887
111596
  return false;
110888
111597
  }
110889
111598
  }
110890
- async function commandAvailable(command2) {
110891
- return runExternalOptional("sh", ["-lc", `command -v ${command2} >/dev/null 2>&1`]);
111599
+ async function commandAvailable(command3) {
111600
+ return runExternalOptional("sh", ["-lc", `command -v ${command3} >/dev/null 2>&1`]);
110892
111601
  }
110893
111602
  async function claudePluginInstalled(pluginId) {
110894
111603
  try {
@@ -110902,23 +111611,23 @@ async function claudePluginInstalled(pluginId) {
110902
111611
  }
110903
111612
  }
110904
111613
  function codexHome() {
110905
- return process.env.CODEX_HOME?.trim() || join105(homedir2(), ".codex");
111614
+ return process.env.CODEX_HOME?.trim() || join106(homedir2(), ".codex");
110906
111615
  }
110907
111616
  function claudePluginCacheRoot() {
110908
111617
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
110909
111618
  if (explicitRoot)
110910
111619
  return explicitRoot;
110911
111620
  const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
110912
- return join105(home, ".claude", "plugins", "cache");
111621
+ return join106(home, ".claude", "plugins", "cache");
110913
111622
  }
110914
111623
  function sharedSkillsRoot() {
110915
- return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join105(homedir2(), ".agents", "skills");
111624
+ return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join106(homedir2(), ".agents", "skills");
110916
111625
  }
110917
111626
  function claudeSkillsRoot() {
110918
- return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join105(homedir2(), ".claude", "skills");
111627
+ return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join106(homedir2(), ".claude", "skills");
110919
111628
  }
110920
111629
  function cursorPluginRoot() {
110921
- return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join105(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
111630
+ return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join106(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
110922
111631
  }
110923
111632
  function blockHeader(line) {
110924
111633
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -110929,9 +111638,9 @@ function isStaleMarketplaceBlock(header, block) {
110929
111638
  return true;
110930
111639
  if (header !== `marketplaces.${MARKETPLACE_NAME}`)
110931
111640
  return false;
110932
- const text9 = block.join(`
111641
+ const text10 = block.join(`
110933
111642
  `);
110934
- return text9.includes('source_type = "local"') || text9.includes("/c4a-plugins") || text9.includes("context4ai/context");
111643
+ return text10.includes('source_type = "local"') || text10.includes("/c4a-plugins") || text10.includes("context4ai/context");
110935
111644
  }
110936
111645
  function isStalePluginBlock(header) {
110937
111646
  return header === `plugins."context@context"` || header === `plugins."context@c4a"` || header === "plugins.context";
@@ -110969,27 +111678,27 @@ function pruneLegacyCodexConfigContent(content3) {
110969
111678
  `), removed };
110970
111679
  }
110971
111680
  async function pruneLegacyCodexConfig(dryRun, steps) {
110972
- const configPath = join105(codexHome(), "config.toml");
110973
- const current2 = await readFile85(configPath, "utf8").catch(() => "");
111681
+ const configPath = join106(codexHome(), "config.toml");
111682
+ const current2 = await readFile87(configPath, "utf8").catch(() => "");
110974
111683
  if (!current2)
110975
111684
  return;
110976
- const next = pruneLegacyCodexConfigContent(current2);
110977
- if (next.removed.length === 0)
111685
+ const next2 = pruneLegacyCodexConfigContent(current2);
111686
+ if (next2.removed.length === 0)
110978
111687
  return;
110979
111688
  steps.push({
110980
111689
  agent: "codex",
110981
- command: `prune stale Codex config blocks: ${next.removed.join(", ")}`,
111690
+ command: `prune stale Codex config blocks: ${next2.removed.join(", ")}`,
110982
111691
  status: dryRun ? "planned" : "ran"
110983
111692
  });
110984
111693
  if (!dryRun) {
110985
- await writeFile25(configPath, next.content, "utf8");
111694
+ await writeFile25(configPath, next2.content, "utf8");
110986
111695
  }
110987
111696
  }
110988
111697
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
110989
- const cacheRoot = join105(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
111698
+ const cacheRoot = join106(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
110990
111699
  if (!existsSync34(cacheRoot))
110991
111700
  return;
110992
- const versions = (await readdir24(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
111701
+ const versions = (await readdir26(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
110993
111702
  if (versions.length === 0)
110994
111703
  return;
110995
111704
  steps.push({
@@ -110998,7 +111707,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
110998
111707
  status: dryRun ? "planned" : "ran"
110999
111708
  });
111000
111709
  if (!dryRun)
111001
- await Promise.all(versions.map((version3) => rm22(join105(cacheRoot, version3), { recursive: true, force: true })));
111710
+ await Promise.all(versions.map((version3) => rm22(join106(cacheRoot, version3), { recursive: true, force: true })));
111002
111711
  }
111003
111712
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
111004
111713
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -111008,7 +111717,7 @@ async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
111008
111717
  }
111009
111718
  async function isEmptyDir2(dir) {
111010
111719
  try {
111011
- return (await readdir24(dir)).length === 0;
111720
+ return (await readdir26(dir)).length === 0;
111012
111721
  } catch {
111013
111722
  return false;
111014
111723
  }
@@ -111018,19 +111727,19 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
111018
111727
  if (!existsSync34(cacheRoot))
111019
111728
  return;
111020
111729
  const removed = [];
111021
- const marketplaces = await readdir24(cacheRoot, { withFileTypes: true }).catch(() => []);
111730
+ const marketplaces = await readdir26(cacheRoot, { withFileTypes: true }).catch(() => []);
111022
111731
  for (const marketplace of marketplaces) {
111023
111732
  if (!marketplace.isDirectory())
111024
111733
  continue;
111025
- const pluginDir = join105(cacheRoot, marketplace.name, PLUGIN_NAME);
111734
+ const pluginDir = join106(cacheRoot, marketplace.name, PLUGIN_NAME);
111026
111735
  if (!existsSync34(pluginDir))
111027
111736
  continue;
111028
- const versions = await readdir24(pluginDir, { withFileTypes: true }).catch(() => []);
111737
+ const versions = await readdir26(pluginDir, { withFileTypes: true }).catch(() => []);
111029
111738
  for (const version3 of versions) {
111030
111739
  if (!version3.isDirectory())
111031
111740
  continue;
111032
- const versionDir = join105(pluginDir, version3.name);
111033
- if (!existsSync34(join105(versionDir, ORPHAN_MARKER2)))
111741
+ const versionDir = join106(pluginDir, version3.name);
111742
+ if (!existsSync34(join106(versionDir, ORPHAN_MARKER2)))
111034
111743
  continue;
111035
111744
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
111036
111745
  if (!dryRun) {
@@ -111040,7 +111749,7 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
111040
111749
  if (!dryRun && await isEmptyDir2(pluginDir)) {
111041
111750
  await rm22(pluginDir, { recursive: true, force: true });
111042
111751
  }
111043
- const marketplaceDir = join105(cacheRoot, marketplace.name);
111752
+ const marketplaceDir = join106(cacheRoot, marketplace.name);
111044
111753
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
111045
111754
  await rm22(marketplaceDir, { recursive: true, force: true });
111046
111755
  }
@@ -111061,7 +111770,7 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
111061
111770
  return;
111062
111771
  const removed = [];
111063
111772
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
111064
- const pluginDir = join105(cacheRoot, MARKETPLACE_NAME, pluginName);
111773
+ const pluginDir = join106(cacheRoot, MARKETPLACE_NAME, pluginName);
111065
111774
  if (!existsSync34(pluginDir))
111066
111775
  continue;
111067
111776
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
@@ -111078,12 +111787,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
111078
111787
  }
111079
111788
  }
111080
111789
  async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
111081
- const manifest = await readFile85(join105(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
111790
+ const manifest = await readFile87(join106(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
111082
111791
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
111083
111792
  if (!currentVersion)
111084
111793
  return;
111085
- const pluginDir = join105(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
111086
- const staleVersions = (await readdir24(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
111794
+ const pluginDir = join106(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
111795
+ const staleVersions = (await readdir26(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
111087
111796
  if (staleVersions.length === 0)
111088
111797
  return;
111089
111798
  steps.push({
@@ -111092,7 +111801,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
111092
111801
  status: dryRun ? "planned" : "ran"
111093
111802
  });
111094
111803
  if (!dryRun) {
111095
- await Promise.all(staleVersions.map((version3) => rm22(join105(pluginDir, version3), { recursive: true, force: true })));
111804
+ await Promise.all(staleVersions.map((version3) => rm22(join106(pluginDir, version3), { recursive: true, force: true })));
111096
111805
  }
111097
111806
  }
111098
111807
  function enableCodexPluginConfig(content3) {
@@ -111156,36 +111865,36 @@ source = ${JSON.stringify(root2)}
111156
111865
  `;
111157
111866
  }
111158
111867
  async function ensureCodexPluginEnabled() {
111159
- const configPath = join105(codexHome(), "config.toml");
111160
- await mkdir33(dirname45(configPath), { recursive: true });
111161
- const current2 = await readFile85(configPath, "utf8").catch(() => "");
111162
- const next = enableCodexPluginConfig(current2);
111163
- if (next !== current2) {
111164
- await writeFile25(configPath, next, "utf8");
111868
+ const configPath = join106(codexHome(), "config.toml");
111869
+ await mkdir34(dirname45(configPath), { recursive: true });
111870
+ const current2 = await readFile87(configPath, "utf8").catch(() => "");
111871
+ const next2 = enableCodexPluginConfig(current2);
111872
+ if (next2 !== current2) {
111873
+ await writeFile25(configPath, next2, "utf8");
111165
111874
  }
111166
111875
  }
111167
111876
  async function ensureCodexLocalMarketplace(root2) {
111168
- const configPath = join105(codexHome(), "config.toml");
111169
- await mkdir33(dirname45(configPath), { recursive: true });
111170
- const current2 = await readFile85(configPath, "utf8").catch(() => "");
111171
- const next = upsertCodexLocalMarketplaceConfig(current2, root2);
111172
- if (next !== current2) {
111173
- await writeFile25(configPath, next, "utf8");
111877
+ const configPath = join106(codexHome(), "config.toml");
111878
+ await mkdir34(dirname45(configPath), { recursive: true });
111879
+ const current2 = await readFile87(configPath, "utf8").catch(() => "");
111880
+ const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
111881
+ if (next2 !== current2) {
111882
+ await writeFile25(configPath, next2, "utf8");
111174
111883
  }
111175
111884
  }
111176
111885
  async function codexPluginVersion(root2) {
111177
- const manifestPath = join105(root2, "codex", ".codex-plugin", "plugin.json");
111178
- const manifest = JSON.parse(await readFile85(manifestPath, "utf8"));
111886
+ const manifestPath = join106(root2, "codex", ".codex-plugin", "plugin.json");
111887
+ const manifest = JSON.parse(await readFile87(manifestPath, "utf8"));
111179
111888
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
111180
111889
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
111181
111890
  }
111182
111891
  return manifest.version;
111183
111892
  }
111184
111893
  function codexPluginCacheDir(version3) {
111185
- return join105(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
111894
+ return join106(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
111186
111895
  }
111187
111896
  async function replaceDirectoryFromSource(source2, target) {
111188
- await mkdir33(dirname45(target), { recursive: true });
111897
+ await mkdir34(dirname45(target), { recursive: true });
111189
111898
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
111190
111899
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
111191
111900
  await rm22(temporary, { recursive: true, force: true });
@@ -111193,19 +111902,19 @@ async function replaceDirectoryFromSource(source2, target) {
111193
111902
  const hadPrevious = existsSync34(target);
111194
111903
  try {
111195
111904
  if (hadPrevious)
111196
- await rename7(target, previous3);
111197
- await rename7(temporary, target);
111905
+ await rename8(target, previous3);
111906
+ await rename8(temporary, target);
111198
111907
  if (hadPrevious)
111199
111908
  await rm22(previous3, { recursive: true, force: true });
111200
111909
  } catch (error) {
111201
111910
  await rm22(temporary, { recursive: true, force: true });
111202
111911
  if (hadPrevious && !existsSync34(target) && existsSync34(previous3))
111203
- await rename7(previous3, target);
111912
+ await rename8(previous3, target);
111204
111913
  throw error;
111205
111914
  }
111206
111915
  }
111207
111916
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
111208
- const source2 = join105(root2, "codex");
111917
+ const source2 = join106(root2, "codex");
111209
111918
  const target = codexPluginCacheDir(version3);
111210
111919
  steps.push({
111211
111920
  agent: "codex",
@@ -111217,16 +111926,16 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
111217
111926
  await replaceDirectoryFromSource(source2, target);
111218
111927
  }
111219
111928
  async function bundledProviderSkillNames(root2) {
111220
- const skillsRoot = join105(root2, "skills");
111221
- const entries2 = await readdir24(skillsRoot, { withFileTypes: true });
111929
+ const skillsRoot = join106(root2, "skills");
111930
+ const entries2 = await readdir26(skillsRoot, { withFileTypes: true });
111222
111931
  const names = [];
111223
111932
  for (const entry of entries2) {
111224
111933
  if (!entry.isDirectory() || entry.name === "context")
111225
111934
  continue;
111226
- const skillPath = join105(skillsRoot, entry.name, "SKILL.md");
111935
+ const skillPath = join106(skillsRoot, entry.name, "SKILL.md");
111227
111936
  if (!existsSync34(skillPath))
111228
111937
  continue;
111229
- const skill = await readFile85(skillPath, "utf8");
111938
+ const skill = await readFile87(skillPath, "utf8");
111230
111939
  if (!/^\s*context-role:\s*["']?indexer-provider["']?\s*$/mu.test(skill))
111231
111940
  continue;
111232
111941
  names.push(entry.name);
@@ -111238,10 +111947,10 @@ async function bundledProviderSkillNames(root2) {
111238
111947
  return names;
111239
111948
  }
111240
111949
  async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
111241
- const sourceRoot2 = join105(root2, "skills");
111950
+ const sourceRoot2 = join106(root2, "skills");
111242
111951
  for (const name3 of await bundledProviderSkillNames(root2)) {
111243
- const source2 = join105(sourceRoot2, name3);
111244
- const target = join105(targetRoot, name3);
111952
+ const source2 = join106(sourceRoot2, name3);
111953
+ const target = join106(targetRoot, name3);
111245
111954
  steps.push({
111246
111955
  agent,
111247
111956
  command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
@@ -111252,7 +111961,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
111252
111961
  }
111253
111962
  }
111254
111963
  async function installCursor(root2, dryRun, steps) {
111255
- const source2 = join105(root2, "cursor");
111964
+ const source2 = join106(root2, "cursor");
111256
111965
  const target = cursorPluginRoot();
111257
111966
  steps.push({
111258
111967
  agent: "cursor",
@@ -111307,12 +112016,12 @@ async function installCodex(root2, dryRun, steps) {
111307
112016
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
111308
112017
  steps.push({
111309
112018
  agent: "codex",
111310
- command: `ensure ${shellQuote8(join105(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
112019
+ command: `ensure ${shellQuote8(join106(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
111311
112020
  status: dryRun ? "planned" : "ran"
111312
112021
  });
111313
112022
  steps.push({
111314
112023
  agent: "codex",
111315
- command: `ensure ${shellQuote8(join105(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
112024
+ command: `ensure ${shellQuote8(join106(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
111316
112025
  status: dryRun ? "planned" : "ran"
111317
112026
  });
111318
112027
  if (dryRun) {
@@ -111367,13 +112076,13 @@ function pluginRootCandidates() {
111367
112076
  return [resolve40(envRoot)];
111368
112077
  const candidates = [];
111369
112078
  for (const dir of packageCandidateDirs()) {
111370
- candidates.push(join106(dir, "plugins"));
111371
- candidates.push(join106(dir, "dist", "plugins"));
112079
+ candidates.push(join107(dir, "plugins"));
112080
+ candidates.push(join107(dir, "dist", "plugins"));
111372
112081
  }
111373
112082
  return [...new Set(candidates)];
111374
112083
  }
111375
112084
  function isInstallablePluginRoot(root2) {
111376
- return existsSync35(join106(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join106(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join106(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join106(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join106(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join106(root2, "skills"));
112085
+ return existsSync35(join107(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join107(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join107(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join107(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join107(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join107(root2, "skills"));
111377
112086
  }
111378
112087
  function resolveBundledPluginsRoot() {
111379
112088
  const candidates = pluginRootCandidates();
@@ -111603,10 +112312,10 @@ function readQuickstartPath() {
111603
112312
  try {
111604
112313
  let dir = dirname47(fileURLToPath10(import.meta.url));
111605
112314
  for (let i2 = 0;i2 < 8; i2++) {
111606
- const candidate = join107(dir, "docs", "quickstart.md");
112315
+ const candidate = join108(dir, "docs", "quickstart.md");
111607
112316
  if (existsSync36(candidate))
111608
112317
  return candidate;
111609
- const pkg = join107(dir, "package.json");
112318
+ const pkg = join108(dir, "package.json");
111610
112319
  if (existsSync36(pkg))
111611
112320
  return candidate;
111612
112321
  const parent = dirname47(dir);
@@ -111615,7 +112324,7 @@ function readQuickstartPath() {
111615
112324
  dir = parent;
111616
112325
  }
111617
112326
  } catch {}
111618
- return join107(dirname47(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
112327
+ return join108(dirname47(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
111619
112328
  }
111620
112329
  var GREEN = "\x1B[32m";
111621
112330
  var RESET = "\x1B[0m";
@@ -111641,7 +112350,7 @@ ${greenBox([
111641
112350
  `;
111642
112351
  }
111643
112352
  function assertKnownTopLevelCommand(argv, program2) {
111644
- const commands = new Set(["help", ...program2.commands.flatMap((command2) => [command2.name(), ...command2.aliases()])]);
112353
+ const commands = new Set(["help", ...program2.commands.flatMap((command3) => [command3.name(), ...command3.aliases()])]);
111645
112354
  for (const token of argv.slice(2)) {
111646
112355
  if (token === "-h" || token === "--help" || token === "-V" || token === "--version")
111647
112356
  return;
@@ -111867,9 +112576,9 @@ async function cli_main(argv = process.argv) {
111867
112576
  await withContextRuntimeEventDelivery(async () => {
111868
112577
  const program2 = createCliProgram();
111869
112578
  assertKnownTopLevelCommand(argv, program2);
111870
- const overrideExit = (command2) => {
111871
- command2.exitOverride();
111872
- command2.commands.forEach(overrideExit);
112579
+ const overrideExit = (command3) => {
112580
+ command3.exitOverride();
112581
+ command3.commands.forEach(overrideExit);
111873
112582
  };
111874
112583
  overrideExit(program2);
111875
112584
  try {