@c4a/context-cli 0.7.10 → 0.7.12

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 (39) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +3 -3
  3. package/cli.js +1216 -450
  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 +29 -65
  22. package/providers/context/provider.yaml +1 -1
  23. package/providers/context/resources/manuals/guides/knowledge-updates.md +87 -3
  24. package/providers/context/resources/manuals/guides/package-outputs.md +39 -1
  25. package/providers/context/resources/manuals/guides/workspace-prepare.md +3 -0
  26. package/providers/context/resources/manuals/reference/project-api.md +21 -2
  27. package/providers/context/resources/procedures/knowledge-review.md +18 -2
  28. package/providers/context/resources/procedures/knowledge-updates.md +87 -3
  29. package/providers/context/resources/procedures/package-output.md +18 -0
  30. package/providers/context/resources/procedures/production-stage-files.md +21 -0
  31. package/providers/context/resources/procedures/repository-source-recovery.md +5 -3
  32. package/providers/context/resources/procedures/task-recovery.md +6 -0
  33. package/providers/context/resources/procedures/work-start-report.md +14 -7
  34. package/providers/context/resources/procedures/workspace-prepare.md +3 -0
  35. package/providers/context/resources/templates/work-start-report.md +11 -6
  36. package/providers/context/actions/inspect-repository-recovery.yaml +0 -6
  37. package/providers/context/actions/restore-repository-sources.yaml +0 -7
  38. package/providers/context/resources/dialogue/repository-source-recovery.md +0 -23
  39. 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) {
@@ -56101,7 +56219,9 @@ function projectPackageKnowledgeMarkdown(content3) {
56101
56219
  return content3;
56102
56220
  const body = content3.slice(match[0].length).replace(CONTEXT_METADATA_BLOCK_RE, "").replace(CONTEXT_SECTION_OPEN_RE, (opening) => {
56103
56221
  const key = /\bid="([a-zA-Z0-9_-]+)"/u.exec(opening)?.[1];
56104
- return key === undefined ? "" : `<a id="section-${encodeURIComponent(key)}"></a>
56222
+ return key === undefined ? "" : `
56223
+
56224
+ <a id="section-${encodeURIComponent(key)}"></a>
56105
56225
 
56106
56226
  `;
56107
56227
  }).replace(CONTEXT_SECTION_CLOSE_RE, `
@@ -63603,8 +63723,9 @@ function validateProductionStage(value) {
63603
63723
  throw new TypeError("An unavailable source requires an explicit gap and pending investigation");
63604
63724
  }
63605
63725
  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");
63726
+ const invalid = usage.scopes.filter((scope2) => !scopes.has(scope2));
63727
+ if (invalid.length)
63728
+ 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
63729
  }
63609
63730
  const visited = new Set;
63610
63731
  const visiting = new Set;
@@ -63624,7 +63745,9 @@ function validateProductionStage(value) {
63624
63745
  visited.add(task.id);
63625
63746
  }
63626
63747
  for (const task of stage.tasks) {
63627
- indexerKnowledgeCollectionSchema2.parse(task.path.split("/")[0]);
63748
+ if (!indexerKnowledgeCollectionSchema2.safeParse(task.path.split("/")[0]).success) {
63749
+ 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.`);
63750
+ }
63628
63751
  if (!isSafeKnowledgeTargetPath(task.path.split("/")[0], task.path))
63629
63752
  throw new TypeError(`Unsafe article target for ${task.id}`);
63630
63753
  if (task.input !== productionTaskInput(task))
@@ -63712,7 +63835,7 @@ var init_productionStage = __esm(() => {
63712
63835
  skills: exports_external.array(exports_external.object({ name, entry: name.optional() }).strict()).default([])
63713
63836
  }).strict();
63714
63837
  productionIndexerUsageSchema = exports_external.object({
63715
- scopes: exports_external.array(name).min(1),
63838
+ 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
63839
  skills: exports_external.array(name).min(1),
63717
63840
  purpose: name
63718
63841
  }).strict();
@@ -63748,6 +63871,20 @@ var init_productionStage = __esm(() => {
63748
63871
  });
63749
63872
 
63750
63873
  // src/project/productionStageStore.ts
63874
+ var exports_productionStageStore = {};
63875
+ __export(exports_productionStageStore, {
63876
+ writeProductionProjection: () => writeProductionProjection,
63877
+ saveProductionStage: () => saveProductionStage,
63878
+ readProductionStageSnapshot: () => readProductionStageSnapshot,
63879
+ readProductionStage: () => readProductionStage,
63880
+ readProductionCapabilities: () => readProductionCapabilities,
63881
+ productionStageDirectory: () => productionStageDirectory,
63882
+ productionSourceFile: () => productionSourceFile,
63883
+ productionPlanMarkdown: () => productionPlanMarkdown,
63884
+ prepareNextProductionStage: () => prepareNextProductionStage,
63885
+ materializeProductionStage: () => materializeProductionStage,
63886
+ PRODUCTION_STAGES_ROOT: () => PRODUCTION_STAGES_ROOT
63887
+ });
63751
63888
  import { constants as constants4 } from "node:fs";
63752
63889
  import { readFile as readFile21, access as access2, stat as stat5 } from "node:fs/promises";
63753
63890
  import { join as join20 } from "node:path";
@@ -64632,12 +64769,14 @@ Restore the authorized source and retry preparation.
64632
64769
  "",
64633
64770
  ...scopes.map((scope2) => `- ${scope2.scope}: ${join25(directory, productionSourceFile(scope2.scope))}`),
64634
64771
  "",
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.",
64772
+ "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
64773
  "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.",
64774
+ "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.",
64775
+ "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
64776
  ...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
64777
  "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
64778
  "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.",
64779
+ "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
64780
  "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
64781
  `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
64782
  ""
@@ -64677,9 +64816,9 @@ async function submitProductionPlan(input) {
64677
64816
  throw new TypeError("Pending investigation must name unique authorized stage scopes");
64678
64817
  }
64679
64818
  if (stage.gaps.some((gap) => !pendingScopes.includes(gap.scope)))
64680
- throw new TypeError("Keep unresolved material gaps in pending_scopes; declaring investigation complete does not resolve unavailable material");
64819
+ throw refreshRequired(stage.id, "Keep unresolved material gaps in pending_scopes; restore the source if unavailable, then prepare the current stage to refresh its material snapshot");
64681
64820
  if (plan.articles.some((article) => article.sources.some((scope2) => stage.gaps.some((gap) => gap.scope === scope2)))) {
64682
- throw new TypeError("An article requires unavailable material. Resolve that source gap before issuing it; independent source plans may proceed");
64821
+ throw refreshRequired(stage.id, "An article requires unavailable material in the captured stage. Restore the source if needed, then prepare the current stage; independent source plans may proceed");
64683
64822
  }
64684
64823
  for (const source2 of stage.scopes)
64685
64824
  if (!stage.gaps.some((gap) => gap.scope === source2.scope) && await productionSourceBaseline(input.projectRoot, source2.scope) !== source2.baseline) {
@@ -64784,7 +64923,7 @@ var init_productionPlanning = __esm(() => {
64784
64923
  stage: text5,
64785
64924
  capabilities: productionCapabilitiesSchema,
64786
64925
  articles: exports_external.array(exports_external.object({
64787
- path: text5,
64926
+ path: text5.describe("Relative to knowledge/, e.g. business/example.md; do not prefix knowledge/"),
64788
64927
  question: text5,
64789
64928
  sources: exports_external.array(text5).min(1),
64790
64929
  batch: text5,
@@ -64793,7 +64932,7 @@ var init_productionPlanning = __esm(() => {
64793
64932
  }).strict()),
64794
64933
  indexer_usage: exports_external.array(productionIndexerUsageSchema).default([]),
64795
64934
  replaces: exports_external.array(text5).default([]),
64796
- pending_scopes: exports_external.array(text5).optional()
64935
+ pending_scopes: exports_external.array(text5).describe("Exact authorized source refs from the current stage scopes; no prose or module descriptions. Omit on amendments to preserve remaining investigation.").optional()
64797
64936
  }).strict();
64798
64937
  });
64799
64938
 
@@ -66152,6 +66291,77 @@ var init_knowledgeAssetRepair = __esm(() => {
66152
66291
  init_assetSourceRegistry();
66153
66292
  });
66154
66293
 
66294
+ // src/project/reviewApplyIndexer.ts
66295
+ var exports_reviewApplyIndexer = {};
66296
+ __export(exports_reviewApplyIndexer, {
66297
+ renderApprovedIndexerMarkdown: () => renderApprovedIndexerMarkdown
66298
+ });
66299
+ function escapeHtmlAttribute(value) {
66300
+ return value.replace(/&/gu, "&amp;").replace(/"/gu, "&quot;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
66301
+ }
66302
+ function sectionMarkdown(section) {
66303
+ return [
66304
+ `<!-- context:section id="${escapeHtmlAttribute(section.section_key)}" -->`,
66305
+ "",
66306
+ section.markdown.trimEnd(),
66307
+ "",
66308
+ "<!-- /context:section -->"
66309
+ ].join(`
66310
+ `);
66311
+ }
66312
+ function renderApprovedIndexerMarkdown(input) {
66313
+ if (input.record.approved_revision !== undefined) {
66314
+ const content3 = compactApprovedKnowledgeMarkdown(ensureApprovedKnowledgePresentation(input.record.body));
66315
+ return content3.replace(/^---\r?\n([\s\S]*?)\r?\n---/u, (_match, header) => {
66316
+ const metadata = import_yaml25.default.parse(header);
66317
+ const reclassified = input.record.approved_revision?.previous_path !== undefined && input.record.approved_revision.previous_path.split("/")[0] !== input.record.collection;
66318
+ return ["---", import_yaml25.default.stringify({
66319
+ ...metadata,
66320
+ type: reclassified ? okfTypeForCollection(input.record.collection) : metadata.type ?? okfTypeForCollection(input.record.collection),
66321
+ timestamp: input.timestamp
66322
+ }).trimEnd(), "---"].join(`
66323
+ `);
66324
+ });
66325
+ }
66326
+ const binding = input.record.indexer_candidate;
66327
+ if (input.record.candidate_type !== "indexer-artifact" || binding === undefined) {
66328
+ throw new TypeError("Indexer approved renderer requires an indexer-artifact Candidate");
66329
+ }
66330
+ const title = input.record.review.title;
66331
+ const body = binding.sections.flatMap((section, index2) => [
66332
+ ...index2 === 0 ? [] : [""],
66333
+ sectionMarkdown(section)
66334
+ ]).join(`
66335
+ `);
66336
+ const description = readerKnowledgeDescription({
66337
+ description: input.record.review.summary,
66338
+ markdown: body,
66339
+ title
66340
+ });
66341
+ const frontmatter = import_yaml25.default.stringify({
66342
+ title,
66343
+ type: okfTypeForCollection(input.record.collection),
66344
+ description,
66345
+ timestamp: input.timestamp
66346
+ }).trimEnd();
66347
+ return [
66348
+ "---",
66349
+ frontmatter,
66350
+ "---",
66351
+ "",
66352
+ ensureMarkdownPageTitle(body, title),
66353
+ ""
66354
+ ].join(`
66355
+ `);
66356
+ }
66357
+ var import_yaml25;
66358
+ var init_reviewApplyIndexer = __esm(() => {
66359
+ init_okfTypes();
66360
+ init_packageKnowledgeProjection();
66361
+ init_approvedKnowledgeMetadata();
66362
+ import_yaml25 = __toESM(require_dist(), 1);
66363
+ });
66364
+
66155
66365
  // src/project/approvedRevisionBatch.ts
66156
66366
  var exports_approvedRevisionBatch = {};
66157
66367
  __export(exports_approvedRevisionBatch, {
@@ -66208,7 +66418,8 @@ async function approvedRevisionCandidateApplied(root, candidate, applied, closed
66208
66418
  return false;
66209
66419
  if (!closed && applied === candidate.body)
66210
66420
  return true;
66211
- const expected = revisionComparableMarkdown(candidate.body);
66421
+ const { renderApprovedIndexerMarkdown: renderApprovedIndexerMarkdown2 } = await Promise.resolve().then(() => (init_reviewApplyIndexer(), exports_reviewApplyIndexer));
66422
+ const expected = revisionComparableMarkdown(renderApprovedIndexerMarkdown2({ record: candidate, timestamp: candidate.updated }));
66212
66423
  const approved = revisionComparableMarkdown(applied);
66213
66424
  if (expected === approved)
66214
66425
  return true;
@@ -66224,9 +66435,9 @@ async function approvedRevisionCandidateApplied(root, candidate, applied, closed
66224
66435
  function revisionComparableMarkdown(markdown) {
66225
66436
  const compact = compactApprovedKnowledgeMarkdown(ensureApprovedKnowledgePresentation(markdown));
66226
66437
  return compact.replace(/^---\r?\n([\s\S]*?)\r?\n---/u, (_match, header) => {
66227
- const metadata = import_yaml25.default.parse(header);
66438
+ const metadata = import_yaml26.default.parse(header);
66228
66439
  const { timestamp: _timestamp, ...content3 } = metadata;
66229
- return ["---", import_yaml25.default.stringify(content3).trimEnd(), "---"].join(`
66440
+ return ["---", import_yaml26.default.stringify(content3).trimEnd(), "---"].join(`
66230
66441
  `);
66231
66442
  });
66232
66443
  }
@@ -66266,7 +66477,7 @@ async function observeApprovedRevisionBatch(root, request) {
66266
66477
  ...candidates.some((candidate) => candidate.status === "rejected") ? { revision_pending: true } : {}
66267
66478
  };
66268
66479
  }
66269
- var import_yaml25;
66480
+ var import_yaml26;
66270
66481
  var init_approvedRevisionBatch = __esm(() => {
66271
66482
  init_src2();
66272
66483
  init_approvedRevision();
@@ -66275,7 +66486,7 @@ var init_approvedRevisionBatch = __esm(() => {
66275
66486
  init_approvedKnowledgeMetadata();
66276
66487
  init_durableSingleFileTransaction();
66277
66488
  init_knowledgeAssetRepair();
66278
- import_yaml25 = __toESM(require_dist(), 1);
66489
+ import_yaml26 = __toESM(require_dist(), 1);
66279
66490
  });
66280
66491
 
66281
66492
  // src/project/verifyFrontmatter.ts
@@ -66291,7 +66502,7 @@ function isDeprecatedApprovedMarkdown(content3) {
66291
66502
  if (end < 0)
66292
66503
  return false;
66293
66504
  try {
66294
- const parsed = import_yaml26.default.parse(content3.slice(4, end));
66505
+ const parsed = import_yaml27.default.parse(content3.slice(4, end));
66295
66506
  return isRecord7(parsed) && parsed.deprecated === true;
66296
66507
  } catch {
66297
66508
  return false;
@@ -66310,7 +66521,7 @@ function parseFrontmatter3(content3, path2, issues) {
66310
66521
  return;
66311
66522
  }
66312
66523
  try {
66313
- const parsed = import_yaml26.default.parse(content3.slice(4, end));
66524
+ const parsed = import_yaml27.default.parse(content3.slice(4, end));
66314
66525
  if (!isRecord7(parsed)) {
66315
66526
  issues.push({ severity: "error", code: "frontmatter-invalid", path: path2, line: 1, message: "frontmatter must be a YAML object" });
66316
66527
  return;
@@ -66336,7 +66547,7 @@ function parseFrontmatterLoose(content3) {
66336
66547
  if (end < 0)
66337
66548
  return {};
66338
66549
  try {
66339
- const parsed = import_yaml26.default.parse(content3.slice(4, end));
66550
+ const parsed = import_yaml27.default.parse(content3.slice(4, end));
66340
66551
  return isRecord7(parsed) ? parsed : {};
66341
66552
  } catch {
66342
66553
  return {};
@@ -66406,10 +66617,10 @@ async function validateApprovedMarkdown(input) {
66406
66617
  });
66407
66618
  }
66408
66619
  }
66409
- var import_yaml26;
66620
+ var import_yaml27;
66410
66621
  var init_verifyFrontmatter = __esm(() => {
66411
66622
  init_okfTypes();
66412
- import_yaml26 = __toESM(require_dist(), 1);
66623
+ import_yaml27 = __toESM(require_dist(), 1);
66413
66624
  });
66414
66625
 
66415
66626
  // src/project/indexerTemplateSnapshots.ts
@@ -66827,7 +67038,7 @@ var init_indexerMainRunStore = __esm(() => {
66827
67038
  // src/project/productionDeliveryScope.ts
66828
67039
  import { readFile as readFile34 } from "node:fs/promises";
66829
67040
  import { join as join36, posix as posix2 } from "node:path";
66830
- async function productionDeliverableArticles(root) {
67041
+ async function productionDeliverableArticles(root, phase = "delivery") {
66831
67042
  return withProductionFeedback({ operation: "delivery-scope" }, async () => {
66832
67043
  const stage = await readProductionStage(root);
66833
67044
  if (!stage)
@@ -66850,6 +67061,8 @@ async function productionDeliverableArticles(root) {
66850
67061
  continue;
66851
67062
  selected.set(article.article_id, { path: article.path, article_id: article.article_id });
66852
67063
  }
67064
+ if (phase === "review")
67065
+ return [...selected.values()];
66853
67066
  for (const article of selected.values()) {
66854
67067
  const markdown = await readFile34(await safeProjectTarget(root, join36("knowledge", article.path)), "utf8");
66855
67068
  for (const link of markdownReaderLinks(markdown)) {
@@ -66948,6 +67161,9 @@ async function clearCompletedLifecycle(projectRoot) {
66948
67161
  if (production) {
66949
67162
  if (production.delivery)
66950
67163
  throw new TypeError("Partial delivery must retain the production stage and its unfinished tasks; finish the build or explicitly resume writing.");
67164
+ if (dispatchProductionStage(production, productionCapabilitiesSchema.parse({})).state !== "ended") {
67165
+ throw new TypeError("Production still has unfinished work; keep its files and follow context status --format json.");
67166
+ }
66951
67167
  const candidates = await readCandidateRecords(projectRoot);
66952
67168
  await assertRequiredArticlesReviewed(projectRoot, candidates);
66953
67169
  if (candidates.some((candidate) => candidate.status === "draft") || (await readProjectCloseStatus(projectRoot)).state !== "ready") {
@@ -66987,6 +67203,7 @@ async function clearCompletedLifecycle(projectRoot) {
66987
67203
  var COMPLETED_RUNTIME_PATHS;
66988
67204
  var init_lifecycleCleanup = __esm(() => {
66989
67205
  init_productionStageStore();
67206
+ init_productionStage();
66990
67207
  init_indexerRequiredArticleReview();
66991
67208
  init_candidateLedger();
66992
67209
  init_close();
@@ -67022,7 +67239,7 @@ async function requestProductionDelivery(root) {
67022
67239
  if (stage.delivery)
67023
67240
  return true;
67024
67241
  const candidates = await readCandidateRecords(root);
67025
- const formal = await productionDeliverableArticles(root);
67242
+ const formal = await productionDeliverableArticles(root, "review");
67026
67243
  const selected = stage.tasks.filter((task) => task.status === "accepted" && (candidates.some((candidate) => candidate.candidate_id === task.accepted?.receipt) || formal.some((article) => article.article_id === task.article_id && article.path === task.path)));
67027
67244
  if (!selected.length)
67028
67245
  throw new TypeError("No completed articles are available. Continue the current writing task before requesting delivery.");
@@ -67076,7 +67293,7 @@ var init_productionDelivery = __esm(() => {
67076
67293
 
67077
67294
  // src/project/indexerRequiredArticleReview.ts
67078
67295
  async function assertRequiredArticlesReviewed(root, candidates) {
67079
- if ((await readMaintenance(root)).active)
67296
+ if ((await readMaintenance(root)).active || await readApprovedRevision(root))
67080
67297
  return;
67081
67298
  const rejected = candidates.filter((candidate) => candidate.status === "rejected" && candidate.indexer_candidate);
67082
67299
  const production = await readProductionStage(root);
@@ -67147,6 +67364,7 @@ var init_indexerRequiredArticleReview = __esm(() => {
67147
67364
  init_productionSubmissionFiles();
67148
67365
  init_productionPlanning();
67149
67366
  init_maintenanceStorage();
67367
+ init_approvedRevision();
67150
67368
  });
67151
67369
 
67152
67370
  // src/project/partialDelivery.ts
@@ -67297,7 +67515,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67297
67515
  if (error.code !== "ENOENT")
67298
67516
  throw error;
67299
67517
  }
67300
- const structure = before === undefined ? {} : import_yaml27.default.parse(before);
67518
+ const structure = before === undefined ? {} : import_yaml28.default.parse(before);
67301
67519
  if (!structure || typeof structure !== "object" || Array.isArray(structure))
67302
67520
  throw new TypeError("Invalid knowledge structure");
67303
67521
  const articles = new Map(approvedKnowledgeSnapshotsFromStructure(structure).map((article) => [article.article_id, article]));
@@ -67321,7 +67539,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67321
67539
  articles.set(article.article_id, article);
67322
67540
  }
67323
67541
  const entries2 = validateArticleStructureEntries([...articles.values()]);
67324
- const content3 = import_yaml27.default.stringify({
67542
+ const content3 = import_yaml28.default.stringify({
67325
67543
  ...structure,
67326
67544
  articles: entries2.sort((a, b) => a.article_id.localeCompare(b.article_id))
67327
67545
  });
@@ -67335,12 +67553,12 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67335
67553
  content: content3
67336
67554
  };
67337
67555
  }
67338
- var import_yaml27, STRUCTURE_PATH2 = "knowledge/structure.yaml";
67556
+ var import_yaml28, STRUCTURE_PATH2 = "knowledge/structure.yaml";
67339
67557
  var init_approvedKnowledgeSnapshots = __esm(() => {
67340
67558
  init_src2();
67341
67559
  init_approvedKnowledgeMetadata();
67342
67560
  init_durableSingleFileTransaction();
67343
- import_yaml27 = __toESM(require_dist(), 1);
67561
+ import_yaml28 = __toESM(require_dist(), 1);
67344
67562
  });
67345
67563
 
67346
67564
  // src/runtimeEventOutbox.ts
@@ -69378,7 +69596,7 @@ function parseFrontmatter4(content3) {
69378
69596
  const match = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(content3);
69379
69597
  if (match?.[1] === undefined)
69380
69598
  return {};
69381
- const parsed = import_yaml28.default.parse(match[1]);
69599
+ const parsed = import_yaml29.default.parse(match[1]);
69382
69600
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
69383
69601
  }
69384
69602
  function isDeprecated(content3) {
@@ -69439,7 +69657,7 @@ async function writeApprovedStructureProjection(projectRoot) {
69439
69657
  const { inputHash, structure, compactFiles } = await deriveApprovedStructure(projectRoot);
69440
69658
  const outputPath = join48(projectRoot, STRUCTURE_PATH4);
69441
69659
  await mkdir17(dirname21(outputPath), { recursive: true });
69442
- await writeFile11(outputPath, import_yaml28.default.stringify(structure), "utf8");
69660
+ await writeFile11(outputPath, import_yaml29.default.stringify(structure), "utf8");
69443
69661
  await Promise.all(compactFiles.map((file) => writeFile11(file.absPath, file.content, "utf8")));
69444
69662
  return { inputHash, articles: structure.articles.length, structure: STRUCTURE_PATH4 };
69445
69663
  }
@@ -69507,7 +69725,7 @@ async function closeProjectWorkspace(projectRoot) {
69507
69725
  }
69508
69726
  const outputPath = join48(projectRoot, STRUCTURE_PATH4);
69509
69727
  await mkdir17(dirname21(outputPath), { recursive: true });
69510
- await writeFile11(outputPath, `${import_yaml28.default.stringify(structure)}`, "utf8");
69728
+ await writeFile11(outputPath, `${import_yaml29.default.stringify(structure)}`, "utf8");
69511
69729
  await Promise.all(compactFiles.map((file) => writeFile11(file.absPath, file.content, "utf8")));
69512
69730
  const { readTaskRollback } = await Promise.resolve().then(() => (init_taskRollback(), exports_taskRollback));
69513
69731
  if (!production && !await readTaskRollback(projectRoot))
@@ -69558,7 +69776,7 @@ async function runProjectCloseCommand(input) {
69558
69776
  }
69559
69777
  return true;
69560
69778
  }
69561
- var import_yaml28, KNOWLEDGE_ROOT = "knowledge", STRUCTURE_PATH4, STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
69779
+ var import_yaml29, KNOWLEDGE_ROOT = "knowledge", STRUCTURE_PATH4, STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
69562
69780
  var init_close = __esm(() => {
69563
69781
  init_indexerRequiredArticleReview();
69564
69782
  init_approvedFileRead();
@@ -69579,7 +69797,7 @@ var init_close = __esm(() => {
69579
69797
  init_candidateLedger();
69580
69798
  init_knowledgeAssetRepair();
69581
69799
  init_approvedKnowledgeMetadata();
69582
- import_yaml28 = __toESM(require_dist(), 1);
69800
+ import_yaml29 = __toESM(require_dist(), 1);
69583
69801
  STRUCTURE_PATH4 = join48(KNOWLEDGE_ROOT, "structure.yaml");
69584
69802
  });
69585
69803
 
@@ -69843,7 +70061,7 @@ async function optionalText(root, path2) {
69843
70061
  }
69844
70062
  async function readKnowledgeMap(root) {
69845
70063
  const content3 = await optionalText(root, KNOWLEDGE_MAP_PATH);
69846
- return content3 === undefined ? undefined : validateKnowledgeMap(import_yaml29.parse(content3));
70064
+ return content3 === undefined ? undefined : validateKnowledgeMap(import_yaml30.parse(content3));
69847
70065
  }
69848
70066
  async function applyKnowledgeMapUpdate(projectRoot, update) {
69849
70067
  return withProjectWriteLock(projectRoot, "adjust-knowledge-map", async () => {
@@ -69855,7 +70073,7 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
69855
70073
  const preview = previewText === undefined ? undefined : JSON.parse(previewText);
69856
70074
  const planned = preview?.topics?.flatMap((topic) => topic.article_targets ?? []) ?? [];
69857
70075
  assertKnowledgeMapCoverage(next, approved, { known: [...approved, ...planned], current_revision: current?.revision ?? null });
69858
- const content3 = import_yaml29.stringify(next);
70076
+ const content3 = import_yaml30.stringify(next);
69859
70077
  const previous2 = await optionalText(projectRoot, KNOWLEDGE_MAP_PATH);
69860
70078
  await runDurableMultiFileTransaction({
69861
70079
  projectRoot,
@@ -69876,14 +70094,14 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
69876
70094
  };
69877
70095
  });
69878
70096
  }
69879
- var import_yaml29, KNOWLEDGE_MAP_PATH = "src/knowledge-map.yaml";
70097
+ var import_yaml30, KNOWLEDGE_MAP_PATH = "src/knowledge-map.yaml";
69880
70098
  var init_knowledgeMap2 = __esm(() => {
69881
70099
  init_knowledgeMapCoverage();
69882
70100
  init_src2();
69883
70101
  init_durableSingleFileTransaction();
69884
70102
  init_durableMultiFileTransaction();
69885
70103
  init_writeLock();
69886
- import_yaml29 = __toESM(require_dist(), 1);
70104
+ import_yaml30 = __toESM(require_dist(), 1);
69887
70105
  });
69888
70106
 
69889
70107
  // src/project/packageKnowledgeMap.ts
@@ -70157,7 +70375,7 @@ async function optionalWorkspaceText(root, path2) {
70157
70375
  }
70158
70376
  async function readWorkspaceChangelog(root) {
70159
70377
  const value = await optionalWorkspaceText(root, "changelog.yaml");
70160
- return value === undefined ? [] : ledgerSchema.parse(import_yaml30.parse(value)).entries;
70378
+ return value === undefined ? [] : ledgerSchema.parse(import_yaml31.parse(value)).entries;
70161
70379
  }
70162
70380
  async function workspaceVersion(root) {
70163
70381
  const manifest = JSON.parse(await readFile45(join55(root, "package.json"), "utf8"));
@@ -70299,7 +70517,7 @@ async function recordWorkspaceVersion(root, value) {
70299
70517
  const writes = {
70300
70518
  "package.json": JSON.stringify(manifest, null, 2) + `
70301
70519
  `,
70302
- "changelog.yaml": import_yaml30.stringify({ entries: entries2 }),
70520
+ "changelog.yaml": import_yaml31.stringify({ entries: entries2 }),
70303
70521
  "CHANGELOG.md": renderChangelog(entries2),
70304
70522
  ".context-version.json": JSON.stringify({ version: entry.version, files: status.files }) + `
70305
70523
  `
@@ -70313,13 +70531,13 @@ async function recordWorkspaceVersion(root, value) {
70313
70531
  return { version: entry.version, next_action: { command: "context status --format json" } };
70314
70532
  });
70315
70533
  }
70316
- var import_yaml30, exec, semver, text6, changelogEntrySchema, changelogInputSchema, ledgerSchema, baselineSchema, hash2 = (value) => createHash15("sha256").update(JSON.stringify(value)).digest("hex");
70534
+ var import_yaml31, exec, semver, text6, changelogEntrySchema, changelogInputSchema, ledgerSchema, baselineSchema, hash2 = (value) => createHash15("sha256").update(JSON.stringify(value)).digest("hex");
70317
70535
  var init_workspaceChangelog = __esm(() => {
70318
70536
  init_zod();
70319
70537
  init_writeLock();
70320
70538
  init_durableSingleFileTransaction();
70321
70539
  init_durableMultiFileTransaction();
70322
- import_yaml30 = __toESM(require_dist(), 1);
70540
+ import_yaml31 = __toESM(require_dist(), 1);
70323
70541
  exec = promisify6(execFile6);
70324
70542
  semver = exports_external.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u);
70325
70543
  text6 = exports_external.string().trim().min(1);
@@ -70452,17 +70670,22 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70452
70670
  }
70453
70671
  .VPNavBar .wrapper { padding: 0 24px !important; }
70454
70672
  .VPNavBar .container { max-width: none !important; }
70673
+ .VPNav, .VPNavBar, .VPNavBar .wrapper { background: var(--vp-c-bg) !important; }
70455
70674
  .VPNavBar .title { position: static !important; padding: 0 !important; width: var(--vp-sidebar-width) !important; flex-shrink: 0; }
70456
70675
  .VPNavBarTitle .title { font-size: 15px; font-weight: 650; border: 0 !important; }
70457
70676
  .VPNavBar .content { flex: 1; min-width: 0; padding-left: 0 !important; }
70458
70677
  .VPNavBar .content-body { background: var(--vp-c-bg) !important; gap: 8px; }
70459
70678
  .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; }
70679
+ .context-language { display: inline-flex; align-items: center; padding: 5px 7px; border: 0; border-radius: 6px; color: var(--vp-c-text-2);
70680
+ background: transparent; white-space: nowrap; font-size: 12px; font-weight: 550; cursor: pointer; }
70681
+ .context-language:hover { color: var(--vp-c-brand-1); background: var(--vp-c-brand-soft); }
70463
70682
  .VPNavBarMenuLink { font-size: 13px !important; font-weight: 550 !important; padding: 0 16px !important; }
70464
70683
  .VPNavBarMenuLink.active { box-shadow: inset 0 -2px var(--vp-c-brand-1); }
70465
- .VPNavBarSearch { flex-grow: 0 !important; padding: 0 12px !important; }
70684
+ .VPNavBarSearch { flex: 0 0 376px !important; width: 376px; padding: 0 12px !important; }
70685
+ .VPNavBarSearch #local-search, .VPNavBarSearch .DocSearch-Button { width: 352px; }
70686
+ .VPNavBarSearch .DocSearch-Button { display: flex; align-items: center; }
70687
+ .VPNavBarSearch .DocSearch-Button-Container { display: flex; flex: 1; min-width: 0; align-items: center; }
70688
+ .VPNavBarSearch .DocSearch-Button-Keys { margin-left: auto; }
70466
70689
  .VPSidebar { border-top: 1px solid var(--vp-c-divider); border-right: 1px solid var(--vp-c-divider); scrollbar-width: thin; }
70467
70690
  .VPSidebar .group + .group { border: 0; padding-top: 8px; }
70468
70691
  .VPSidebarItem .link { min-width: 0; overflow: hidden; }
@@ -70508,16 +70731,84 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70508
70731
  .vp-doc details { margin: 20px 0; border: 1px solid var(--vp-c-divider); border-radius: 6px; padding: 12px 16px; }
70509
70732
  .vp-doc summary { cursor: pointer; font-size: 14px; font-weight: 550; }
70510
70733
  .vp-doc img { max-width: 100%; height: auto; }
70734
+ .context-home { max-width: 100%; min-width: 0; overflow-x: clip; }
70735
+ .context-home .VPContent, .context-home .VPHome, .context-home .VPHero { max-width: 100%; min-width: 0; }
70736
+ .context-home .VPHome { padding-bottom: 0; }
70737
+ .context-home .VPHero { position: relative; padding: 132px 0 62px; }
70738
+ .context-home .VPHero::before { content: ''; position: absolute; top: -1px; right: 0; bottom: 0; left: calc(0px - var(--vp-sidebar-width)); pointer-events: none;
70739
+ background: linear-gradient(to bottom, transparent 58%, var(--vp-c-bg) 100%),
70740
+ radial-gradient(ellipse 58% 145% at 8% 18%, rgba(37,99,235,.16), transparent 72%),
70741
+ radial-gradient(ellipse 58% 150% at 68% 24%, rgba(0,190,200,.11), transparent 72%),
70742
+ linear-gradient(90deg, rgba(37,99,235,.045), rgba(0,190,200,.025) 68%, transparent); }
70743
+ .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; }
70744
+ .context-home .VPHero .main { width: 100%; max-width: 980px; min-width: 0; }
70745
+ .context-home .VPHero .heading { display: block; width: 100%; min-width: 0; max-width: 100%; }
70746
+ .context-home .VPHero .name { display: block; width: 100%; max-width: 100%; overflow-wrap: anywhere; white-space: normal; color: transparent;
70747
+ background: linear-gradient(112deg, var(--vp-c-brand-1), var(--context-accent)); background-clip: text; -webkit-background-clip: text; }
70748
+ .context-home .VPHero .text { display: block; width: 100%; max-width: 100%; overflow-wrap: anywhere; word-break: break-word; white-space: normal;
70749
+ font-size: clamp(38px, 4.2vw, 60px); line-height: 1.08; letter-spacing: -.045em; }
70750
+ .context-home .VPHero .tagline { max-width: 820px; font-size: 18px; line-height: 1.75; }
70751
+ .context-home .VPHero .actions { width: 100%; min-width: 0; padding-top: 38px; flex-wrap: wrap; }
70752
+ .context-home .VPFeatures { display: none; }
70753
+ .context-home-section { width: min(1180px, calc(100% - 104px)); margin: 0 auto 0 52px; padding: 36px 0 44px; }
70754
+ .context-home-section + .context-home-section { border-top: 1px solid var(--vp-c-divider); }
70755
+ .context-home-map { padding-top: 0; }
70756
+ .context-home-resources { padding-top: 6px; border-top: 0 !important; }
70757
+ .context-home-section-heading { max-width: 700px; margin-bottom: 24px; }
70758
+ .context-home-section-heading h2 { margin: 2px 0 8px; border: 0; font-size: 28px; line-height: 1.3; letter-spacing: -.02em; }
70759
+ .context-home-section-heading > p:last-child { color: var(--vp-c-text-2); line-height: 1.7; }
70760
+ .context-home-kicker { margin: 0; color: var(--vp-c-brand-1); font-size: 11px; font-weight: 700; letter-spacing: .16em; }
70761
+ .context-home-map-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); gap: 14px; }
70762
+ .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));
70763
+ animation: context-home-rise .5s both; animation-delay: var(--context-home-delay); }
70764
+ .context-home-map-card { min-height: 224px; padding: 22px; border-radius: 14px; }
70765
+ .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));
70766
+ box-shadow: 0 14px 38px rgba(23,36,66,.08); transform: translateY(-2px); transition: border-color .18s, box-shadow .18s, transform .18s; }
70767
+ .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); }
70768
+ .context-home-map-card h3, .context-home-resource-card h3 { margin: 0; font-size: 17px; line-height: 1.45; }
70769
+ .context-home-map-card h3 a { color: var(--vp-c-text-1); }
70770
+ .context-home-map-card-heading span { flex: none; color: var(--vp-c-text-2); font-size: 11px; }
70771
+ .context-home-map-card ul { margin: 14px 0 0; padding: 0; list-style: none; }
70772
+ .context-home-map-card li { margin: 7px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
70773
+ .context-home-map-card li a { color: var(--vp-c-text-2); font-size: 13px; }
70774
+ .context-home-map-card li a:hover, .context-home-map-more:hover { color: var(--vp-c-brand-1); }
70775
+ .context-home-map-more { display: inline-block; margin-top: 12px; color: var(--vp-c-brand-1); font-size: 12px; font-weight: 600; }
70776
+ .context-home-resource-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
70777
+ .context-home-resource-card { min-height: 118px; padding: 16px 18px; border-radius: 12px; }
70778
+ .context-home-resource-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
70779
+ .context-home-resource-actions { display: flex; flex: none; align-items: center; gap: 6px; }
70780
+ .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;
70781
+ color: var(--vp-c-text-2); background: var(--vp-c-bg); font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap; }
70782
+ .context-home-resource-action:hover, .context-home-install-action:hover { border-color: var(--vp-c-brand-1); color: var(--vp-c-brand-1); }
70783
+ .context-home-install-action { cursor: pointer; background: var(--vp-c-brand-soft); }
70784
+ .context-home-resource-card p { margin: 8px 0 0; color: var(--vp-c-text-2); font-size: 13px; line-height: 1.55; }
70785
+ .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);
70786
+ color: var(--vp-c-text-2); font-size: 11px; text-align: right; }
70787
+ .context-home-powered a { color: inherit; }
70788
+ @keyframes context-home-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
70511
70789
  @media (min-width: 960px) {
70512
70790
  .VPSidebar { top: var(--vp-nav-height) !important; width: var(--vp-sidebar-width) !important; padding: 12px 0 48px !important; }
70513
70791
  .VPSidebar .curtain { display: none; }
70514
70792
  .VPContent.has-sidebar { padding-left: var(--vp-sidebar-width) !important; padding-right: 0 !important; }
70515
70793
  .context-empty-sidebar .VPContent { padding-left: var(--vp-sidebar-width) !important; padding-right: 0 !important; }
70794
+ .context-home .VPContent { padding-left: var(--vp-sidebar-width) !important; padding-right: 0 !important; }
70516
70795
  .VPNavBar .content { padding-right: 32px !important; }
70517
70796
  .VPDoc { padding: 44px 36px 80px !important; }
70518
70797
  .VPDoc > .container > .content { padding: 0 24px 80px 0 !important; }
70519
70798
  }
70520
70799
  @media (min-width: 1600px) { .VPDoc { padding-left: 52px !important; padding-right: 36px !important; } }
70800
+ @media (min-width: 960px) and (max-width: 1279px) {
70801
+ .VPNavBar .title { width: 220px !important; }
70802
+ .VPNavBarMenuLink { padding: 0 9px !important; }
70803
+ .VPNavBarSearch { flex-basis: 168px !important; width: 168px; }
70804
+ .VPNavBarSearch .DocSearch-Button { width: 144px; }
70805
+ .context-home .VPHero .main { max-width: 100%; }
70806
+ .context-home-resource-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
70807
+ }
70808
+ @media (min-width: 1280px) and (max-width: 1599px) {
70809
+ .VPNavBarSearch { flex-basis: 248px !important; width: 248px; }
70810
+ .VPNavBarSearch #local-search, .VPNavBarSearch .DocSearch-Button { width: 224px; }
70811
+ }
70521
70812
  .context-mobile-directory { display: none; }
70522
70813
  @media (max-width: 959px) {
70523
70814
  .VPNavBar .wrapper { padding: 0 16px !important; }
@@ -70541,6 +70832,25 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70541
70832
  .vp-doc h2 { font-size: 22px; }
70542
70833
  .VPDoc { padding: 32px 36px 64px !important; }
70543
70834
  .vp-doc a.header-anchor { margin-left: -0.8em; }
70835
+ .context-home .VPHero { padding-top: 104px; padding-bottom: 66px; }
70836
+ .context-home .VPHero::before { left: 0; }
70837
+ .context-home .VPHero .container { width: min(calc(100% - 36px), 680px); margin-left: auto; margin-right: auto; }
70838
+ .context-home .VPHero .text { font-size: 40px; }
70839
+ .context-home .VPHero .tagline { font-size: 16px; }
70840
+ .context-home-section, .context-home-powered { width: min(calc(100% - 36px), 680px); margin-left: auto; margin-right: auto; }
70841
+ .context-home-resource-grid { grid-template-columns: 1fr; }
70842
+ }
70843
+ @media (max-width: 959px) {
70844
+ .VPNavBarMenu { display: none !important; }
70845
+ .VPNavBarHamburger { display: flex !important; }
70846
+ .VPNavScreen { display: block !important; }
70847
+ .VPNavBarSearch { flex: 0 0 48px !important; width: 48px; padding: 0 4px !important; }
70848
+ .VPNavBarSearch #local-search, .VPNavBarSearch .DocSearch-Button { width: 40px; }
70849
+ .VPNavBarSearch .DocSearch-Button-Placeholder, .VPNavBarSearch .DocSearch-Button-Keys { display: none !important; }
70850
+ }
70851
+ @media (prefers-reduced-motion: reduce) {
70852
+ .context-home-map-card, .context-home-resource-card { animation: none; }
70853
+ .context-home-map-card:hover, .context-home-resource-card:hover { transform: none; }
70544
70854
  }
70545
70855
  .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
70856
  .context-sources-header { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px 16px; margin-bottom: 8px; }
@@ -70553,7 +70863,7 @@ var siteMarkdownConfig, siteThemeScript, siteThemeCss = `
70553
70863
  .context-sources a { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
70554
70864
  .context-sources a:hover { color: var(--vp-c-brand-1); border-color: currentColor; }
70555
70865
  .context-diagram { overflow: auto; padding: 20px; background: var(--vp-c-bg); }
70556
- .context-diagram svg { max-width: none !important; }
70866
+ .context-diagram svg { height: auto; }
70557
70867
  .context-diagram .node rect, .context-diagram .node polygon, .context-diagram .node circle,
70558
70868
  .context-diagram .flowchart-link { stroke-width: 1px !important; }
70559
70869
  .context-rendered:not(.context-show-source) pre, .context-rendered:not(.context-show-source) > .copy,
@@ -70610,7 +70920,7 @@ var init_packageSiteTheme = __esm(() => {
70610
70920
  if (!silent) { const token = state.push('context_anchor', '', 0); token.content = match[1]; }
70611
70921
  state.line = line + 1;
70612
70922
  return true;
70613
- });
70923
+ }, { alt: ['paragraph'] });
70614
70924
  md.renderer.rules.context_anchor = (tokens, index) => '<a id="' + md.utils.escapeHtml(tokens[index].content) + '"></a>\n';
70615
70925
  }
70616
70926
  `;
@@ -70626,9 +70936,12 @@ export default {
70626
70936
  const data = useData();
70627
70937
  const route = useRoute();
70628
70938
  const sections = computed(() => data.theme.value.contextSections || []);
70939
+ const home = computed(() => data.theme.value.contextHome || {});
70629
70940
  const selected = ref('');
70630
70941
  const mounted = ref(false);
70631
70942
  const language = ref('zh');
70943
+ const copiedCommand = ref('');
70944
+ let copyReset;
70632
70945
  const chinese = computed(() => language.value === 'zh');
70633
70946
  const languageKey = 'context-language:' + data.site.value.base;
70634
70947
  onMounted(() => {
@@ -70641,6 +70954,76 @@ export default {
70641
70954
  language.value = value;
70642
70955
  try { localStorage.setItem(languageKey, value); } catch {}
70643
70956
  };
70957
+ const href = value => value.startsWith('/') ? data.site.value.base + value.slice(1) : value;
70958
+ const external = value => /^https?:\/\//.test(value) || value.startsWith('mailto:');
70959
+ const copyCommand = async value => {
70960
+ try {
70961
+ await navigator.clipboard.writeText(value);
70962
+ copiedCommand.value = value;
70963
+ clearTimeout(copyReset);
70964
+ copyReset = setTimeout(() => { if (copiedCommand.value === value) copiedCommand.value = ''; }, 1600);
70965
+ } catch {}
70966
+ };
70967
+ const links = items => items.flatMap(item => [
70968
+ ...(item.link ? [{ text: item.text, link: item.link }] : []),
70969
+ ...links(item.items || []),
70970
+ ]);
70971
+ const siteMap = () => h('section', { class: 'context-home-section context-home-map', 'aria-labelledby': 'context-home-map-title' }, [
70972
+ h('div', { class: 'context-home-section-heading' }, [
70973
+ h('p', { class: 'context-home-kicker' }, chinese.value ? 'KNOWLEDGE MAP' : 'KNOWLEDGE MAP'),
70974
+ h('h2', { id: 'context-home-map-title' }, chinese.value ? '网站地图' : 'Site map'),
70975
+ h('p', chinese.value ? '从主题进入知识,也可以继续查看栏目中的具体页面。' :
70976
+ 'Start with a topic, then continue to the pages within each section.'),
70977
+ ]),
70978
+ h('div', { class: 'context-home-map-grid' }, sections.value.map((section, index) => {
70979
+ const pages = links(section.items || []);
70980
+ return h('article', { class: 'context-home-map-card', style: { '--context-home-delay': (index * 35) + 'ms' } }, [
70981
+ h('div', { class: 'context-home-map-card-heading' }, [
70982
+ h('h3', h('a', { href: href(section.href) }, section.title)),
70983
+ h('span', chinese.value ? section.pages.length + ' 页' : section.pages.length + ' pages'),
70984
+ ]),
70985
+ pages.length ? h('ul', pages.slice(0, 6).map(page => h('li',
70986
+ h('a', { href: href(page.link) }, page.text)))) : null,
70987
+ pages.length > 6 ? h('a', { class: 'context-home-map-more', href: href(section.href) },
70988
+ chinese.value ? '查看全部 ' + pages.length + ' 页 →' : 'View all ' + pages.length + ' pages →') : null,
70989
+ ]);
70990
+ })),
70991
+ ]);
70992
+ const resources = () => {
70993
+ const builtins = [
70994
+ { title: 'LLM Docs', description: chinese.value ? '面向 Agent 和模型的结构化知识入口。' :
70995
+ 'Structured knowledge entry points for agents and models.', href: '/llms/index.html', action: chinese.value ? '打开文档' : 'Open docs' },
70996
+ { title: 'Changelog', description: chinese.value ? '查看知识内容的版本变化与更新时间。' :
70997
+ 'Review knowledge versions and update history.', href: '/changelog.html', action: chinese.value ? '查看更新' : 'View updates' },
70998
+ ];
70999
+ const items = [...(home.value.resources || []), ...builtins];
71000
+ return h('section', { class: 'context-home-section context-home-resources', 'aria-labelledby': 'context-home-resources-title' }, [
71001
+ h('div', { class: 'context-home-section-heading' }, [
71002
+ h('p', { class: 'context-home-kicker' }, chinese.value ? 'RESOURCES' : 'RESOURCES'),
71003
+ h('h2', { id: 'context-home-resources-title' }, chinese.value ? '工具与资源' : 'Tools and resources'),
71004
+ ]),
71005
+ h('div', { class: 'context-home-resource-grid' }, items.map((item, index) => h('article', {
71006
+ class: 'context-home-resource-card', style: { '--context-home-delay': (index * 35) + 'ms' },
71007
+ }, [
71008
+ h('div', { class: 'context-home-resource-heading' }, [
71009
+ h('h3', item.title),
71010
+ h('div', { class: 'context-home-resource-actions' }, [
71011
+ item.command ? h('button', { class: 'context-home-install-action', type: 'button',
71012
+ title: (chinese.value ? '复制安装命令:' : 'Copy install command: ') + item.command,
71013
+ onClick: () => copyCommand(item.command) }, copiedCommand.value === item.command
71014
+ ? (chinese.value ? '已复制' : 'Copied') : (chinese.value ? '安装' : 'Install')) : null,
71015
+ item.href ? h('a', { class: 'context-home-resource-action', href: href(item.href), ...(external(item.href)
71016
+ ? { target: '_blank', rel: 'noopener noreferrer' } : {}) }, item.action || (chinese.value ? '访问' : 'Open')) : null,
71017
+ ]),
71018
+ ]),
71019
+ item.description ? h('p', item.description) : null,
71020
+ ]))),
71021
+ ]);
71022
+ };
71023
+ const poweredBy = () => home.value.branding ? h('footer', { class: 'context-home-powered' }, [
71024
+ home.value.branding.label + ' ',
71025
+ h('a', { href: home.value.branding.href, target: '_blank', rel: 'noopener noreferrer' }, home.value.branding.name),
71026
+ ]) : null;
70644
71027
  const history = computed(() => data.frontmatter.value.contextHistory
70645
71028
  ? JSON.parse(new TextDecoder().decode(Uint8Array.from(atob(data.frontmatter.value.contextHistory), char => char.charCodeAt(0)))) : null);
70646
71029
  onMounted(() => { mounted.value = true; });
@@ -70667,6 +71050,7 @@ export default {
70667
71050
  const active = computed(() => sections.value.find(section => section.key === selected.value));
70668
71051
  const inLlms = computed(() => route.path.startsWith(data.site.value.base + 'llms/'));
70669
71052
  const inHistory = computed(() => route.path === data.site.value.base + 'changelog.html');
71053
+ const inHome = computed(() => data.frontmatter.value.layout === 'home');
70670
71054
  provide(dataSymbol, { ...data, theme: computed(() => ({ ...data.theme.value,
70671
71055
  ...data.theme.value.contextUiLabels?.[language.value],
70672
71056
  sidebar: inLlms.value || inHistory.value ? [] : active.value?.items || [],
@@ -70678,9 +71062,12 @@ export default {
70678
71062
  activeMatch: inLlms.value || inHistory.value ? '^' : '(?!)' }],
70679
71063
  })) });
70680
71064
  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'))),
71065
+ 'nav-bar-content-after': () => h('button', { class: 'context-language', type: 'button',
71066
+ 'aria-label': chinese.value ? 'Switch interface language to English' : '将界面语言切换为中文',
71067
+ title: chinese.value ? 'Switch to English' : '切换为中文',
71068
+ onClick: () => changeLanguage(chinese.value ? 'en' : 'zh') }, chinese.value ? 'EN' : '中文'),
71069
+ 'home-features-before': () => [siteMap(), resources()],
71070
+ 'home-features-after': poweredBy,
70684
71071
  'doc-after': () => history.value ? h('section', { class: 'context-history-cards' },
70685
71072
  history.value.length ? history.value.map((entry, index) =>
70686
71073
  h('details', { class: 'context-history-card', open: index < 3, key: entry.version }, [
@@ -70729,7 +71116,8 @@ export default {
70729
71116
  },
70730
71117
  };
70731
71118
  // 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,
71119
+ return () => h(DefaultTheme.Layout, { class: inHome.value ? 'context-home' :
71120
+ inLlms.value || inHistory.value ? 'context-empty-sidebar' : undefined }, { ...slots, 'doc-after': undefined,
70733
71121
  'doc-footer-before': () => [slots['doc-after'](), slots['doc-footer-before']()] });
70734
71122
  }
70735
71123
  },
@@ -70789,10 +71177,20 @@ export default {
70789
71177
  `;
70790
71178
  });
70791
71179
 
71180
+ // src/project/packageSiteBranding.ts
71181
+ var packageSiteBranding;
71182
+ var init_packageSiteBranding = __esm(() => {
71183
+ packageSiteBranding = {
71184
+ label: "Powered by",
71185
+ name: "context4ai/context",
71186
+ href: "https://github.com/context4ai/context"
71187
+ };
71188
+ });
71189
+
70792
71190
  // src/project/packageSite.ts
70793
71191
  import { createHash as createHash16 } from "node:crypto";
70794
71192
  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";
71193
+ 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
71194
  import { createRequire as createRequire5 } from "node:module";
70797
71195
  import { dirname as dirname23, join as join56, posix as posix6 } from "node:path";
70798
71196
  function sitePagePath(identity) {
@@ -70986,6 +71384,7 @@ async function writePackageSite(input) {
70986
71384
  contextUpdated: historyDate,
70987
71385
  contextUiLabels: { zh: siteThemeLabels("zh"), en: siteThemeLabels("en") },
70988
71386
  contextSections: sections.map(({ key, title, href, pages, items }) => ({ key, title, href, pages, items })),
71387
+ contextHome: { resources: options.home?.resources ?? [], branding: packageSiteBranding },
70989
71388
  sidebar: sections[0]?.items ?? [],
70990
71389
  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
71390
  }
@@ -71022,11 +71421,24 @@ ${body}`);
71022
71421
  `) + `
71023
71422
  `);
71024
71423
  }
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
- `) + `
71424
+ const chinese = (options.lang ?? "en-US").startsWith("zh");
71425
+ const firstSection = sections[0]?.href ?? "/llms/index.html";
71426
+ const featuredResources = (options.home?.resources ?? []).filter((resource) => resource.featured && resource.href);
71427
+ const hero = {
71428
+ name: options.home?.title ?? options.title ?? pkg.name,
71429
+ text: options.home?.slogan ?? (chinese ? "从知识地图开始探索" : "Explore from the knowledge map"),
71430
+ tagline: options.home?.description ?? options.description ?? "",
71431
+ actions: options.home?.actions ?? [
71432
+ { theme: "brand", text: chinese ? "浏览知识" : "Browse knowledge", link: firstSection },
71433
+ ...featuredResources.map((resource) => ({ theme: "alt", text: resource.title, link: resource.href })),
71434
+ { theme: "alt", text: "LLM Docs", link: "/llms/index.html" }
71435
+ ]
71436
+ };
71437
+ await writeFile14(join56(temporary, "index.md"), `---
71438
+ layout: home
71439
+ title: ${JSON.stringify(options.home?.title ?? options.title ?? pkg.name)}
71440
+ hero: ${JSON.stringify(hero)}
71441
+ ---
71030
71442
  `);
71031
71443
  await writeFile14(join56(temporary, "changelog.md"), `---
71032
71444
  title: Changelog
@@ -71068,6 +71480,15 @@ title: LLM Docs
71068
71480
  await cp(join56(root, path2), destination);
71069
71481
  }
71070
71482
  await compileSite(temporary, output);
71483
+ for (const file of await walkPackageFiles(output)) {
71484
+ const extension2 = posix6.extname(file.relPath).toLowerCase();
71485
+ const placeholder = [".css", ".js", ".mjs", ".cjs"].includes(extension2) ? `/* Intentionally empty. */
71486
+ ` : [".html", ".htm"].includes(extension2) ? `<!-- Intentionally empty. -->
71487
+ ` : null;
71488
+ if (placeholder !== null && (await stat7(file.absPath)).size === 0) {
71489
+ await writeFile14(file.absPath, placeholder);
71490
+ }
71491
+ }
71071
71492
  await writeFile14(join56(output, "context-site-map.json"), JSON.stringify({
71072
71493
  protocol: "context.site-output/v1",
71073
71494
  knowledge_map_revision: structure?.revision ?? null,
@@ -71084,7 +71505,7 @@ title: LLM Docs
71084
71505
  await rm11(temporary, { recursive: true, force: true });
71085
71506
  }
71086
71507
  }
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, " ");
71508
+ var PACKAGE_SITE_VERSION = "vitepress-site-v42-section-anchor-blocks", require2, encodePath = (path2) => path2.split("/").map(encodeURIComponent).join("/"), mdLabel = (value) => value.replace(/[\\[\]<>`*]/gu, "\\$&").replace(/[\r\n]/gu, " ");
71088
71509
  var init_packageSite2 = __esm(() => {
71089
71510
  init_packageOutputPaths();
71090
71511
  init_workspaceChangelog();
@@ -71096,6 +71517,7 @@ var init_packageSite2 = __esm(() => {
71096
71517
  init_packageKnowledgeMap();
71097
71518
  init_markdownLinks();
71098
71519
  init_packageSiteTheme();
71520
+ init_packageSiteBranding();
71099
71521
  require2 = createRequire5(import.meta.url);
71100
71522
  });
71101
71523
 
@@ -72274,7 +72696,7 @@ function validateRenderedSkillDefinition(input) {
72274
72696
  }
72275
72697
  let frontmatter;
72276
72698
  try {
72277
- frontmatter = import_yaml31.parse(frontmatterMatch[1]);
72699
+ frontmatter = import_yaml33.parse(frontmatterMatch[1]);
72278
72700
  } catch {
72279
72701
  frontmatter = null;
72280
72702
  }
@@ -72301,7 +72723,7 @@ function validateRenderedSkillDefinition(input) {
72301
72723
  });
72302
72724
  }
72303
72725
  }
72304
- var import_yaml31, OKF_OUTPUT_ROOTS2, SKILL_NAME_PATTERN;
72726
+ var import_yaml33, OKF_OUTPUT_ROOTS2, SKILL_NAME_PATTERN;
72305
72727
  var init_packageTemplateGuard = __esm(() => {
72306
72728
  init_cliFeedback();
72307
72729
  init_errors3();
@@ -72309,7 +72731,7 @@ var init_packageTemplateGuard = __esm(() => {
72309
72731
  init_packageIndexes();
72310
72732
  init_packageDistribution();
72311
72733
  init_packageTemplateUtils();
72312
- import_yaml31 = __toESM(require_dist(), 1);
72734
+ import_yaml33 = __toESM(require_dist(), 1);
72313
72735
  OKF_OUTPUT_ROOTS2 = new Set(["wikis", "guides", "rules", "feats"]);
72314
72736
  SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
72315
72737
  });
@@ -72370,7 +72792,7 @@ function isDeprecatedKnowledge(content3) {
72370
72792
  if (match?.[1] === undefined)
72371
72793
  return false;
72372
72794
  try {
72373
- const frontmatter = import_yaml33.parse(match[1]);
72795
+ const frontmatter = import_yaml35.parse(match[1]);
72374
72796
  return frontmatter !== null && typeof frontmatter === "object" && !Array.isArray(frontmatter) && frontmatter.deprecated === true;
72375
72797
  } catch {
72376
72798
  return false;
@@ -72797,10 +73219,11 @@ async function buildProjectPackagesInternal(projectRoot, options) {
72797
73219
  if (!production && (!maintenanceActive || (await readRevisionDelivery(projectRoot))?.partial) && !await readTaskRollback(projectRoot))
72798
73220
  await completeRevisionDelivery(projectRoot);
72799
73221
  const { finishApprovedRevision } = await Promise.resolve().then(() => (init_approvedRevision(), exports_approvedRevision));
72800
- await finishApprovedRevision(projectRoot);
72801
73222
  const { readApprovedRevision: readApprovedRevision2 } = await Promise.resolve().then(() => (init_approvedRevision(), exports_approvedRevision));
73223
+ const revisionInterruptedProduction = !!production && !!await readApprovedRevision2(projectRoot);
73224
+ await finishApprovedRevision(projectRoot);
72802
73225
  const { readKnowledgeUpdate } = await Promise.resolve().then(() => (init_knowledgeUpdate(), exports_knowledgeUpdate));
72803
- if (!production?.delivery && !maintenanceActive && !await readTaskRollback(projectRoot) && !await readApprovedRevision2(projectRoot) && !await readKnowledgeUpdate(projectRoot) && (await readProjectCloseStatus(projectRoot)).state === "ready") {
73226
+ if (!revisionInterruptedProduction && !production?.delivery && !maintenanceActive && !await readTaskRollback(projectRoot) && !await readApprovedRevision2(projectRoot) && !await readKnowledgeUpdate(projectRoot) && (await readProjectCloseStatus(projectRoot)).state === "ready") {
72804
73227
  const { clearCompletedLifecycle: clearCompletedLifecycle2 } = await Promise.resolve().then(() => (init_lifecycleCleanup(), exports_lifecycleCleanup));
72805
73228
  await clearCompletedLifecycle2(projectRoot);
72806
73229
  }
@@ -72901,7 +73324,7 @@ async function runProjectBuildCommand(input) {
72901
73324
  process.stdout.write(formatProjectBuildResult(result, input.format ?? "text", input.verbose === true));
72902
73325
  return true;
72903
73326
  }
72904
- var import_yaml33, PACKAGE_FINGERPRINT_ROOT, PACKAGE_BUILDER_PROTOCOL_VERSION = "v23-sibling-site-output";
73327
+ var import_yaml35, PACKAGE_FINGERPRINT_ROOT, PACKAGE_BUILDER_PROTOCOL_VERSION = "v23-sibling-site-output";
72905
73328
  var init_packageBuilder = __esm(() => {
72906
73329
  init_knowledgeMap2();
72907
73330
  init_approvedFileRead();
@@ -72938,7 +73361,7 @@ var init_packageBuilder = __esm(() => {
72938
73361
  init_workspace();
72939
73362
  init_packageTemplateReview();
72940
73363
  init_approvedKnowledgeMetadata();
72941
- import_yaml33 = __toESM(require_dist(), 1);
73364
+ import_yaml35 = __toESM(require_dist(), 1);
72942
73365
  PACKAGE_FINGERPRINT_ROOT = join62(".tmp", "context-runtime", "packages");
72943
73366
  });
72944
73367
 
@@ -73691,7 +74114,7 @@ __export(exports_approvedRevision, {
73691
74114
  assertApprovedRevisionBase: () => assertApprovedRevisionBase,
73692
74115
  APPROVED_REVISION_PATH: () => APPROVED_REVISION_PATH
73693
74116
  });
73694
- import { readFile as readFile56, realpath as realpath6 } from "node:fs/promises";
74117
+ import { readFile as readFile56, realpath as realpath6, rm as rm15 } from "node:fs/promises";
73695
74118
  import { join as join66, relative as relative19, isAbsolute as isAbsolute12 } from "node:path";
73696
74119
  function requestDigest(input) {
73697
74120
  const scopes = input.processed_scopes?.filter((scope2) => input.target.source_refs.some((ref) => ref === scope2.source_ref || ref.startsWith(`${scope2.source_ref}#`) || ref.startsWith(`${scope2.source_ref}/`)));
@@ -73709,7 +74132,7 @@ function parseApprovedRevision(value) {
73709
74132
  if (!value || typeof value !== "object" || !("protocol" in value) || value.protocol !== "context.approved-revision/v1")
73710
74133
  return;
73711
74134
  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))
74135
+ 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
74136
  throw new TypeError("Approved revision target or digest is invalid");
73714
74137
  const { candidate: raw, batch_candidates: batch, ...rest } = parsed;
73715
74138
  const request = { ...rest, ...batch === undefined ? {} : { batch_candidates: batch.map((item, index2) => parseCandidateRecord(item, index2 + 1)) } };
@@ -73902,12 +74325,15 @@ async function prepareApprovedRevision(input) {
73902
74325
  };
73903
74326
  }
73904
74327
  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.");
74328
+ const destinationCollection = indexerKnowledgeCollectionSchema2.safeParse(input.move_to.split("/")[0]);
74329
+ if (input.create || !destinationCollection.success || !isSafeKnowledgeTargetPath(destinationCollection.data, input.move_to) || input.move_to.includes("\\") || input.move_to === target.path) {
74330
+ throw new TypeError("Move requires a different safe path in a supported knowledge collection.");
73907
74331
  }
73908
74332
  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 };
74333
+ 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 : `---
74334
+ ${import_yaml36.default.stringify({ ...import_yaml36.default.parse(fields), type: okfTypeForCollection(destinationCollection.data) }).trimEnd()}
74335
+ ---`);
74336
+ target = { ...target, collection: destinationCollection.data, previous_path: target.path, path: input.move_to, markdown: movedMarkdown };
73911
74337
  await assertApprovedRevisionBase(input.projectRoot, { target });
73912
74338
  }
73913
74339
  if (input.supporting_sources) {
@@ -73958,7 +74384,7 @@ async function prepareApprovedRevision(input) {
73958
74384
  }
73959
74385
  function frontmatter(markdown) {
73960
74386
  const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(markdown);
73961
- const parsed = match ? import_yaml35.default.parse(match[1]) : undefined;
74387
+ const parsed = match ? import_yaml36.default.parse(match[1]) : undefined;
73962
74388
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
73963
74389
  throw new TypeError("Revision must retain the approved page frontmatter");
73964
74390
  return parsed;
@@ -74143,6 +74569,11 @@ async function advanceApprovedRevision(projectRoot, request) {
74143
74569
  const { finishMaintenanceRevision: finishMaintenanceRevision2 } = await Promise.resolve().then(() => (init_knowledgeMaintenance(), exports_knowledgeMaintenance));
74144
74570
  if (await finishMaintenanceRevision2(projectRoot))
74145
74571
  return;
74572
+ const { readProductionStage: readProductionStage2 } = await Promise.resolve().then(() => (init_productionStageStore(), exports_productionStageStore));
74573
+ if (await readProductionStage2(projectRoot)) {
74574
+ await rm15(join66(projectRoot, await revisionStoragePath(projectRoot)), { force: true });
74575
+ return;
74576
+ }
74146
74577
  const { clearCompletedLifecycle: clearCompletedLifecycle2 } = await Promise.resolve().then(() => (init_lifecycleCleanup(), exports_lifecycleCleanup));
74147
74578
  await clearCompletedLifecycle2(projectRoot);
74148
74579
  }
@@ -74246,7 +74677,7 @@ async function reopenApprovedRevision(input) {
74246
74677
  };
74247
74678
  });
74248
74679
  }
74249
- var import_yaml35, digest5, revisionTargetSchema, requestSchema2;
74680
+ var import_yaml36, digest5, revisionTargetSchema, requestSchema2;
74250
74681
  var init_approvedRevision = __esm(() => {
74251
74682
  init_productionRequirements();
74252
74683
  init_approvedRevisionEdits();
@@ -74263,8 +74694,9 @@ var init_approvedRevision = __esm(() => {
74263
74694
  init_durableSingleFileTransaction();
74264
74695
  init_durableMultiFileTransaction();
74265
74696
  init_processedScopeStorage();
74697
+ init_okfTypes();
74266
74698
  init_maintenanceStorage();
74267
- import_yaml35 = __toESM(require_dist(), 1);
74699
+ import_yaml36 = __toESM(require_dist(), 1);
74268
74700
  digest5 = exports_external.string().regex(/^sha256:[a-f0-9]{64}$/u);
74269
74701
  revisionTargetSchema = exports_external.object({
74270
74702
  path: exports_external.string().min(1),
@@ -80458,7 +80890,7 @@ var init_documentRun = __esm(() => {
80458
80890
  });
80459
80891
 
80460
80892
  // src/lib/atomicFileBatch.ts
80461
- import { lstat as lstat7, mkdir as mkdir25, mkdtemp as mkdtemp3, rename as rename6, rm as rm15, writeFile as writeFile19 } from "node:fs/promises";
80893
+ import { lstat as lstat7, mkdir as mkdir25, mkdtemp as mkdtemp3, rename as rename6, rm as rm16, writeFile as writeFile19 } from "node:fs/promises";
80462
80894
  import { dirname as dirname31, join as join70, resolve as resolve23 } from "node:path";
80463
80895
  async function existingFileKind(path2) {
80464
80896
  try {
@@ -80521,7 +80953,7 @@ async function applyAtomicFileBatch(input) {
80521
80953
  } catch (error) {
80522
80954
  const rollbackFailures = [];
80523
80955
  for (const path2 of installed.reverse()) {
80524
- await rm15(path2, { force: true }).catch((rollbackError) => {
80956
+ await rm16(path2, { force: true }).catch((rollbackError) => {
80525
80957
  rollbackFailures.push(`remove ${path2}: ${String(rollbackError)}`);
80526
80958
  });
80527
80959
  }
@@ -80538,7 +80970,7 @@ async function applyAtomicFileBatch(input) {
80538
80970
  throw error;
80539
80971
  } finally {
80540
80972
  if (!preserveTransaction)
80541
- await rm15(transactionDir, { recursive: true, force: true });
80973
+ await rm16(transactionDir, { recursive: true, force: true });
80542
80974
  }
80543
80975
  }
80544
80976
  var init_atomicFileBatch = () => {};
@@ -81718,7 +82150,7 @@ async function approveProductionReport(input) {
81718
82150
  throw new TypeError("The report's plan changed. Read and present the current proposal before confirming it.");
81719
82151
  }
81720
82152
  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));
82153
+ const decision = productionReportInputSchema.extend({ stage: exports_external.literal(stage.id) }).parse(import_yaml39.default.parse(file.text));
81722
82154
  if (!stage.report_approved)
81723
82155
  await assertProductionPlanRequirementsCurrent(input.projectRoot, stage);
81724
82156
  if (decision.decision === "approved")
@@ -81734,7 +82166,7 @@ async function approveProductionReport(input) {
81734
82166
  }
81735
82167
  }));
81736
82168
  }
81737
- var import_yaml38, productionReportInputSchema;
82169
+ var import_yaml39, productionReportInputSchema;
81738
82170
  var init_productionReport = __esm(() => {
81739
82171
  init_zod();
81740
82172
  init_src2();
@@ -81744,7 +82176,7 @@ var init_productionReport = __esm(() => {
81744
82176
  init_productionStagePreparation();
81745
82177
  init_productionPlanning();
81746
82178
  init_productionFeedback();
81747
- import_yaml38 = __toESM(require_dist(), 1);
82179
+ import_yaml39 = __toESM(require_dist(), 1);
81748
82180
  productionReportInputSchema = exports_external.object({ stage: exports_external.string().min(1), decision: exports_external.literal("approved") }).strict();
81749
82181
  });
81750
82182
 
@@ -86644,7 +87076,7 @@ var init_larkResourceCommand = __esm(() => {
86644
87076
 
86645
87077
  // src/lib/larkResourceMaterialization.ts
86646
87078
  import { createHash as createHash26 } from "node:crypto";
86647
- import { mkdtemp as mkdtemp4, readFile as readFile67, readdir as readdir18, rm as rm18 } from "node:fs/promises";
87079
+ import { mkdtemp as mkdtemp4, readFile as readFile67, readdir as readdir18, rm as rm19 } from "node:fs/promises";
86648
87080
  import { extname as extname13, join as join88 } from "node:path";
86649
87081
  import { tmpdir } from "node:os";
86650
87082
  function countByKind(items, status) {
@@ -86777,7 +87209,7 @@ async function downloadedFile(input) {
86777
87209
  const bytes = await readFile67(join88(tempRoot, path3));
86778
87210
  return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes) };
86779
87211
  } finally {
86780
- await rm18(tempRoot, { recursive: true, force: true });
87212
+ await rm19(tempRoot, { recursive: true, force: true });
86781
87213
  }
86782
87214
  }
86783
87215
  function parseCsv(value) {
@@ -86909,7 +87341,7 @@ ${markdownTable2(parseCsv(csv))}
86909
87341
  [CSV snapshot](${sourceAssetTarget(path3)}) <!-- ${resource.locator} -->`
86910
87342
  };
86911
87343
  } finally {
86912
- await rm18(tempRoot, { recursive: true, force: true });
87344
+ await rm19(tempRoot, { recursive: true, force: true });
86913
87345
  }
86914
87346
  }
86915
87347
  function basePageRecords(value) {
@@ -87043,7 +87475,7 @@ async function whiteboardMaterialization(resource, runner2, identity) {
87043
87475
  ], { cwd: tempRoot });
87044
87476
  rawPayload = JSON.parse(await readFile67(join88(tempRoot, "raw.json"), "utf8"));
87045
87477
  } finally {
87046
- await rm18(tempRoot, { recursive: true, force: true });
87478
+ await rm19(tempRoot, { recursive: true, force: true });
87047
87479
  }
87048
87480
  const digest6 = resourceDigest(resource);
87049
87481
  const previewPath = `materialized/${resource.kind}/${digest6}${extensionFor2(preview.mediaType, preview.path)}`;
@@ -88328,6 +88760,355 @@ var init_actionInputWorkspace = __esm(() => {
88328
88760
  init_workspace();
88329
88761
  });
88330
88762
 
88763
+ // src/project/articleRetirement.ts
88764
+ var exports_articleRetirement = {};
88765
+ __export(exports_articleRetirement, {
88766
+ retireArticles: () => retireArticles,
88767
+ articleRetirementSchema: () => articleRetirementSchema
88768
+ });
88769
+ import { readFile as readFile74, readdir as readdir20 } from "node:fs/promises";
88770
+ import { posix as posix10 } from "node:path";
88771
+ function invalid(reason, message, details = {}) {
88772
+ throw new ContextError(ExitCode.UserError, message, {
88773
+ category: ErrorCategory.UserInputInvalid,
88774
+ reason_code: reason,
88775
+ ...details,
88776
+ next_action: {
88777
+ command: next,
88778
+ message: "Keep the retirement input. Resolve the listed page/reference or finish the active revision, then preview it again; no retirement was applied."
88779
+ }
88780
+ });
88781
+ }
88782
+ async function text9(root2, path3) {
88783
+ try {
88784
+ return await readFile74(await safeProjectTarget(root2, path3), "utf8");
88785
+ } catch (error) {
88786
+ if (error.code === "ENOENT")
88787
+ return;
88788
+ throw error;
88789
+ }
88790
+ }
88791
+ async function retireArticles(input) {
88792
+ const parsed = articleRetirementSchema.safeParse(input.value);
88793
+ if (!parsed.success)
88794
+ 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)" }] } });
88795
+ const value = parsed.data;
88796
+ return withProjectWriteLock(input.projectRoot, "retire-articles", async () => {
88797
+ if (input.apply)
88798
+ await recoverDurableMultiFileTransactions(input.projectRoot);
88799
+ if (input.apply && input.plan_digest && /^sha256:[a-f0-9]{64}$/u.test(input.plan_digest)) {
88800
+ const receipt3 = await text9(input.projectRoot, `.tmp/context-runtime/retirements/${input.plan_digest.slice(7)}/receipt.json`);
88801
+ if (receipt3) {
88802
+ const saved = JSON.parse(receipt3);
88803
+ if (saved.request !== indexerProtocolDigest(value))
88804
+ invalid("article-retirement-input-changed", "The retirement input differs from the applied request.");
88805
+ for (const file of saved.files) {
88806
+ const current2 = await text9(input.projectRoot, file.path);
88807
+ if ((current2 === undefined ? null : durableContentDigest(current2)) !== file.digest)
88808
+ invalid("article-retirement-result-changed", "Retirement was applied but a resulting file has since changed; inspect the current workspace.", { path: file.path });
88809
+ }
88810
+ return { action: "already-applied", revision: input.plan_digest, next_action: { command: next } };
88811
+ }
88812
+ }
88813
+ const maintenance = await readMaintenance(input.projectRoot);
88814
+ if ((await readCandidateRecords(input.projectRoot)).length || await readApprovedRevision(input.projectRoot) || await readKnowledgeUpdate(input.projectRoot) || await readTaskRollback(input.projectRoot) || maintenance.active) {
88815
+ invalid("article-retirement-active-review", "Finish the active candidate/revision delivery before retiring approved pages.");
88816
+ }
88817
+ const before = await text9(input.projectRoot, "knowledge/structure.yaml");
88818
+ const structure = before === undefined ? {} : import_yaml41.default.parse(before);
88819
+ const articles = validateArticleStructureEntries(structure.articles ?? []);
88820
+ const byPath = new Map(articles.map((article) => [article.path, article]));
88821
+ const selected = new Set(value.targets.map((target) => target.path));
88822
+ if (selected.size !== value.targets.length)
88823
+ invalid("article-retirement-duplicate", "Select each approved article once.");
88824
+ if (maintenance.pending.some((request) => request.targets.some((target) => selected.has(target.path)))) {
88825
+ invalid("article-retirement-pending-maintenance", "Cancel or finish queued maintenance for the selected pages before retirement.");
88826
+ }
88827
+ const stage = await readProductionStage(input.projectRoot);
88828
+ if (stage?.tasks.some((task) => selected.has(task.path) && !["accepted", "excluded", "replaced"].includes(task.status))) {
88829
+ invalid("article-retirement-pending-task", "A selected article still has unfinished production; finish or amend that task first.");
88830
+ }
88831
+ const replacements = new Map;
88832
+ for (const target of value.targets) {
88833
+ if (!byPath.has(target.path))
88834
+ invalid("article-retirement-target-missing", "Select an exact approved article path from knowledge/structure.yaml.", { path: target.path });
88835
+ if (target.replacement !== undefined && (!byPath.has(target.replacement) || selected.has(target.replacement))) {
88836
+ invalid("article-retirement-replacement-invalid", "Replacement must be an already-approved article outside the retirement set.", { path: target.path, replacement: target.replacement });
88837
+ }
88838
+ replacements.set(target.path, target.replacement);
88839
+ }
88840
+ const targets = [];
88841
+ const restore = [];
88842
+ function change(path3, old, content3) {
88843
+ if (old === content3)
88844
+ return;
88845
+ 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 });
88846
+ restore.push({ path: path3, base_digest: content3 === undefined ? null : durableContentDigest(content3), content: old ?? null });
88847
+ }
88848
+ const blockers = [];
88849
+ const readDigests = [];
88850
+ for (const article of articles) {
88851
+ const path3 = `knowledge/${article.path}`;
88852
+ const bytes = await text9(input.projectRoot, path3);
88853
+ if (bytes === undefined)
88854
+ invalid("article-retirement-article-missing", "Approved article bytes are missing; recover the workspace before retirement.", { path: path3 });
88855
+ readDigests.push({ path: path3, digest: durableContentDigest(bytes) });
88856
+ if (selected.has(article.path)) {
88857
+ change(path3, bytes);
88858
+ continue;
88859
+ }
88860
+ const content3 = replaceMarkdownInlineLinkTargets(bytes, (link2) => {
88861
+ if (link2.target.startsWith("#") || link2.target.startsWith("//"))
88862
+ return;
88863
+ const knowledge = link2.target.startsWith("knowledge:");
88864
+ if (!knowledge && /^[a-z][a-z0-9+.-]*:/iu.test(link2.target))
88865
+ return;
88866
+ const match = /^([^#?]*)(.*)$/u.exec(knowledge ? link2.target.slice(10) : link2.target);
88867
+ let target;
88868
+ try {
88869
+ target = decodeURI(match[1]);
88870
+ } catch {
88871
+ return;
88872
+ }
88873
+ const rooted = /^\/?knowledge\//u.test(target);
88874
+ if (target.startsWith("/") && !rooted)
88875
+ return;
88876
+ let resolved = knowledge ? target : rooted ? target.replace(/^\/?knowledge\//u, "") : posix10.normalize(posix10.join(posix10.dirname(article.path), target));
88877
+ if (knowledge && !resolved.endsWith(".md"))
88878
+ resolved += ".md";
88879
+ if (!selected.has(resolved))
88880
+ return;
88881
+ const replacement = replacements.get(resolved);
88882
+ if (!replacement || match[2].includes("#")) {
88883
+ blockers.push({ path: path3, target: link2.target, reason: replacement ? "Repair fragment links explicitly before retirement." : "Repair this incoming link or supply an approved replacement." });
88884
+ return;
88885
+ }
88886
+ 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]}`;
88887
+ });
88888
+ change(path3, bytes, content3);
88889
+ }
88890
+ async function inspectTemplates(directory2) {
88891
+ const absolute = await safeProjectTarget(input.projectRoot, directory2);
88892
+ const entries2 = await readdir20(absolute, { withFileTypes: true }).catch((error) => {
88893
+ if (error.code === "ENOENT")
88894
+ return [];
88895
+ throw error;
88896
+ });
88897
+ for (const entry of entries2) {
88898
+ const path3 = `${directory2}/${entry.name}`;
88899
+ if (entry.isDirectory()) {
88900
+ await inspectTemplates(path3);
88901
+ continue;
88902
+ }
88903
+ if (!entry.isFile() || !entry.name.endsWith(".md"))
88904
+ continue;
88905
+ const bytes = await text9(input.projectRoot, path3);
88906
+ readDigests.push({ path: path3, digest: durableContentDigest(bytes) });
88907
+ replaceMarkdownInlineLinkTargets(bytes, (link2) => {
88908
+ if (/^(?!knowledge:)[a-z][a-z0-9+.-]*:/iu.test(link2.target))
88909
+ return;
88910
+ let destination;
88911
+ try {
88912
+ destination = decodeURI(link2.target.split(/[?#]/u)[0]);
88913
+ } catch {
88914
+ return;
88915
+ }
88916
+ if (destination.startsWith("knowledge:") && !destination.endsWith(".md"))
88917
+ destination += ".md";
88918
+ if ([...selected].some((old) => destination === old || destination.endsWith(`/${old}`) || destination === `knowledge:${old}`)) {
88919
+ blockers.push({ path: path3, target: link2.target, reason: "Update this custom package-template link before retirement." });
88920
+ }
88921
+ return;
88922
+ });
88923
+ }
88924
+ }
88925
+ await inspectTemplates("src/package-templates");
88926
+ const map4 = await readKnowledgeMap(input.projectRoot);
88927
+ if (map4) {
88928
+ const retiredIds = new Map(value.targets.map((target) => [byPath.get(target.path).article_id, target]));
88929
+ const upsert = map4.entries.flatMap((entry) => {
88930
+ const target = entry.target && retiredIds.get(entry.target.artifact_ref);
88931
+ if (!target)
88932
+ return [];
88933
+ if (target.replacement && entry.target?.section_key) {
88934
+ blockers.push({ path: KNOWLEDGE_MAP_PATH, target: entry.key, reason: "Rebind this fragment navigation entry explicitly before retirement." });
88935
+ return [];
88936
+ }
88937
+ const { target: _old, ...group } = entry;
88938
+ return [target.replacement ? { ...group, target: { artifact_ref: byPath.get(target.replacement).article_id } } : group];
88939
+ });
88940
+ const updated = updateKnowledgeMap(map4, { expected_revision: map4.revision, upsert, remove: [] });
88941
+ change(KNOWLEDGE_MAP_PATH, await text9(input.projectRoot, KNOWLEDGE_MAP_PATH), import_yaml41.default.stringify(updated));
88942
+ }
88943
+ change("knowledge/structure.yaml", before, import_yaml41.default.stringify({ ...structure, articles: articles.filter((article) => !selected.has(article.path)) }));
88944
+ targets.sort((a, b) => a.path.localeCompare(b.path));
88945
+ const revision = indexerProtocolDigest({ value, readDigests, targets });
88946
+ const preview = {
88947
+ action: "preview",
88948
+ revision,
88949
+ reason: value.reason,
88950
+ retired: value.targets,
88951
+ changed_files: targets.map((target) => ({ path: target.path, operation: target.operation })),
88952
+ blockers,
88953
+ next_action: { command: blockers.length ? next : `context task retire --input <same-file> --apply --plan-digest '${revision}' --format json` }
88954
+ };
88955
+ if (!input.apply)
88956
+ return preview;
88957
+ if (input.plan_digest !== revision)
88958
+ invalid("article-retirement-preview-stale", "Preview this retirement input again; the selected pages, links or navigation changed.");
88959
+ if (blockers.length)
88960
+ invalid("article-retirement-references-unresolved", "Resolve incoming fragment links before applying retirement.", { blockers });
88961
+ const directory = `.tmp/context-runtime/retirements/${revision.slice(7)}`;
88962
+ const recovery = `${directory}/restore.json`;
88963
+ const receipt2 = `${directory}/receipt.json`;
88964
+ change(recovery, await text9(input.projectRoot, recovery), JSON.stringify({ summary: `Restore retired articles: ${value.reason}`, discard_unfinished: true, files: [...restore] }));
88965
+ change(receipt2, await text9(input.projectRoot, receipt2), JSON.stringify({
88966
+ request: indexerProtocolDigest(value),
88967
+ files: targets.map((target) => ({ path: target.path, digest: target.target_digest }))
88968
+ }));
88969
+ await runDurableMultiFileTransaction({
88970
+ projectRoot: input.projectRoot,
88971
+ kind: "retire-articles",
88972
+ proposal_digest: revision,
88973
+ targets: targets.sort((a, b) => a.path.localeCompare(b.path)),
88974
+ ...input.inject_failure ? { inject_failure: input.inject_failure } : {}
88975
+ });
88976
+ return {
88977
+ action: "applied",
88978
+ revision,
88979
+ retired: [...selected],
88980
+ recovery,
88981
+ 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." }
88982
+ };
88983
+ });
88984
+ }
88985
+ var import_yaml41, articleRetirementSchema, next = "context status --format json";
88986
+ var init_articleRetirement = __esm(() => {
88987
+ init_zod();
88988
+ init_src2();
88989
+ init_errors3();
88990
+ init_cliFeedback();
88991
+ init_exitCode();
88992
+ init_candidateLedger();
88993
+ init_approvedRevision();
88994
+ init_knowledgeUpdate();
88995
+ init_taskRollback();
88996
+ init_maintenanceStorage();
88997
+ init_productionStageStore();
88998
+ init_knowledgeMap2();
88999
+ init_markdownLinks();
89000
+ init_durableSingleFileTransaction();
89001
+ init_durableMultiFileTransaction();
89002
+ init_writeLock();
89003
+ import_yaml41 = __toESM(require_dist(), 1);
89004
+ articleRetirementSchema = exports_external.object({
89005
+ reason: exports_external.string().trim().min(1),
89006
+ targets: exports_external.array(exports_external.object({ path: exports_external.string().min(1), replacement: exports_external.string().min(1).optional() }).strict()).min(1)
89007
+ }).strict();
89008
+ });
89009
+
89010
+ // src/lib/schemaOutput.ts
89011
+ var exports_schemaOutput = {};
89012
+ __export(exports_schemaOutput, {
89013
+ writeSchemaOutput: () => writeSchemaOutput,
89014
+ schemaOutputFormat: () => schemaOutputFormat
89015
+ });
89016
+ function schemaOutputFormat(value) {
89017
+ if (value === "text" || value === "yaml" || value === "json")
89018
+ return value;
89019
+ throw new ContextError(ExitCode.UserError, "Expected schema format text, json, or yaml", { category: ErrorCategory.UserInputInvalid });
89020
+ }
89021
+ function writeSchemaOutput(value, format2) {
89022
+ process.stdout.write(format2 === "json" ? `${JSON.stringify(value, null, 2)}
89023
+ ` : import_yaml42.default.stringify(value));
89024
+ }
89025
+ var import_yaml42;
89026
+ var init_schemaOutput = __esm(() => {
89027
+ init_errors3();
89028
+ init_cliFeedback();
89029
+ init_exitCode();
89030
+ import_yaml42 = __toESM(require_dist(), 1);
89031
+ });
89032
+
89033
+ // src/project/writeLockRecovery.ts
89034
+ var exports_writeLockRecovery = {};
89035
+ __export(exports_writeLockRecovery, {
89036
+ recoverWriterLock: () => recoverWriterLock,
89037
+ inspectWriterLock: () => inspectWriterLock
89038
+ });
89039
+ import { lstat as lstat9, mkdir as mkdir32, readFile as readFile75, readdir as readdir21, rename as rename7, rmdir as rmdir2 } from "node:fs/promises";
89040
+ import { join as join94 } from "node:path";
89041
+ import { createHash as createHash28, randomUUID as randomUUID7 } from "node:crypto";
89042
+ async function inspectWriterLock(root2) {
89043
+ const path3 = await safeProjectTarget(root2, lockRelative);
89044
+ let stat11;
89045
+ try {
89046
+ stat11 = await lstat9(path3);
89047
+ } catch (error) {
89048
+ if (error.code === "ENOENT")
89049
+ return null;
89050
+ throw error;
89051
+ }
89052
+ if (!stat11.isDirectory() || stat11.isSymbolicLink())
89053
+ throw new Error("Writer lock must be a real directory.");
89054
+ const ownerPath = await safeProjectTarget(root2, `${lockRelative}/owner.json`);
89055
+ const bytes = await readFile75(ownerPath, "utf8");
89056
+ const owner = JSON.parse(bytes);
89057
+ if (owner.protocol !== "context.project-write-lock.v1" || !Number.isSafeInteger(owner.pid) || owner.pid <= 0) {
89058
+ throw new Error("Writer lock owner is invalid; preserve the lock for diagnosis.");
89059
+ }
89060
+ let processState = "running";
89061
+ try {
89062
+ process.kill(owner.pid, 0);
89063
+ } catch (error) {
89064
+ const code3 = error.code;
89065
+ processState = code3 === "ESRCH" ? "not-running" : code3 === "EPERM" ? "running" : "unknown";
89066
+ }
89067
+ const digest6 = `sha256:${createHash28("sha256").update(`${stat11.dev}:${stat11.ino}:${stat11.birthtimeMs}:${bytes}`).digest("hex")}`;
89068
+ return { ...owner, process_state: processState, digest: digest6, path: lockRelative };
89069
+ }
89070
+ async function recoverWriterLock(input) {
89071
+ const before = await inspectWriterLock(input.projectRoot);
89072
+ if (!before)
89073
+ return { action: "writer-lock-absent", next: "context task recover --format json" };
89074
+ if (before.process_state !== "not-running")
89075
+ throw new Error("Writer is running or cannot be identified as stopped; keep the lock.");
89076
+ if (!input.apply)
89077
+ return {
89078
+ action: "preview",
89079
+ operation: "writer-lock",
89080
+ revision: before.digest,
89081
+ owner: before,
89082
+ 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.",
89083
+ next: `${command2} --apply --plan-digest '${before.digest}'`
89084
+ };
89085
+ if (input.plan_digest !== before.digest)
89086
+ throw new Error("Writer lock changed; preview recovery again.");
89087
+ const path3 = join94(input.projectRoot, lockRelative);
89088
+ const guard = join94(path3, ".recovery");
89089
+ await mkdir32(guard);
89090
+ let archived = false;
89091
+ try {
89092
+ const current2 = await inspectWriterLock(input.projectRoot);
89093
+ if (current2?.digest !== before.digest || current2.process_state !== "not-running")
89094
+ throw new Error("Writer lock changed or owner resumed; keep the lock.");
89095
+ const names = await readdir21(path3);
89096
+ if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
89097
+ throw new Error("Unexpected lock contents; preserve for diagnosis.");
89098
+ const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
89099
+ await rename7(path3, join94(input.projectRoot, archive));
89100
+ archived = true;
89101
+ return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
89102
+ } finally {
89103
+ if (!archived)
89104
+ await rmdir2(guard);
89105
+ }
89106
+ }
89107
+ var lockRelative = ".tmp/context-runtime/locks/project-write.lock", command2 = "context task recover --operation writer-lock --format json";
89108
+ var init_writeLockRecovery = __esm(() => {
89109
+ init_durableMultiFileTransaction();
89110
+ });
89111
+
88331
89112
  // src/project/taskRecovery.ts
88332
89113
  var exports_taskRecovery = {};
88333
89114
  __export(exports_taskRecovery, {
@@ -88339,12 +89120,12 @@ __export(exports_taskRecovery, {
88339
89120
  RECOVERY_COMMAND: () => RECOVERY_COMMAND
88340
89121
  });
88341
89122
  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";
89123
+ import { dirname as dirname40, join as join95 } from "node:path";
89124
+ import { lstat as lstat10, readdir as readdir22, readFile as readFile76 } from "node:fs/promises";
88344
89125
  async function recoveryText(root2, path3) {
88345
89126
  const target = await safeProjectTarget(root2, path3);
88346
89127
  try {
88347
- return await readFile74(target, "utf8");
89128
+ return await readFile76(target, "utf8");
88348
89129
  } catch (error) {
88349
89130
  if (error.code === "ENOENT")
88350
89131
  return;
@@ -88355,22 +89136,22 @@ async function recoveryJournals(root2) {
88355
89136
  const entries2 = [];
88356
89137
  async function visit4(path3, depth) {
88357
89138
  await safeProjectTarget(root2, path3);
88358
- let stat10;
89139
+ let stat11;
88359
89140
  try {
88360
- stat10 = await lstat9(join94(root2, path3));
89141
+ stat11 = await lstat10(join95(root2, path3));
88361
89142
  } catch (error) {
88362
89143
  if (error.code === "ENOENT")
88363
89144
  return;
88364
89145
  throw error;
88365
89146
  }
88366
- if (stat10.isSymbolicLink())
89147
+ if (stat11.isSymbolicLink())
88367
89148
  throw new TypeError("Recovery does not follow transaction symlinks.");
88368
- if (stat10.isDirectory()) {
89149
+ if (stat11.isDirectory()) {
88369
89150
  if (depth > 3)
88370
89151
  throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
88371
- for (const name3 of (await readdir20(join94(root2, path3))).sort())
89152
+ for (const name3 of (await readdir22(join95(root2, path3))).sort())
88372
89153
  await visit4(`${path3}/${name3}`, depth + 1);
88373
- } else if (stat10.isFile())
89154
+ } else if (stat11.isFile())
88374
89155
  entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
88375
89156
  }
88376
89157
  await visit4(TRANSACTIONS_PATH, 0);
@@ -88380,8 +89161,8 @@ function recoveryResources() {
88380
89161
  try {
88381
89162
  const root2 = dirname40(contextWorkflowProviderPath());
88382
89163
  const resources = {
88383
- skill: join94(root2, "skills/recover-workspace/SKILL.md"),
88384
- issue_template: join94(root2, "resources/templates/recovery-issue.md")
89164
+ skill: join95(root2, "skills/recover-workspace/SKILL.md"),
89165
+ issue_template: join95(root2, "resources/templates/recovery-issue.md")
88385
89166
  };
88386
89167
  if (!Object.values(resources).every((path3) => existsSync26(path3)))
88387
89168
  throw new Error("Recovery resources are absent from this Provider.");
@@ -88402,10 +89183,7 @@ async function inspectTaskRecovery(root2) {
88402
89183
  }
88403
89184
  const stage = await probe("production-stage", () => readProductionStage(root2));
88404
89185
  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
- });
89186
+ const lock = await probe("writer-lock", () => inspectWriterLock(root2));
88409
89187
  return {
88410
89188
  action: "recovery-inspected",
88411
89189
  resources: recoveryResources(),
@@ -88415,6 +89193,7 @@ async function inspectTaskRecovery(root2) {
88415
89193
  transactions: journals,
88416
89194
  writer_lock: lock,
88417
89195
  actions: [
89196
+ ...lock?.process_state === "not-running" ? [{ operation: "writer-lock", command: `${RECOVERY_COMMAND} --operation writer-lock` }] : [],
88418
89197
  ...journals?.length ? [{ operation: "transactions", command: `${RECOVERY_COMMAND} --operation transactions` }] : [],
88419
89198
  ...stage ? [{ operation: "continue", command: "context status --format json" }] : []
88420
89199
  ],
@@ -88460,6 +89239,7 @@ var init_taskRecovery = __esm(() => {
88460
89239
  init_writeLock();
88461
89240
  init_durableMultiFileTransaction();
88462
89241
  init_workflowProvider();
89242
+ init_writeLockRecovery();
88463
89243
  });
88464
89244
 
88465
89245
  // src/project/taskLocalSourceAdjustment.ts
@@ -88467,8 +89247,8 @@ var exports_taskLocalSourceAdjustment = {};
88467
89247
  __export(exports_taskLocalSourceAdjustment, {
88468
89248
  adjustLocalRevisionSources: () => adjustLocalRevisionSources
88469
89249
  });
88470
- import { readFile as readFile75 } from "node:fs/promises";
88471
- import { join as join95 } from "node:path";
89250
+ import { readFile as readFile77 } from "node:fs/promises";
89251
+ import { join as join96 } from "node:path";
88472
89252
  async function adjustLocalRevisionSources(root2, input) {
88473
89253
  const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
88474
89254
  if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
@@ -88492,11 +89272,11 @@ async function adjustLocalRevisionSources(root2, input) {
88492
89272
  if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
88493
89273
  throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
88494
89274
  }
88495
- const raw = await readFile75(join95(root2, await revisionStoragePath(root2)), "utf8");
88496
- let next;
89275
+ const raw = await readFile77(join96(root2, await revisionStoragePath(root2)), "utf8");
89276
+ let next2;
88497
89277
  const discardIds = new Set;
88498
89278
  if (!input.refresh) {
88499
- next = { ...current2, refresh_sources: selected };
89279
+ next2 = { ...current2, refresh_sources: selected };
88500
89280
  } else {
88501
89281
  const oldScopes = [
88502
89282
  ...revision?.processed_scopes ?? update?.scopes ?? [],
@@ -88570,7 +89350,7 @@ ${input.instruction}`,
88570
89350
 
88571
89351
  ${input.instruction}` : revision.instruction
88572
89352
  };
88573
- next = { ...payload, revision: requestDigest(payload), ...!affected && candidate ? { candidate } : {} };
89353
+ next2 = { ...payload, revision: requestDigest(payload), ...!affected && candidate ? { candidate } : {} };
88574
89354
  if (affected && candidate)
88575
89355
  discardIds.add(candidate.candidate_id);
88576
89356
  } else {
@@ -88578,14 +89358,14 @@ ${input.instruction}` : revision.instruction
88578
89358
  const payload = { ...rest, scopes, requirements, changes: [rest.changes, input.instruction].filter(Boolean).join(`
88579
89359
 
88580
89360
  `) };
88581
- next = { ...payload, revision: indexerProtocolDigest(payload) };
89361
+ next2 = { ...payload, revision: indexerProtocolDigest(payload) };
88582
89362
  }
88583
89363
  }
88584
89364
  if (update && !input.refresh) {
88585
- const { revision: _revision, ...payload } = next;
88586
- next.revision = indexerProtocolDigest(payload);
89365
+ const { revision: _revision, ...payload } = next2;
89366
+ next2.revision = indexerProtocolDigest(payload);
88587
89367
  }
88588
- const content3 = `${JSON.stringify(next)}
89368
+ const content3 = `${JSON.stringify(next2)}
88589
89369
  `;
88590
89370
  const targets = [{
88591
89371
  path: await revisionStoragePath(root2),
@@ -88595,7 +89375,7 @@ ${input.instruction}` : revision.instruction
88595
89375
  content: content3
88596
89376
  }];
88597
89377
  if (discardIds.size > 0) {
88598
- const ledger = await readFile75(join95(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
89378
+ const ledger = await readFile77(join96(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
88599
89379
  if (error.code === "ENOENT")
88600
89380
  return;
88601
89381
  throw error;
@@ -88631,6 +89411,7 @@ var init_taskLocalSourceAdjustment = __esm(() => {
88631
89411
  // src/project/taskSourceAdjustment.ts
88632
89412
  var exports_taskSourceAdjustment = {};
88633
89413
  __export(exports_taskSourceAdjustment, {
89414
+ taskSourceAdjustmentSchema: () => taskSourceAdjustmentSchema,
88634
89415
  adjustCurrentTaskSources: () => adjustCurrentTaskSources
88635
89416
  });
88636
89417
  async function adjustCurrentTaskSources(projectRoot, value) {
@@ -88685,7 +89466,7 @@ async function adjustCurrentTaskSources(projectRoot, value) {
88685
89466
  });
88686
89467
  });
88687
89468
  }
88688
- var schema2;
89469
+ var schema2, taskSourceAdjustmentSchema;
88689
89470
  var init_taskSourceAdjustment = __esm(() => {
88690
89471
  init_src2();
88691
89472
  init_knowledgeMap2();
@@ -88712,10 +89493,11 @@ var init_taskSourceAdjustment = __esm(() => {
88712
89493
  instruction: exports_external.string().trim().min(1),
88713
89494
  refresh: exports_external.boolean().optional()
88714
89495
  }).strict();
89496
+ taskSourceAdjustmentSchema = exports_external.union([schema2, exports_external.object({ knowledge_map: knowledgeMapUpdateSchema }).strict()]);
88715
89497
  });
88716
89498
 
88717
89499
  // src/project/managedDocumentImport.ts
88718
- import { readFile as readFile81 } from "node:fs/promises";
89500
+ import { readFile as readFile83 } from "node:fs/promises";
88719
89501
  async function importManagedDocument(projectRoot, value) {
88720
89502
  const input = inputSchema.parse(value);
88721
89503
  if (input.type !== "sessions" && input.changes !== undefined)
@@ -88724,7 +89506,7 @@ async function importManagedDocument(projectRoot, value) {
88724
89506
  const path3 = await assertManagedDocumentPath(projectRoot, input.type, input.name);
88725
89507
  let previous3;
88726
89508
  try {
88727
- previous3 = await readFile81(path3, "utf8");
89509
+ previous3 = await readFile83(path3, "utf8");
88728
89510
  } catch (error) {
88729
89511
  if (!(error && typeof error === "object" && ("code" in error) && error.code === "ENOENT"))
88730
89512
  throw error;
@@ -88771,14 +89553,14 @@ var init_managedDocumentImport = __esm(() => {
88771
89553
  });
88772
89554
 
88773
89555
  // src/project/larkDocumentImport.ts
88774
- import { readFile as readFile82 } from "node:fs/promises";
89556
+ import { readFile as readFile84 } from "node:fs/promises";
88775
89557
  async function importLarkDocument(projectRoot, value) {
88776
89558
  const input = schema3.parse(value);
88777
89559
  const responsePages = [];
88778
89560
  for (const path3 of input.response_files) {
88779
89561
  assertActionInputWorkspace(projectRoot, path3);
88780
89562
  const { resolve: resolve8 } = await import("node:path");
88781
- responsePages.push(await readFile82(resolve8(projectRoot, path3), "utf8"));
89563
+ responsePages.push(await readFile84(resolve8(projectRoot, path3), "utf8"));
88782
89564
  }
88783
89565
  const mediaFiles = {};
88784
89566
  for (const [token, path3] of Object.entries(input.media_files ?? {})) {
@@ -88846,11 +89628,11 @@ var exports_managedDocumentRename = {};
88846
89628
  __export(exports_managedDocumentRename, {
88847
89629
  renameManagedDocument: () => renameManagedDocument
88848
89630
  });
88849
- import { readFile as readFile83 } from "node:fs/promises";
88850
- import { join as join103, posix as posix10 } from "node:path";
89631
+ import { readFile as readFile85 } from "node:fs/promises";
89632
+ import { join as join104, posix as posix11 } from "node:path";
88851
89633
  async function optionalText2(path3) {
88852
89634
  try {
88853
- return await readFile83(path3, "utf8");
89635
+ return await readFile85(path3, "utf8");
88854
89636
  } catch (error) {
88855
89637
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
88856
89638
  return;
@@ -88934,12 +89716,12 @@ async function renameManagedDocument(input) {
88934
89716
  if (path3.split("/").includes("..") || path3.startsWith("/"))
88935
89717
  throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
88936
89718
  await safeProjectTarget(input.projectRoot, path3);
88937
- const before = await optionalText2(join103(input.projectRoot, path3));
89719
+ const before = await optionalText2(join104(input.projectRoot, path3));
88938
89720
  if (before === undefined)
88939
89721
  continue;
88940
89722
  let after;
88941
89723
  if (path3.endsWith(".yaml")) {
88942
- const parsed = import_yaml46.default.parse(before);
89724
+ const parsed = import_yaml48.default.parse(before);
88943
89725
  const updated = replace2(parsed);
88944
89726
  if (path3 === "knowledge/structure.yaml") {
88945
89727
  const rewritten = articles.map((article) => ({ ...article, sections: article.sections.map((section) => ({
@@ -88947,14 +89729,14 @@ async function renameManagedDocument(input) {
88947
89729
  references: section.references.map((citation) => citation.source_ref !== input.source_ref ? citation : {
88948
89730
  ...citation,
88949
89731
  source_ref: nextRef,
88950
- locator: { ...citation.locator, path: posix10.basename(input.name) }
89732
+ locator: { ...citation.locator, path: posix11.basename(input.name) }
88951
89733
  })
88952
89734
  })) }));
88953
89735
  updated.articles = rewritten;
88954
89736
  }
88955
89737
  if (JSON.stringify(parsed) === JSON.stringify(updated))
88956
89738
  continue;
88957
- after = import_yaml46.default.stringify(updated);
89739
+ after = import_yaml48.default.stringify(updated);
88958
89740
  } else
88959
89741
  after = before.replace(reference2, nextRef);
88960
89742
  if (path3 === "src/index.ts")
@@ -88973,11 +89755,11 @@ async function renameManagedDocument(input) {
88973
89755
  return;
88974
89756
  }
88975
89757
  const rooted = destination.startsWith("sources/") || destination.startsWith("/sources/");
88976
- const resolved = rooted ? destination.replace(/^\//u, "") : posix10.normalize(posix10.join(posix10.dirname(path3), destination));
89758
+ const resolved = rooted ? destination.replace(/^\//u, "") : posix11.normalize(posix11.join(posix11.dirname(path3), destination));
88977
89759
  if (resolved !== `sources/${type}/${oldName}`)
88978
89760
  return;
88979
89761
  const renamed = `sources/${type}/${input.name}`;
88980
- return encodeURI(rooted ? `${destination.startsWith("/") ? "/" : ""}${renamed}` : posix10.relative(posix10.dirname(path3), renamed)) + match2[2];
89762
+ return encodeURI(rooted ? `${destination.startsWith("/") ? "/" : ""}${renamed}` : posix11.relative(posix11.dirname(path3), renamed)) + match2[2];
88981
89763
  });
88982
89764
  if (before === after)
88983
89765
  continue;
@@ -89006,7 +89788,7 @@ async function renameManagedDocument(input) {
89006
89788
  };
89007
89789
  });
89008
89790
  }
89009
- var import_yaml46;
89791
+ var import_yaml48;
89010
89792
  var init_managedDocumentRename = __esm(() => {
89011
89793
  init_markdownLinks();
89012
89794
  init_src2();
@@ -89018,12 +89800,12 @@ var init_managedDocumentRename = __esm(() => {
89018
89800
  init_durableSingleFileTransaction();
89019
89801
  init_durableMultiFileTransaction();
89020
89802
  init_writeLock();
89021
- import_yaml46 = __toESM(require_dist(), 1);
89803
+ import_yaml48 = __toESM(require_dist(), 1);
89022
89804
  });
89023
89805
 
89024
89806
  // src/cli.ts
89025
89807
  import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
89026
- import { dirname as dirname47, join as join107 } from "node:path";
89808
+ import { dirname as dirname47, join as join108 } from "node:path";
89027
89809
  import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL3 } from "node:url";
89028
89810
 
89029
89811
  // ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
@@ -89103,7 +89885,7 @@ init_cliFeedback();
89103
89885
  init_errors3();
89104
89886
  init_exitCode();
89105
89887
  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";
89888
+ import { mkdir as mkdir26, readdir as readdir16, readFile as readFile60, rm as rm17, stat as stat10, writeFile as writeFile20 } from "node:fs/promises";
89107
89889
  import { basename as basename8, dirname as dirname32, extname as extname12, join as join72, relative as relative22, resolve as resolve24 } from "node:path";
89108
89890
 
89109
89891
  // src/project/documentCaptureAssets.ts
@@ -89113,7 +89895,7 @@ init_errors3();
89113
89895
  init_exitCode();
89114
89896
  init_markdownLinks();
89115
89897
  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";
89898
+ import { mkdir as mkdir24, readFile as readFile57, stat as stat8, writeFile as writeFile18 } from "node:fs/promises";
89117
89899
  import { dirname as dirname29, isAbsolute as isAbsolute13, join as join67, relative as relative20, resolve as resolve21 } from "node:path";
89118
89900
  function runtimeError(message, detail) {
89119
89901
  return new ContextError(ExitCode.UserError, message, {
@@ -89154,7 +89936,7 @@ async function writeCaptureAssetIfChanged(path2, content3) {
89154
89936
  await writeFile18(path2, content3);
89155
89937
  }
89156
89938
  async function readLinkedCaptureAssets(input) {
89157
- const rootStat = await stat7(input.localRoot);
89939
+ const rootStat = await stat8(input.localRoot);
89158
89940
  const boundaryRoot = rootStat.isFile() ? dirname29(input.localRoot) : input.localRoot;
89159
89941
  const bySnapshotPath = new Map;
89160
89942
  for (const file of input.files) {
@@ -89173,7 +89955,7 @@ async function readLinkedCaptureAssets(input) {
89173
89955
  }
89174
89956
  let bytes;
89175
89957
  try {
89176
- const assetStat = await stat7(absolutePath);
89958
+ const assetStat = await stat8(absolutePath);
89177
89959
  if (!assetStat.isFile())
89178
89960
  throw new TypeError("asset target is not a file");
89179
89961
  bytes = await readFile57(absolutePath);
@@ -96967,7 +97749,7 @@ async function readRouteMetadataFiles(input) {
96967
97749
  }
96968
97750
 
96969
97751
  // src/project/documentSiteDetection.ts
96970
- import { readdir as readdir15, stat as stat8 } from "node:fs/promises";
97752
+ import { readdir as readdir15, stat as stat9 } from "node:fs/promises";
96971
97753
  import { basename as basename7, extname as extname11, join as join68, relative as relative21, resolve as resolve22 } from "node:path";
96972
97754
  var SKIPPED_DIRS = new Set([
96973
97755
  ".cache",
@@ -97018,7 +97800,7 @@ async function detectDocumentSiteFiles(input) {
97018
97800
  const result = emptyDetection();
97019
97801
  let rootStats;
97020
97802
  try {
97021
- rootStats = await stat8(localRoot);
97803
+ rootStats = await stat9(localRoot);
97022
97804
  } catch {
97023
97805
  return result;
97024
97806
  }
@@ -97222,7 +98004,7 @@ function assignFlatSnapshotPaths(files, module) {
97222
98004
  });
97223
98005
  }
97224
98006
  async function walkMarkdownFiles(input) {
97225
- const rootStat = await stat9(input.localRoot);
98007
+ const rootStat = await stat10(input.localRoot);
97226
98008
  if (rootStat.isFile()) {
97227
98009
  const sourcePath = normalizeSnapshotRelativePath(basename8(input.localRoot));
97228
98010
  return {
@@ -97349,13 +98131,13 @@ async function removeEmptySnapshotDirs(root, dir = root) {
97349
98131
  return;
97350
98132
  const remaining = await readdir16(dir);
97351
98133
  if (remaining.length === 0) {
97352
- await rm16(dir, { recursive: true, force: true });
98134
+ await rm17(dir, { recursive: true, force: true });
97353
98135
  }
97354
98136
  }
97355
98137
  async function cleanupStaleSnapshotFiles(input) {
97356
98138
  for (const path2 of input.previousPaths) {
97357
98139
  if (!input.currentPaths.has(path2)) {
97358
- await rm16(join72(input.materializedAtAbsPath, path2), { force: true });
98140
+ await rm17(join72(input.materializedAtAbsPath, path2), { force: true });
97359
98141
  }
97360
98142
  }
97361
98143
  await removeEmptySnapshotDirs(input.materializedAtAbsPath);
@@ -97728,7 +98510,7 @@ init_cliFeedback();
97728
98510
  init_errors3();
97729
98511
  init_exitCode();
97730
98512
  import { existsSync as existsSync21 } from "node:fs";
97731
- import { lstat as lstat8, mkdir as mkdir27, readFile as readFile62, readlink, realpath as realpath7, rm as rm17, symlink as symlink2 } from "node:fs/promises";
98513
+ import { lstat as lstat8, mkdir as mkdir27, readFile as readFile62, readlink, realpath as realpath7, rm as rm18, symlink as symlink2 } from "node:fs/promises";
97732
98514
  import { execFile as execFile8 } from "node:child_process";
97733
98515
  import { promisify as promisify8 } from "node:util";
97734
98516
  import { dirname as dirname33, isAbsolute as isAbsolute14, join as join76, relative as relative23, resolve as resolve26 } from "node:path";
@@ -97839,7 +98621,7 @@ init_cliFeedback();
97839
98621
  init_errors3();
97840
98622
  init_exitCode();
97841
98623
  init_atomicWrite();
97842
- var import_yaml36 = __toESM(require_dist(), 1);
98624
+ var import_yaml37 = __toESM(require_dist(), 1);
97843
98625
  import { existsSync as existsSync20 } from "node:fs";
97844
98626
  import { join as join75 } from "node:path";
97845
98627
  var SOURCE_NAME_PATTERN2 = /^[a-z0-9][a-z0-9._-]*$/u;
@@ -97916,7 +98698,7 @@ async function writeRepoRegistry(projectRoot, registry2) {
97916
98698
  modules.push(registryRecordToYaml(record4));
97917
98699
  namespaces.set(record4.namespace, modules);
97918
98700
  }
97919
- await atomicWriteFile(path2, import_yaml36.default.stringify({
98701
+ await atomicWriteFile(path2, import_yaml37.default.stringify({
97920
98702
  sources: [...namespaces].map(([name3, modules]) => ({ name: name3, modules }))
97921
98703
  }));
97922
98704
  }
@@ -98082,7 +98864,7 @@ async function ensureMaterializedSymlink(input) {
98082
98864
  const currentAbs = resolve26(dirname33(linkPath), current2);
98083
98865
  if (currentAbs === input.localAbs)
98084
98866
  return true;
98085
- await rm17(linkPath);
98867
+ await rm18(linkPath);
98086
98868
  }
98087
98869
  const relTarget = relative23(dirname33(linkPath), input.localAbs) || ".";
98088
98870
  await symlink2(relTarget, linkPath);
@@ -98479,7 +99261,7 @@ init_errors3();
98479
99261
  init_exitCode();
98480
99262
  init_approvedKnowledgeMetadata();
98481
99263
  init_knowledgeAssets();
98482
- var import_yaml37 = __toESM(require_dist(), 1);
99264
+ var import_yaml38 = __toESM(require_dist(), 1);
98483
99265
  import { createHash as createHash22 } from "node:crypto";
98484
99266
  import { mkdir as mkdir28, writeFile as writeFile21 } from "node:fs/promises";
98485
99267
  import { dirname as dirname34, join as join77 } from "node:path";
@@ -98553,7 +99335,7 @@ async function buildApprovedArticleIndex(projectRoot) {
98553
99335
  const block = frontmatterBlock(content3);
98554
99336
  if (block === null)
98555
99337
  continue;
98556
- const parsed = import_yaml37.default.parse(block.yaml);
99338
+ const parsed = import_yaml38.default.parse(block.yaml);
98557
99339
  if (!isRecord14(parsed))
98558
99340
  continue;
98559
99341
  const frontmatter2 = hydrateApprovedFrontmatter({
@@ -98600,13 +99382,13 @@ function updateFrontmatter(content3, mutate) {
98600
99382
  next: "Fix approved Markdown frontmatter before running this review maintenance command."
98601
99383
  });
98602
99384
  }
98603
- const parsed = import_yaml37.default.parse(block.yaml);
99385
+ const parsed = import_yaml38.default.parse(block.yaml);
98604
99386
  if (!isRecord14(parsed)) {
98605
99387
  throw new ContextError(ExitCode.WorkspaceStateError, "approved page frontmatter must be a YAML object", {
98606
99388
  category: ErrorCategory.SchemaInvalid
98607
99389
  });
98608
99390
  }
98609
- const yaml3 = import_yaml37.default.stringify(mutate(parsed)).trimEnd();
99391
+ const yaml3 = import_yaml38.default.stringify(mutate(parsed)).trimEnd();
98610
99392
  return `---
98611
99393
  ${yaml3}
98612
99394
  ---${content3.slice(block.end)}`;
@@ -105437,76 +106219,12 @@ init_errors3();
105437
106219
  init_exitCode();
105438
106220
  init_candidateLedger();
105439
106221
  init_writeLock();
106222
+ init_reviewApplyIndexer();
106223
+ init_approvedKnowledgeSnapshots();
105440
106224
  import { existsSync as existsSync25 } from "node:fs";
105441
106225
  import { readFile as readFile69 } from "node:fs/promises";
105442
106226
  import { join as join91 } from "node:path";
105443
106227
 
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
106228
  // src/project/reviewCandidateAuthority.ts
105511
106229
  init_src2();
105512
106230
  init_approvedRevision();
@@ -105550,12 +106268,13 @@ async function readProductionReviewCandidates(projectRoot) {
105550
106268
  init_productionFeedback();
105551
106269
  async function loadReviewCandidateAuthority(projectRoot) {
105552
106270
  return withProductionFeedback({ operation: "review" }, async () => {
105553
- const production = await readProductionReviewCandidates(projectRoot);
105554
- if (production)
105555
- return new Map(production.candidates.map((candidate) => [candidate.candidate_id, candidate]));
105556
106271
  const revision = await readApprovedRevision(projectRoot);
105557
- if (!revision)
106272
+ if (!revision) {
106273
+ const production = await readProductionReviewCandidates(projectRoot);
106274
+ if (production)
106275
+ return new Map(production.candidates.map((candidate) => [candidate.candidate_id, candidate]));
105558
106276
  throw new TypeError("No current production or article revision is available for Review");
106277
+ }
105559
106278
  if (!revision.review_ready && !revision.candidate)
105560
106279
  throw new TypeError("Complete the current article revision before Review");
105561
106280
  const observed = await observeApprovedRevisionBatch(projectRoot, revision);
@@ -105604,7 +106323,7 @@ async function prepareApprovedPage(input) {
105604
106323
  const relPath = join91("knowledge", input.record.path);
105605
106324
  const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
105606
106325
  const previousPath = input.record.approved_revision?.previous_path;
105607
- if (previousPath !== undefined && !isSafeKnowledgeTargetPath(input.record.collection, previousPath))
106326
+ if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
105608
106327
  throw new TypeError("Unsafe original page path in a move");
105609
106328
  if (existingView !== undefined && existingView.relPath !== relPath && existingView.relPath !== (previousPath === undefined ? undefined : `knowledge/${previousPath}`)) {
105610
106329
  throw new ContextError(ExitCode.WorkspaceStateError, `approved page already exists for view_ref at a different path: ${input.record.article_id}`, {
@@ -107326,22 +108045,52 @@ function requireProjectRoot2() {
107326
108045
  }
107327
108046
  function registerDocumentRevisionCommand(program2) {
107328
108047
  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) => {
108048
+ 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) => {
108049
+ const { retireArticles: retireArticles2, articleRetirementSchema: articleRetirementSchema2 } = await Promise.resolve().then(() => (init_articleRetirement(), exports_articleRetirement));
108050
+ if (options.schema) {
108051
+ const { zodToJsonSchema: zodToJsonSchema3 } = await Promise.resolve().then(() => (init_esm(), exports_esm));
108052
+ const { writeSchemaOutput: writeSchemaOutput2, schemaOutputFormat: schemaOutputFormat2 } = await Promise.resolve().then(() => (init_schemaOutput(), exports_schemaOutput));
108053
+ writeSchemaOutput2(zodToJsonSchema3(articleRetirementSchema2), schemaOutputFormat2(options.format));
108054
+ return;
108055
+ }
108056
+ if (options.format !== "json" || !options.input)
108057
+ throw new ContextError(ExitCode.UserError, "Use --input <file> --format json, or --schema.", { category: ErrorCategory.UserInputInvalid });
108058
+ assertActionInputWorkspace(process.cwd(), options.input);
108059
+ const value = await readYamlOrJsonInput({
108060
+ path: options.input,
108061
+ label: "article retirement",
108062
+ missingNext: "Provide reason and targets with exact approved paths and optional replacement paths.",
108063
+ readFailureNext: "Use an input file in this workspace.",
108064
+ parseFailureNext: "Provide valid YAML or JSON."
108065
+ });
108066
+ const result = await retireArticles2({
108067
+ projectRoot: requireProjectRoot2(),
108068
+ value,
108069
+ ...options.apply ? { apply: true } : {},
108070
+ ...options.planDigest ? { plan_digest: options.planDigest } : {}
108071
+ });
108072
+ if (result.action === "preview" && result.blockers.length === 0)
108073
+ result.next_action.command = `context task retire --input '${options.input.replace(/'/gu, "'\\''")}' --apply --plan-digest '${result.revision}' --format json`;
108074
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
108075
+ `);
108076
+ });
108077
+ 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
108078
  if (options.format !== "json")
107331
108079
  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.");
108080
+ if (!["inspect", "writer-lock", "transactions"].includes(options.operation))
108081
+ 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
108082
  if (options.operation === "inspect" && options.apply)
107335
108083
  throw new TypeError("Inspection is read-only; select a recovery operation to apply.");
107336
108084
  const projectRoot = requireProjectRoot2();
107337
108085
  const { inspectTaskRecovery: inspectTaskRecovery2, recoverTaskTransactions: recoverTaskTransactions2 } = await Promise.resolve().then(() => (init_taskRecovery(), exports_taskRecovery));
108086
+ const { recoverWriterLock: recoverWriterLock2 } = await Promise.resolve().then(() => (init_writeLockRecovery(), exports_writeLockRecovery));
107338
108087
  const base = {
107339
108088
  projectRoot,
107340
108089
  ...options.apply ? { apply: true } : {},
107341
108090
  ...options.planDigest ? { plan_digest: options.planDigest } : {}
107342
108091
  };
107343
108092
  try {
107344
- const result = options.operation === "inspect" ? await inspectTaskRecovery2(projectRoot) : await recoverTaskTransactions2(base);
108093
+ const result = options.operation === "inspect" ? await inspectTaskRecovery2(projectRoot) : options.operation === "writer-lock" ? await recoverWriterLock2(base) : await recoverTaskTransactions2(base);
107345
108094
  process.stdout.write(`${JSON.stringify(result, null, 2)}
107346
108095
  `);
107347
108096
  } catch (error) {
@@ -107408,9 +108157,19 @@ function registerDocumentRevisionCommand(program2) {
107408
108157
  process.stdout.write(`${JSON.stringify(await cancelKnowledgeMaintenance2(requireProjectRoot2(), id3, options.discardRevision))}
107409
108158
  `);
107410
108159
  });
107411
- task.command("adjust").description("Adjust current source/module inputs or reader organization while preserving unrelated work").requiredOption("--input <file>", "YAML/JSON source scopes with instruction, or knowledge_map; - for stdin").option("--format <format>", "output format: json", "json").action(async (options) => {
107412
- if (options.format !== "json")
107413
- throw new TypeError("--format must be json");
108160
+ task.command("adjust").description("Adjust current source/module inputs or reader organization while preserving unrelated work").option("--input <file>", "YAML/JSON source scopes with instruction, or knowledge_map; - for stdin").option("--schema", "show source adjustment or knowledge map input schema").option("--format <format>", "output format: json", "json").action(async (options) => {
108161
+ if (options.schema) {
108162
+ const { taskSourceAdjustmentSchema: taskSourceAdjustmentSchema2 } = await Promise.resolve().then(() => (init_taskSourceAdjustment(), exports_taskSourceAdjustment));
108163
+ const { zodToJsonSchema: zodToJsonSchema3 } = await Promise.resolve().then(() => (init_esm(), exports_esm));
108164
+ const { writeSchemaOutput: writeSchemaOutput2, schemaOutputFormat: schemaOutputFormat2 } = await Promise.resolve().then(() => (init_schemaOutput(), exports_schemaOutput));
108165
+ writeSchemaOutput2(zodToJsonSchema3(taskSourceAdjustmentSchema2), schemaOutputFormat2(options.format));
108166
+ return;
108167
+ }
108168
+ if (options.format !== "json" || !options.input)
108169
+ throw new ContextError(ExitCode.UserError, "Use --input <file> --format json, or --schema.", {
108170
+ category: ErrorCategory.UserInputInvalid,
108171
+ next_action: { command: "context task adjust --schema --format json" }
108172
+ });
107414
108173
  assertActionInputWorkspace(process.cwd(), options.input);
107415
108174
  const value = await readYamlOrJsonInput({
107416
108175
  path: options.input,
@@ -107465,7 +108224,7 @@ function registerDocumentRevisionCommand(program2) {
107465
108224
  process.stdout.write(`${JSON.stringify(await beginKnowledgeUpdate(requireProjectRoot2(), value), null, 2)}
107466
108225
  `);
107467
108226
  });
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) => {
108227
+ 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
108228
  if (options.format !== "json") {
107470
108229
  throw new ContextError(ExitCode.UserError, "--format must be json", {
107471
108230
  category: ErrorCategory.UserInputInvalid
@@ -107494,8 +108253,8 @@ function registerDocumentRevisionCommand(program2) {
107494
108253
  init_workspace();
107495
108254
  init_workspaceChangelog();
107496
108255
  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) => {
108256
+ const command3 = program2.command("version").description("Inspect formal changes and record a knowledge workspace SemVer and changelog");
108257
+ command3.command("inspect").option("--publish", "include same-version dist changes before publishing").option("--format <format>", "json", "json").action(async (options) => {
107499
108258
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107500
108259
  if (!root2)
107501
108260
  throw new TypeError("Run inside a Context workspace");
@@ -107507,7 +108266,7 @@ function registerVersionCommands(program2) {
107507
108266
  }, null, 2) + `
107508
108267
  `);
107509
108268
  });
107510
- command2.command("publish-check").option("--format <format>", "json", "json").action(async () => {
108269
+ command3.command("publish-check").option("--format <format>", "json", "json").action(async () => {
107511
108270
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107512
108271
  if (!root2)
107513
108272
  throw new TypeError("Run inside a Context workspace");
@@ -107515,7 +108274,7 @@ function registerVersionCommands(program2) {
107515
108274
  process.stdout.write(JSON.stringify(await inspectWorkspacePublish2(root2), null, 2) + `
107516
108275
  `);
107517
108276
  });
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) => {
108277
+ 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
108278
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107520
108279
  if (!root2)
107521
108280
  throw new TypeError("Run inside a Context workspace");
@@ -107523,7 +108282,7 @@ function registerVersionCommands(program2) {
107523
108282
  process.stdout.write(JSON.stringify(await markWorkspacePublished2(root2, options.hash, options.receipt)) + `
107524
108283
  `);
107525
108284
  });
107526
- command2.command("record").requiredOption("--input <file>", "YAML/JSON file or -").option("--format <format>", "json", "json").action(async (options) => {
108285
+ command3.command("record").requiredOption("--input <file>", "YAML/JSON file or -").option("--format <format>", "json", "json").action(async (options) => {
107527
108286
  const root2 = findContextProjectRoot(process.cwd())?.projectRoot;
107528
108287
  if (!root2)
107529
108288
  throw new TypeError("Run inside a Context workspace");
@@ -107641,10 +108400,10 @@ init_actionInputWorkspace();
107641
108400
 
107642
108401
  // src/project/actionCompletionOutput.ts
107643
108402
  init_atomicWrite();
107644
- var import_yaml41 = __toESM(require_dist(), 1);
108403
+ var import_yaml43 = __toESM(require_dist(), 1);
107645
108404
  import { Buffer as Buffer4 } from "node:buffer";
107646
- import { createHash as createHash28 } from "node:crypto";
107647
- import { join as join96 } from "node:path";
108405
+ import { createHash as createHash29 } from "node:crypto";
108406
+ import { join as join97 } from "node:path";
107648
108407
  var INLINE_LIMIT = 16 * 1024;
107649
108408
  function record4(value) {
107650
108409
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
@@ -107657,7 +108416,7 @@ function shortText(value, limit = 400) {
107657
108416
  }
107658
108417
  function serializeActionCompletion(value, format2) {
107659
108418
  return format2 === "json" ? `${JSON.stringify(value, null, 2)}
107660
- ` : import_yaml41.default.stringify(value);
108419
+ ` : import_yaml43.default.stringify(value);
107661
108420
  }
107662
108421
  async function prepareActionCompletionOutput(input) {
107663
108422
  if (input.verbose)
@@ -107669,9 +108428,9 @@ async function prepareActionCompletionOutput(input) {
107669
108428
  const production = typeof result.stage_state === "string";
107670
108429
  if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
107671
108430
  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`);
108431
+ const digest6 = createHash29("sha256").update(full).digest("hex");
108432
+ const root2 = join97(input.projectRoot, ".tmp/context-runtime/action-results");
108433
+ const resultFile = join97(root2, `${digest6}.json`);
107675
108434
  await atomicWriteFile(resultFile, full);
107676
108435
  if (production)
107677
108436
  return {
@@ -107681,10 +108440,10 @@ async function prepareActionCompletionOutput(input) {
107681
108440
  details: resultFile,
107682
108441
  ...pick(result, ["next", "next_preparation"])
107683
108442
  };
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`);
108443
+ const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
108444
+ const nextFile = next2 === undefined ? undefined : join97(root2, `${digest6}.next.json`);
107686
108445
  if (nextFile !== undefined)
107687
- await atomicWriteFile(nextFile, serializeActionCompletion(next, "json"));
108446
+ await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
107688
108447
  const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
107689
108448
  const counts2 = {};
107690
108449
  for (const item of outcomes) {
@@ -107721,12 +108480,12 @@ async function prepareActionCompletionOutput(input) {
107721
108480
  "task_completion",
107722
108481
  "pages"
107723
108482
  ]),
107724
- next_route: next === undefined ? null : {
108483
+ next_route: next2 === undefined ? null : {
107725
108484
  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"])
108485
+ digest: `sha256:${createHash29("sha256").update(serializeActionCompletion(next2, "json")).digest("hex")}`,
108486
+ ...pick(next2, ["revision", "node", "availability"]),
108487
+ commands: next2.commands,
108488
+ gate: next2.gate === undefined ? undefined : pick(record4(next2.gate), ["id", "resolution", "delegatable"])
107730
108489
  },
107731
108490
  ...failure2 === undefined ? {} : { next_preparation: {
107732
108491
  outcome: failure2.outcome,
@@ -107740,7 +108499,7 @@ async function prepareActionCompletionOutput(input) {
107740
108499
  summary.outcomes.pop();
107741
108500
  summary.outcomes_omitted++;
107742
108501
  }
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;
108502
+ 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
108503
  return summary;
107745
108504
  }
107746
108505
 
@@ -107770,34 +108529,34 @@ init_errors3();
107770
108529
  init_cliFeedback();
107771
108530
  init_exitCode();
107772
108531
  init_productionFeedback();
107773
- var import_yaml42 = __toESM(require_dist(), 1);
108532
+ var import_yaml44 = __toESM(require_dist(), 1);
107774
108533
  import { relative as relative24, resolve as resolve32 } from "node:path";
107775
108534
  async function completeCurrentProductionAction(input) {
107776
108535
  return withProductionFeedback({ operation: "action", file: input.submissionPath }, () => withProjectWriteLock(input.projectRoot, "production-action", async () => {
107777
108536
  await recoverDurableMultiFileTransactions(input.projectRoot);
107778
108537
  const stage = await readProductionStage(input.projectRoot);
107779
- const invalid = (message) => new ContextError(ExitCode.UserError, message, {
108538
+ const invalid2 = (message) => new ContextError(ExitCode.UserError, message, {
107780
108539
  category: ErrorCategory.UserInputInvalid,
107781
108540
  reason_code: "invalid-production-submission",
107782
108541
  next_action: { command: "context status --format json" }
107783
108542
  });
107784
108543
  if (!stage)
107785
- throw invalid("The production stage expired. Read the current route; do not restore a previous process.");
108544
+ throw invalid2("The production stage expired. Read the current route; do not restore a previous process.");
107786
108545
  if (input.preview)
107787
- throw invalid("Stage files do not use the retired Author preview. Submit the current task files.");
108546
+ throw invalid2("Stage files do not use the retired Author preview. Submit the current task files.");
107788
108547
  if (!input.submissionPath || input.submissionPath === "-")
107789
- throw invalid("Production requires a stage-local manifest file, not stdin.");
108548
+ throw invalid2("Production requires a stage-local manifest file, not stdin.");
107790
108549
  const path3 = relative24(resolve32(input.projectRoot, productionAgentDirectory(stage.id)), resolve32(input.cwd, input.submissionPath));
107791
108550
  const manifest = await readProductionFile({ projectRoot: input.projectRoot, stage: stage.id, path: path3 });
107792
- const value = import_yaml42.default.parse(manifest.text, { uniqueKeys: true });
108551
+ const value = import_yaml44.default.parse(manifest.text, { uniqueKeys: true });
107793
108552
  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.");
108553
+ throw invalid2("The manifest must identify the current production stage. No tasks were saved.");
107795
108554
  }
107796
108555
  const submission = { projectRoot: input.projectRoot, stage: stage.id, path: path3, manifest, multiAgent: input.multiAgent === true };
107797
108556
  if ("decision" in value)
107798
108557
  return approveProductionReport({ ...submission, revision: input.revision });
107799
108558
  if (input.revision !== stage.id)
107800
- throw invalid("Use the current stage revision; task input handles protect independent submissions.");
108559
+ throw invalid2("Use the current stage revision; task input handles protect independent submissions.");
107801
108560
  if (!stage.planning_complete || "articles" in value)
107802
108561
  return submitProductionPlan(submission);
107803
108562
  return completeProductionSubmission(submission);
@@ -107936,7 +108695,7 @@ init_errors3();
107936
108695
  init_cliFeedback();
107937
108696
  init_exitCode();
107938
108697
  init_productionFeedback();
107939
- var import_yaml43 = __toESM(require_dist(), 1);
108698
+ var import_yaml45 = __toESM(require_dist(), 1);
107940
108699
  import { relative as relative25, resolve as resolve33 } from "node:path";
107941
108700
  var productionKnownTasksSchema = productionPlanInputSchema.omit({ stage: true });
107942
108701
  async function prepareKnownProductionTasks(input) {
@@ -107944,29 +108703,29 @@ async function prepareKnownProductionTasks(input) {
107944
108703
  await recoverDurableMultiFileTransactions(input.projectRoot);
107945
108704
  const path3 = relative25(resolve33(input.projectRoot, ".tmp/agent-work"), resolve33(input.cwd, input.path));
107946
108705
  const fixed2 = await readProductionPlanningFile({ projectRoot: input.projectRoot, path: path3 });
107947
- const invalid = (message) => new ContextError(ExitCode.UserError, message, {
108706
+ const invalid2 = (message) => new ContextError(ExitCode.UserError, message, {
107948
108707
  category: ErrorCategory.UserInputInvalid,
107949
108708
  reason_code: "invalid-known-production-tasks",
107950
108709
  file: input.path,
107951
108710
  input_schema: zodToJsonSchema(productionKnownTasksSchema, { $refStrategy: "none" }),
107952
108711
  next_action: { command: "context status --format json" }
107953
108712
  });
107954
- const plan = productionKnownTasksSchema.parse(import_yaml43.default.parse(fixed2.text, { uniqueKeys: true }));
108713
+ const plan = productionKnownTasksSchema.parse(import_yaml45.default.parse(fixed2.text, { uniqueKeys: true }));
107955
108714
  const request = await productionPlanningRequest(input.projectRoot);
107956
108715
  let stage = await readProductionStage(input.projectRoot);
107957
108716
  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.");
108717
+ throw invalid2("Use known tasks before report approval, with the current preparation revision. Approved stages use ordinary task amendments.");
107959
108718
  }
107960
108719
  if (!stage) {
107961
108720
  await prepareCurrentProductionStage({ projectRoot: input.projectRoot, revision: input.revision });
107962
108721
  stage = await readProductionStage(input.projectRoot);
107963
108722
  }
107964
- const text9 = import_yaml43.default.stringify({ ...plan, stage: stage.id });
108723
+ const text10 = import_yaml45.default.stringify({ ...plan, stage: stage.id });
107965
108724
  const result = await submitProductionPlan({
107966
108725
  projectRoot: input.projectRoot,
107967
108726
  stage: stage.id,
107968
108727
  path: fixed2.path,
107969
- manifest: { path: fixed2.path, text: text9, bytes: Buffer.byteLength(text9), digest: durableContentDigest(text9) }
108728
+ manifest: { path: fixed2.path, text: text10, bytes: Buffer.byteLength(text10), digest: durableContentDigest(text10) }
107970
108729
  });
107971
108730
  return { ...result, next_action: { command: "context status --format json" } };
107972
108731
  }));
@@ -108083,9 +108842,9 @@ function registerProjectActionCommands(program2) {
108083
108842
  // src/commands/cleanClaudePluginCache.ts
108084
108843
  init_cliFeedback();
108085
108844
  import { existsSync as existsSync27 } from "node:fs";
108086
- import { readdir as readdir21, rm as rm19 } from "node:fs/promises";
108845
+ import { readdir as readdir23, rm as rm20 } from "node:fs/promises";
108087
108846
  import { homedir } from "node:os";
108088
- import { join as join97 } from "node:path";
108847
+ import { join as join98 } from "node:path";
108089
108848
  var ORPHAN_MARKER = ".orphaned_at";
108090
108849
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
108091
108850
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -108098,40 +108857,40 @@ async function cleanClaudePluginCache(opts = {}) {
108098
108857
  lines.push("· claude plugin cache: missing — nothing to clean");
108099
108858
  return { lines, removed, scanned };
108100
108859
  }
108101
- const marketplaces = await readdir21(cacheRoot, { withFileTypes: true });
108860
+ const marketplaces = await readdir23(cacheRoot, { withFileTypes: true });
108102
108861
  for (const mp of marketplaces) {
108103
108862
  if (!mp.isDirectory())
108104
108863
  continue;
108105
- const mpDir = join97(cacheRoot, mp.name);
108106
- const plugins = await readdir21(mpDir, { withFileTypes: true });
108864
+ const mpDir = join98(cacheRoot, mp.name);
108865
+ const plugins = await readdir23(mpDir, { withFileTypes: true });
108107
108866
  for (const pl of plugins) {
108108
108867
  if (!pl.isDirectory())
108109
108868
  continue;
108110
- const plDir = join97(mpDir, pl.name);
108111
- const versions = await readdir21(plDir, { withFileTypes: true });
108869
+ const plDir = join98(mpDir, pl.name);
108870
+ const versions = await readdir23(plDir, { withFileTypes: true });
108112
108871
  for (const ver of versions) {
108113
108872
  if (!ver.isDirectory())
108114
108873
  continue;
108115
108874
  scanned += 1;
108116
- const verDir = join97(plDir, ver.name);
108117
- const markerPath = join97(verDir, ORPHAN_MARKER);
108875
+ const verDir = join98(plDir, ver.name);
108876
+ const markerPath = join98(verDir, ORPHAN_MARKER);
108118
108877
  if (!existsSync27(markerPath))
108119
108878
  continue;
108120
108879
  const label2 = `${mp.name}/${pl.name}/${ver.name}`;
108121
108880
  if (opts.dryRun) {
108122
108881
  lines.push(` - would remove: ${label2}`);
108123
108882
  } else {
108124
- await rm19(verDir, { recursive: true, force: true });
108883
+ await rm20(verDir, { recursive: true, force: true });
108125
108884
  removed += 1;
108126
108885
  lines.push(` ✓ removed: ${label2}`);
108127
108886
  }
108128
108887
  }
108129
108888
  if (!opts.dryRun && await isEmptyDir(plDir)) {
108130
- await rm19(plDir, { recursive: true, force: true });
108889
+ await rm20(plDir, { recursive: true, force: true });
108131
108890
  }
108132
108891
  }
108133
108892
  if (!opts.dryRun && await isEmptyDir(mpDir)) {
108134
- await rm19(mpDir, { recursive: true, force: true });
108893
+ await rm20(mpDir, { recursive: true, force: true });
108135
108894
  }
108136
108895
  }
108137
108896
  if (scanned === 0) {
@@ -108146,11 +108905,11 @@ function resolveClaudePluginCacheRoot(opts) {
108146
108905
  if (explicitRoot)
108147
108906
  return explicitRoot;
108148
108907
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
108149
- return join97(home, ".claude", "plugins", "cache");
108908
+ return join98(home, ".claude", "plugins", "cache");
108150
108909
  }
108151
108910
  async function isEmptyDir(dir) {
108152
108911
  try {
108153
- const entries2 = await readdir21(dir);
108912
+ const entries2 = await readdir23(dir);
108154
108913
  return entries2.length === 0;
108155
108914
  } catch {
108156
108915
  return false;
@@ -108178,13 +108937,13 @@ init_exitCode();
108178
108937
 
108179
108938
  // src/lib/packageVersion.ts
108180
108939
  import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
108181
- import { dirname as dirname41, join as join98 } from "node:path";
108940
+ import { dirname as dirname41, join as join99 } from "node:path";
108182
108941
  import { fileURLToPath as fileURLToPath7 } from "node:url";
108183
108942
  function readPackageVersion() {
108184
108943
  try {
108185
108944
  let dir = dirname41(fileURLToPath7(import.meta.url));
108186
108945
  for (let depth = 0;depth < 8; depth += 1) {
108187
- const packagePath = join98(dir, "package.json");
108946
+ const packagePath = join99(dir, "package.json");
108188
108947
  if (existsSync28(packagePath)) {
108189
108948
  const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
108190
108949
  if (typeof parsed.version === "string" && parsed.version.length > 0) {
@@ -108207,12 +108966,12 @@ function readPackageVersion() {
108207
108966
 
108208
108967
  // src/project/sourceCommands.ts
108209
108968
  init_src2();
108210
- import { readFile as readFile84 } from "node:fs/promises";
108969
+ import { readFile as readFile86 } from "node:fs/promises";
108211
108970
  import { isAbsolute as isAbsolute22, resolve as resolve37 } from "node:path";
108212
108971
  init_cliFeedback();
108213
108972
  init_errors3();
108214
108973
  init_exitCode();
108215
- var import_yaml47 = __toESM(require_dist(), 1);
108974
+ var import_yaml49 = __toESM(require_dist(), 1);
108216
108975
 
108217
108976
  // src/project/repoSourceRecovery.ts
108218
108977
  init_cliFeedback();
@@ -108220,7 +108979,7 @@ init_errors3();
108220
108979
  init_exitCode();
108221
108980
  import { execFile as execFile10 } from "node:child_process";
108222
108981
  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";
108982
+ import { lstat as lstat11, mkdir as mkdir33, readlink as readlink2, realpath as realpath8, rm as rm21, symlink as symlink3 } from "node:fs/promises";
108224
108983
  import { basename as basename11, dirname as dirname42, isAbsolute as isAbsolute19, relative as relative26, resolve as resolve34 } from "node:path";
108225
108984
  import { promisify as promisify10 } from "node:util";
108226
108985
  init_writeLock();
@@ -108316,7 +109075,9 @@ async function repositoryRecoveryPlan(input) {
108316
109075
  if (input.source !== undefined && selected.length === 0) {
108317
109076
  throw new ContextError(ExitCode.WorkspaceStateError, `repo source is not registered: ${input.source}`, {
108318
109077
  category: ErrorCategory.SourceNotFound,
108319
- sourceId: input.source
109078
+ sourceId: input.source,
109079
+ registered_names: registry2.repos.map((source2) => source2.name),
109080
+ next_action: { command: "context source recovery-plan --format json" }
108320
109081
  });
108321
109082
  }
108322
109083
  const grouped = new Map;
@@ -108404,19 +109165,19 @@ async function cloneCheckout(input) {
108404
109165
  next: `Use local mode with path ${JSON.stringify(target)} after inspecting the existing checkout.`
108405
109166
  });
108406
109167
  }
108407
- await mkdir32(dirname42(target), { recursive: true });
109168
+ await mkdir33(dirname42(target), { recursive: true });
108408
109169
  const cloneArgs = ["clone", "--no-checkout", "--depth=1", "--filter=blob:none", input.remote, target];
108409
109170
  try {
108410
109171
  await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
108411
109172
  } catch {
108412
- await rm20(target, { recursive: true, force: true });
109173
+ await rm21(target, { recursive: true, force: true });
108413
109174
  try {
108414
109175
  await execFileAsync6("git", ["clone", "--no-checkout", "--depth=1", input.remote, target], {
108415
109176
  encoding: "utf8",
108416
109177
  maxBuffer: 4 * 1024 * 1024
108417
109178
  });
108418
109179
  } catch (error) {
108419
- await rm20(target, { recursive: true, force: true });
109180
+ await rm21(target, { recursive: true, force: true });
108420
109181
  const detail = error !== null && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "").trim() : error instanceof Error ? error.message : String(error);
108421
109182
  throw new ContextError(ExitCode.ExternalToolError, `cannot clone registered repository: ${input.remote}`, {
108422
109183
  category: ErrorCategory.ExternalToolFailed,
@@ -108441,7 +109202,7 @@ async function cloneCheckout(input) {
108441
109202
  await verifyCheckout({ checkout: target, remote: input.remote, ref: input.ref, subpaths: input.subpaths });
108442
109203
  return target;
108443
109204
  } catch (error) {
108444
- await rm20(target, { recursive: true, force: true });
109205
+ await rm21(target, { recursive: true, force: true });
108445
109206
  throw error;
108446
109207
  }
108447
109208
  }
@@ -108450,14 +109211,14 @@ async function bindLocalAlias(input) {
108450
109211
  return;
108451
109212
  const projectRoot = await realpath8(input.projectRoot);
108452
109213
  const alias = resolve34(projectRoot, input.declaredLocal);
108453
- const stats = await lstat10(alias).catch(() => null);
109214
+ const stats = await lstat11(alias).catch(() => null);
108454
109215
  if (stats !== null) {
108455
109216
  if (stats.isSymbolicLink()) {
108456
109217
  const actual = resolve34(dirname42(alias), await readlink2(alias));
108457
109218
  const actualReal = await realpath8(actual).catch(() => null);
108458
109219
  if (actualReal !== null && actualReal === await realpath8(input.checkout))
108459
109220
  return;
108460
- await rm20(alias);
109221
+ await rm21(alias);
108461
109222
  } else {
108462
109223
  const actual = await realpath8(alias);
108463
109224
  if (actual === await realpath8(input.checkout))
@@ -108469,7 +109230,7 @@ async function bindLocalAlias(input) {
108469
109230
  });
108470
109231
  }
108471
109232
  }
108472
- await mkdir32(dirname42(alias), { recursive: true });
109233
+ await mkdir33(dirname42(alias), { recursive: true });
108473
109234
  await symlink3(relative26(dirname42(alias), input.checkout) || ".", alias);
108474
109235
  }
108475
109236
  function selectPhysicalGroup(sources, selector) {
@@ -108548,10 +109309,15 @@ async function restoreRepositorySources(input) {
108548
109309
  }
108549
109310
  if (registryChanged)
108550
109311
  await writeRepoRegistry(input.projectRoot, registry2);
109312
+ const { readProductionStage: readProductionStage2 } = await Promise.resolve().then(() => (init_productionStageStore(), exports_productionStageStore));
109313
+ const stage = await readProductionStage2(input.projectRoot);
109314
+ const restoredScopes = new Set(restored.filter((result) => result.ready).flatMap((result) => result.sources.map((name3) => `repo:${name3}`)));
109315
+ const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
109316
+ const refresh = stage && !stage.delivery && stage.scopes.some((source2) => restoredScopes.has(source2.scope)) && !(await readMaintenance2(input.projectRoot)).active;
108551
109317
  return {
108552
109318
  schema: "context.repository-source-recovery-result.v1",
108553
109319
  restored,
108554
- next_action: { command: "context status --format json" }
109320
+ next_action: { command: refresh ? `context action prepare-current --revision ${stage.id} --format json` : "context status --format json" }
108555
109321
  };
108556
109322
  });
108557
109323
  }
@@ -108559,11 +109325,11 @@ async function restoreRepositorySources(input) {
108559
109325
  // src/project/sourceDocumentStatus.ts
108560
109326
  init_src2();
108561
109327
  import { existsSync as existsSync30 } from "node:fs";
108562
- import { readFile as readFile77 } from "node:fs/promises";
108563
- import { join as join100 } from "node:path";
109328
+ import { readFile as readFile79 } from "node:fs/promises";
109329
+ import { join as join101 } from "node:path";
108564
109330
  // src/project/sourceCommandViews.ts
108565
- import { readFile as readFile76 } from "node:fs/promises";
108566
- import { join as join99 } from "node:path";
109331
+ import { readFile as readFile78 } from "node:fs/promises";
109332
+ import { join as join100 } from "node:path";
108567
109333
  init_workspace();
108568
109334
  init_documentBatchManifest();
108569
109335
  function repoSourceAgentView(source2) {
@@ -108626,7 +109392,7 @@ async function fileSourceAgentViewWithNextAction(input) {
108626
109392
  };
108627
109393
  }
108628
109394
  function documentSourceManifestPath(source2) {
108629
- return source2.snapshot?.manifest ?? join99(source2.materializedAt, "manifest.json");
109395
+ return source2.snapshot?.manifest ?? join100(source2.materializedAt, "manifest.json");
108630
109396
  }
108631
109397
  async function fileSourceDocumentSiteHint(input) {
108632
109398
  const detection = await detectDocumentSiteFiles({
@@ -108636,7 +109402,7 @@ async function fileSourceDocumentSiteHint(input) {
108636
109402
  let snapshotConfigured = false;
108637
109403
  const manifest = documentSourceManifestPath(input.source);
108638
109404
  try {
108639
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile76(join99(input.projectRoot, manifest), "utf8")), input.source.name);
109405
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile78(join100(input.projectRoot, manifest), "utf8")), input.source.name);
108640
109406
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
108641
109407
  } catch {
108642
109408
  snapshotConfigured = false;
@@ -108668,11 +109434,11 @@ async function larkSourceAgentViewWithNextAction(input) {
108668
109434
  // src/project/sourceDocumentStatus.ts
108669
109435
  init_documentBatchManifest();
108670
109436
  function documentSourceManifestPath2(source2) {
108671
- return source2.snapshot?.manifest ?? join100(source2.materializedAt, "manifest.json");
109437
+ return source2.snapshot?.manifest ?? join101(source2.materializedAt, "manifest.json");
108672
109438
  }
108673
109439
  async function documentSnapshotState(input) {
108674
109440
  const manifest = documentSourceManifestPath2(input.source);
108675
- const manifestPath = join100(input.projectRoot, manifest);
109441
+ const manifestPath = join101(input.projectRoot, manifest);
108676
109442
  if (!existsSync30(manifestPath)) {
108677
109443
  return {
108678
109444
  snapshotReady: false,
@@ -108683,7 +109449,7 @@ async function documentSnapshotState(input) {
108683
109449
  };
108684
109450
  }
108685
109451
  try {
108686
- const parsed = findDocumentSnapshotForSource(JSON.parse(await readFile77(manifestPath, "utf8")), input.source.name);
109452
+ const parsed = findDocumentSnapshotForSource(JSON.parse(await readFile79(manifestPath, "utf8")), input.source.name);
108687
109453
  if (parsed === null) {
108688
109454
  return {
108689
109455
  snapshotReady: false,
@@ -108751,7 +109517,7 @@ async function documentSnapshotState(input) {
108751
109517
  const missing = [
108752
109518
  ...parsed.files.map((file) => file.path),
108753
109519
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
108754
- ].find((path3) => !existsSync30(join100(input.projectRoot, input.source.materializedAt, path3)));
109520
+ ].find((path3) => !existsSync30(join101(input.projectRoot, input.source.materializedAt, path3)));
108755
109521
  if (missing !== undefined) {
108756
109522
  return {
108757
109523
  snapshotReady: false,
@@ -108850,10 +109616,10 @@ init_atomicWrite();
108850
109616
  init_cliFeedback();
108851
109617
  init_errors3();
108852
109618
  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";
109619
+ var import_yaml46 = __toESM(require_dist(), 1);
109620
+ import { createHash as createHash30 } from "node:crypto";
109621
+ import { readFile as readFile80, realpath as realpath9 } from "node:fs/promises";
109622
+ import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join102, relative as relative27, resolve as resolve35 } from "node:path";
108857
109623
  init_writeLock();
108858
109624
  var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
108859
109625
  function isDateSourceNamespace(value) {
@@ -108882,7 +109648,7 @@ function defaultLarkModule(input) {
108882
109648
  if (titleSlug.length > 0)
108883
109649
  return titleSlug;
108884
109650
  }
108885
- const opaqueSlug = (kind, identity) => `${kind}-${createHash29("sha256").update(identity).digest("hex").slice(0, 12)}`;
109651
+ const opaqueSlug = (kind, identity) => `${kind}-${createHash30("sha256").update(identity).digest("hex").slice(0, 12)}`;
108886
109652
  if (input.url !== undefined) {
108887
109653
  try {
108888
109654
  const parsed = new URL(input.url);
@@ -108949,8 +109715,8 @@ function assertSafeFileInclude(value) {
108949
109715
  }
108950
109716
  async function readRegistryDocument(projectRoot, registryPath2) {
108951
109717
  try {
108952
- const content3 = await readFile78(join101(projectRoot, registryPath2), "utf8");
108953
- return content3.trim().length === 0 ? { sources: [] } : import_yaml44.default.parse(content3);
109718
+ const content3 = await readFile80(join102(projectRoot, registryPath2), "utf8");
109719
+ return content3.trim().length === 0 ? { sources: [] } : import_yaml46.default.parse(content3);
108954
109720
  } catch (error) {
108955
109721
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
108956
109722
  return { sources: [] };
@@ -109067,7 +109833,7 @@ async function addFileSourceUnlocked(input) {
109067
109833
  const record6 = entry2;
109068
109834
  return record6.name !== input.name && record6.id !== input.name;
109069
109835
  }), nextEntry];
109070
- await atomicWriteFile(join101(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml44.default.stringify({ sources: nextSources }));
109836
+ await atomicWriteFile(join102(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml46.default.stringify({ sources: nextSources }));
109071
109837
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
109072
109838
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
109073
109839
  if (entry === undefined) {
@@ -109123,7 +109889,7 @@ async function addLarkSourceUnlocked(input) {
109123
109889
  const record6 = entry2;
109124
109890
  return record6.name !== input.name && record6.id !== input.name;
109125
109891
  }), nextEntry];
109126
- await atomicWriteFile(join101(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml44.default.stringify({ sources: nextSources }));
109892
+ await atomicWriteFile(join102(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml46.default.stringify({ sources: nextSources }));
109127
109893
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
109128
109894
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
109129
109895
  if (entry === undefined) {
@@ -109323,11 +110089,11 @@ init_candidateLedger();
109323
110089
  init_documentBatchManifest();
109324
110090
  init_workspace();
109325
110091
  init_writeLock();
109326
- var import_yaml45 = __toESM(require_dist(), 1);
110092
+ var import_yaml47 = __toESM(require_dist(), 1);
109327
110093
  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";
110094
+ import { createHash as createHash31 } from "node:crypto";
110095
+ import { readFile as readFile81, readdir as readdir24, rm as rm22 } from "node:fs/promises";
110096
+ import { isAbsolute as isAbsolute21, join as join103, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
109331
110097
  function sourceIdentity(source2) {
109332
110098
  if (source2.kind === "source.collection")
109333
110099
  return;
@@ -109359,10 +110125,10 @@ function collectStrings(value, output) {
109359
110125
  }
109360
110126
  }
109361
110127
  async function yamlReferences(input) {
109362
- const absolutePath = join102(input.projectRoot, input.path);
110128
+ const absolutePath = join103(input.projectRoot, input.path);
109363
110129
  if (!existsSync31(absolutePath))
109364
110130
  return false;
109365
- const parsed = import_yaml45.default.parse(await readFile79(absolutePath, "utf8"));
110131
+ const parsed = import_yaml47.default.parse(await readFile81(absolutePath, "utf8"));
109366
110132
  const strings = [];
109367
110133
  collectStrings(parsed, strings);
109368
110134
  return strings.some((value) => stringReferencesSource(value, input.source));
@@ -109488,11 +110254,11 @@ async function registryRemovalWrite(projectRoot, source2) {
109488
110254
  const path3 = registryPath2(source2.type);
109489
110255
  if (path3 === null)
109490
110256
  return;
109491
- const absolutePath = join102(projectRoot, path3);
109492
- const document4 = existsSync31(absolutePath) ? import_yaml45.default.parse(await readFile79(absolutePath, "utf8")) : { sources: [] };
110257
+ const absolutePath = join103(projectRoot, path3);
110258
+ const document4 = existsSync31(absolutePath) ? import_yaml47.default.parse(await readFile81(absolutePath, "utf8")) : { sources: [] };
109493
110259
  return {
109494
110260
  path: absolutePath,
109495
- bytes: import_yaml45.default.stringify(removeDocumentEntry(document4, source2))
110261
+ bytes: import_yaml47.default.stringify(removeDocumentEntry(document4, source2))
109496
110262
  };
109497
110263
  }
109498
110264
  function safeManagedMaterializedPath(projectRoot, source2) {
@@ -109507,7 +110273,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
109507
110273
  return absolute;
109508
110274
  }
109509
110275
  function safeManagedManifestPath(projectRoot, source2) {
109510
- const manifest = source2.manifest ?? join102(source2.materializedAt, "manifest.json");
110276
+ const manifest = source2.manifest ?? join103(source2.materializedAt, "manifest.json");
109511
110277
  if (isAbsolute21(manifest))
109512
110278
  throw unsafeOwnership(source2, manifest);
109513
110279
  const absolute = resolve36(projectRoot, manifest);
@@ -109542,7 +110308,7 @@ function projectRelative(projectRoot, path3) {
109542
110308
  return relative28(projectRoot, path3).split(sep8).join("/");
109543
110309
  }
109544
110310
  function digest6(value) {
109545
- return `sha256:${createHash30("sha256").update(JSON.stringify(value)).digest("hex")}`;
110311
+ return `sha256:${createHash31("sha256").update(JSON.stringify(value)).digest("hex")}`;
109546
110312
  }
109547
110313
  async function sharedMaterializedOwners(projectRoot, source2) {
109548
110314
  const target = safeManagedMaterializedPath(projectRoot, source2);
@@ -109636,12 +110402,12 @@ async function createRemovalPlan(projectRoot, selector) {
109636
110402
  source: source2,
109637
110403
  registry: registryPath2(source2.type),
109638
110404
  registryBytes: registryWrite?.bytes ?? null,
109639
- managedBytes: source2.type === "note" || source2.type === "sessions" ? await readFile79(absoluteRemovals[0], "utf8") : null,
110405
+ managedBytes: source2.type === "note" || source2.type === "sessions" ? await readFile81(absoluteRemovals[0], "utf8") : null,
109640
110406
  references,
109641
110407
  cleanup,
109642
110408
  manifestBytes: manifestWrite?.bytes ?? null
109643
110409
  });
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`;
110410
+ 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
110411
  return {
109646
110412
  action: "preview",
109647
110413
  source: source2,
@@ -109650,7 +110416,7 @@ async function createRemovalPlan(projectRoot, selector) {
109650
110416
  references,
109651
110417
  plan_digest: planDigest,
109652
110418
  cleanup,
109653
- next,
110419
+ next: next2,
109654
110420
  ...registryWrite === undefined ? {} : { registryWrite },
109655
110421
  ...manifestWrite !== undefined ? { manifestWrite } : {},
109656
110422
  absoluteRemovals: [...new Set(absoluteRemovals)].sort()
@@ -109669,12 +110435,12 @@ function publicRemovalResult(plan, action) {
109669
110435
  };
109670
110436
  }
109671
110437
  async function pruneExtractRuntime(projectRoot, source2) {
109672
- const fingerprintPath = join102(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
110438
+ const fingerprintPath = join103(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
109673
110439
  const removedPhaseIds = new Set;
109674
110440
  if (existsSync31(fingerprintPath)) {
109675
- const parsed = JSON.parse(await readFile79(fingerprintPath, "utf8"));
110441
+ const parsed = JSON.parse(await readFile81(fingerprintPath, "utf8"));
109676
110442
  const phases = parsed.phases ?? {};
109677
- const next = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
110443
+ const next2 = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
109678
110444
  if (raw === null || typeof raw !== "object" || Array.isArray(raw))
109679
110445
  return true;
109680
110446
  const sources = raw.sources;
@@ -109683,30 +110449,30 @@ async function pruneExtractRuntime(projectRoot, source2) {
109683
110449
  removedPhaseIds.add(phaseId);
109684
110450
  return keep;
109685
110451
  }));
109686
- await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next }, null, 2)}
110452
+ await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
109687
110453
  `);
109688
110454
  }
109689
- const phaseOwnershipPath = join102(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
110455
+ const phaseOwnershipPath = join103(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
109690
110456
  if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
109691
- const parsed = JSON.parse(await readFile79(phaseOwnershipPath, "utf8"));
110457
+ const parsed = JSON.parse(await readFile81(phaseOwnershipPath, "utf8"));
109692
110458
  const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
109693
110459
  await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
109694
110460
  `);
109695
110461
  }
109696
- const symbolPath = join102(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
110462
+ const symbolPath = join103(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
109697
110463
  if (existsSync31(symbolPath)) {
109698
- const parsed = JSON.parse(await readFile79(symbolPath, "utf8"));
110464
+ const parsed = JSON.parse(await readFile81(symbolPath, "utf8"));
109699
110465
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
109700
110466
  const phaseFingerprints = Object.fromEntries(Object.entries(parsed.phaseFingerprints ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
109701
110467
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
109702
110468
  `);
109703
110469
  }
109704
- const snapshotRoot = join102(projectRoot, ".tmp/context-runtime/extract/candidates");
110470
+ const snapshotRoot = join103(projectRoot, ".tmp/context-runtime/extract/candidates");
109705
110471
  const visit4 = async (directory) => {
109706
110472
  if (!existsSync31(directory))
109707
110473
  return;
109708
- for (const entry of await readdir22(directory, { withFileTypes: true })) {
109709
- const path3 = join102(directory, entry.name);
110474
+ for (const entry of await readdir24(directory, { withFileTypes: true })) {
110475
+ const path3 = join103(directory, entry.name);
109710
110476
  if (entry.isDirectory()) {
109711
110477
  await visit4(path3);
109712
110478
  continue;
@@ -109714,10 +110480,10 @@ async function pruneExtractRuntime(projectRoot, source2) {
109714
110480
  if (!entry.isFile() || !entry.name.endsWith(".json"))
109715
110481
  continue;
109716
110482
  try {
109717
- const parsed = JSON.parse(await readFile79(path3, "utf8"));
110483
+ const parsed = JSON.parse(await readFile81(path3, "utf8"));
109718
110484
  const refs = Array.isArray(parsed.source_refs) ? parsed.source_refs : [];
109719
110485
  if (parsed.source === source2.name || refs.some((ref2) => typeof ref2 === "string" && stringReferencesSource(ref2, source2))) {
109720
- await rm21(path3, { force: true });
110486
+ await rm22(path3, { force: true });
109721
110487
  }
109722
110488
  } catch {}
109723
110489
  }
@@ -109756,7 +110522,7 @@ async function removeProjectSource(input) {
109756
110522
  });
109757
110523
  }
109758
110524
  await applyAtomicFileBatch({
109759
- transactionRoot: join102(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
110525
+ transactionRoot: join103(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
109760
110526
  writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
109761
110527
  removals: plan.absoluteRemovals
109762
110528
  });
@@ -109772,11 +110538,11 @@ init_workspace();
109772
110538
  init_writeLock();
109773
110539
  init_durableMultiFileTransaction();
109774
110540
  init_durableSingleFileTransaction();
109775
- import { readFile as readFile80 } from "node:fs/promises";
110541
+ import { readFile as readFile82 } from "node:fs/promises";
109776
110542
  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))
110543
+ function generateSourceConfiguration(text10, selected) {
110544
+ const file = ts.createSourceFile("index.ts", text10, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
110545
+ if (ts.transpileModule(text10, { reportDiagnostics: true }).diagnostics?.some((item) => item.category === ts.DiagnosticCategory.Error))
109780
110546
  return;
109781
110547
  const imports = file.statements.filter(ts.isImportDeclaration).filter((node3) => ts.isStringLiteral(node3.moduleSpecifier) && node3.moduleSpecifier.text === "@c4a/context");
109782
110548
  if (imports.length !== 1)
@@ -109887,7 +110653,7 @@ function generateSourceConfiguration(text9, selected) {
109887
110653
  }
109888
110654
  }
109889
110655
  if (!additions.length && !captures.length)
109890
- return text9;
110656
+ return text10;
109891
110657
  const identifiers = new Set;
109892
110658
  const visit4 = (node3) => {
109893
110659
  if (ts.isIdentifier(node3))
@@ -109907,12 +110673,12 @@ function generateSourceConfiguration(text9, selected) {
109907
110673
  }
109908
110674
  if (needed.size)
109909
110675
  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);
110676
+ 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
110677
  }
109912
110678
  async function configureRegisteredSources(projectRoot, selected) {
109913
110679
  return withProjectWriteLock(projectRoot, "source-project-configuration", async () => {
109914
110680
  const path3 = "src/index.ts";
109915
- const config = JSON.parse(await readFile80(await safeProjectTarget(projectRoot, "package.json"), "utf8"));
110681
+ const config = JSON.parse(await readFile82(await safeProjectTarget(projectRoot, "package.json"), "utf8"));
109916
110682
  if (config.context?.entry !== path3)
109917
110683
  return {
109918
110684
  status: "manual",
@@ -109921,8 +110687,8 @@ async function configureRegisteredSources(projectRoot, selected) {
109921
110687
  sources: selected
109922
110688
  };
109923
110689
  const target = await safeProjectTarget(projectRoot, path3);
109924
- const text9 = await readFile80(target, "utf8");
109925
- const updated = generateSourceConfiguration(text9, selected);
110690
+ const text10 = await readFile82(target, "utf8");
110691
+ const updated = generateSourceConfiguration(text10, selected);
109926
110692
  if (updated === undefined)
109927
110693
  return {
109928
110694
  status: "manual",
@@ -109930,15 +110696,15 @@ async function configureRegisteredSources(projectRoot, selected) {
109930
110696
  message: "Registration is saved. Preserve the custom project entry and configure only these sources manually.",
109931
110697
  sources: selected
109932
110698
  };
109933
- if (updated !== text9)
110699
+ if (updated !== text10)
109934
110700
  await runDurableSingleFileTransaction({
109935
110701
  projectRoot,
109936
110702
  kind: "source-project-configuration",
109937
110703
  target_path: path3,
109938
- expected_base_digest: durableContentDigest(text9),
110704
+ expected_base_digest: durableContentDigest(text10),
109939
110705
  target_content: updated
109940
110706
  });
109941
- return { status: updated === text9 ? "unchanged" : "configured", file: path3 };
110707
+ return { status: updated === text10 ? "unchanged" : "configured", file: path3 };
109942
110708
  });
109943
110709
  }
109944
110710
 
@@ -110001,7 +110767,7 @@ async function readIncludeList(projectRoot, path3) {
110001
110767
  }
110002
110768
  let content3;
110003
110769
  try {
110004
- content3 = await readFile84(isAbsolute22(trimmed) ? resolve37(trimmed) : resolve37(projectRoot, trimmed), "utf8");
110770
+ content3 = await readFile86(isAbsolute22(trimmed) ? resolve37(trimmed) : resolve37(projectRoot, trimmed), "utf8");
110005
110771
  } catch (error) {
110006
110772
  throw new ContextError(ExitCode.UserError, `cannot read include list: ${trimmed}`, {
110007
110773
  category: ErrorCategory.UserInputInvalid,
@@ -110042,7 +110808,7 @@ function rowsFromValue(value) {
110042
110808
  return value.map((item) => item && typeof item === "object" && !Array.isArray(item) ? item : { value: item });
110043
110809
  }
110044
110810
  if (value && typeof value === "object") {
110045
- return Object.entries(value).map(([key, next]) => ({ key, value: next }));
110811
+ return Object.entries(value).map(([key, next2]) => ({ key, value: next2 }));
110046
110812
  }
110047
110813
  return [{ value }];
110048
110814
  }
@@ -110069,7 +110835,7 @@ function writeFormatted(value, format2) {
110069
110835
  return;
110070
110836
  }
110071
110837
  if (format2 === "yaml") {
110072
- process.stdout.write(import_yaml47.default.stringify(value));
110838
+ process.stdout.write(import_yaml49.default.stringify(value));
110073
110839
  return;
110074
110840
  }
110075
110841
  process.stdout.write(renderTable2(value));
@@ -110390,16 +111156,16 @@ report shown above. A direct maintenance call outside that Route may omit it.
110390
111156
  init_cliFeedback();
110391
111157
  init_errors3();
110392
111158
  init_exitCode();
110393
- var import_yaml49 = __toESM(require_dist(), 1);
111159
+ var import_yaml51 = __toESM(require_dist(), 1);
110394
111160
 
110395
111161
  // src/project/productionSkillCatalog.ts
110396
111162
  init_errors3();
110397
111163
  init_cliFeedback();
110398
111164
  init_exitCode();
110399
- var import_yaml48 = __toESM(require_dist(), 1);
111165
+ var import_yaml50 = __toESM(require_dist(), 1);
110400
111166
  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";
111167
+ import { lstat as lstat12, open as open5, readdir as readdir25 } from "node:fs/promises";
111168
+ import { dirname as dirname43, join as join105, resolve as resolve38 } from "node:path";
110403
111169
  import { fileURLToPath as fileURLToPath8 } from "node:url";
110404
111170
  function bundledSkillRoot() {
110405
111171
  const directory = dirname43(fileURLToPath8(import.meta.url));
@@ -110426,11 +111192,11 @@ async function listProductionSkills(root2) {
110426
111192
  }
110427
111193
  }
110428
111194
  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);
111195
+ 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
111196
  const skills = [];
110431
111197
  for (const directory of entries2) {
110432
- const entry = join104(root2, directory.name, "SKILL.md");
110433
- if (!(await lstat11(entry)).isFile())
111198
+ const entry = join105(root2, directory.name, "SKILL.md");
111199
+ if (!(await lstat12(entry)).isFile())
110434
111200
  throw new TypeError(`Skill entry must be a regular file: ${entry}`);
110435
111201
  const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
110436
111202
  let header;
@@ -110446,7 +111212,7 @@ async function readProductionSkills(root2) {
110446
111212
  const frontmatter2 = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(header);
110447
111213
  if (!frontmatter2)
110448
111214
  throw new TypeError(`Skill entry needs complete frontmatter within 64 KiB: ${entry}`);
110449
- const value = import_yaml48.default.parse(frontmatter2[1], { uniqueKeys: true });
111215
+ const value = import_yaml50.default.parse(frontmatter2[1], { uniqueKeys: true });
110450
111216
  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
111217
  throw new TypeError(`Skill entry needs a name and description: ${entry}`);
110452
111218
  }
@@ -110509,7 +111275,7 @@ function outputFormat2(options) {
110509
111275
  }
110510
111276
  function writeOutput(value, format2) {
110511
111277
  process.stdout.write(format2 === "json" ? `${JSON.stringify(value, null, 2)}
110512
- ` : import_yaml49.default.stringify(value));
111278
+ ` : import_yaml51.default.stringify(value));
110513
111279
  }
110514
111280
  function registerProjectIndexerCommands(program2) {
110515
111281
  const indexer = program2.command("indexer").description("Discover bundled skills or inspect a benchmark result");
@@ -110593,7 +111359,7 @@ function initCommand2(input, projectDir) {
110593
111359
  return args.map(shellQuote7).join(" ");
110594
111360
  }
110595
111361
  function readyResult(input, projectRoot, relocation) {
110596
- const command2 = workflowCommand(input);
111362
+ const command3 = workflowCommand(input);
110597
111363
  return {
110598
111364
  schema: "context.entry.v1",
110599
111365
  guidance: {
@@ -110610,7 +111376,7 @@ function readyResult(input, projectRoot, relocation) {
110610
111376
  },
110611
111377
  next_action: {
110612
111378
  kind: relocation ? "enter-workspace" : "evaluate-workflow",
110613
- command: relocation ? `cd ${shellQuote7(projectRoot)} && ${command2}` : command2,
111379
+ command: relocation ? `cd ${shellQuote7(projectRoot)} && ${command3}` : command3,
110614
111380
  effect: "read",
110615
111381
  confirmation: "not-required"
110616
111382
  }
@@ -110837,7 +111603,7 @@ init_cliFeedback();
110837
111603
  init_errors3();
110838
111604
  init_exitCode();
110839
111605
  import { existsSync as existsSync35 } from "node:fs";
110840
- import { dirname as dirname46, join as join106, resolve as resolve40 } from "node:path";
111606
+ import { dirname as dirname46, join as join107, resolve as resolve40 } from "node:path";
110841
111607
  import { fileURLToPath as fileURLToPath9 } from "node:url";
110842
111608
 
110843
111609
  // src/project/pluginInstallTargets.ts
@@ -110846,9 +111612,9 @@ init_errors3();
110846
111612
  init_exitCode();
110847
111613
  import { execFile as execFile11 } from "node:child_process";
110848
111614
  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";
111615
+ import { cp as cp2, mkdir as mkdir34, readdir as readdir26, readFile as readFile87, rename as rename8, rm as rm23, writeFile as writeFile25 } from "node:fs/promises";
110850
111616
  import { homedir as homedir2 } from "node:os";
110851
- import { dirname as dirname45, join as join105 } from "node:path";
111617
+ import { dirname as dirname45, join as join106 } from "node:path";
110852
111618
  import { promisify as promisify11 } from "node:util";
110853
111619
  var execFileAsync7 = promisify11(execFile11);
110854
111620
  var MARKETPLACE_NAME = "c4a";
@@ -110864,31 +111630,31 @@ var CURSOR_PLUGIN_ROOT_ENV = "CONTEXT_CURSOR_PLUGIN_ROOT";
110864
111630
  function shellQuote8(value) {
110865
111631
  return `'${value.replace(/'/g, "'\\''")}'`;
110866
111632
  }
110867
- function commandLine(command2, args) {
110868
- return [command2, ...args.map((arg) => shellQuote8(arg))].join(" ");
111633
+ function commandLine(command3, args) {
111634
+ return [command3, ...args.map((arg) => shellQuote8(arg))].join(" ");
110869
111635
  }
110870
- async function runExternal(command2, args) {
111636
+ async function runExternal(command3, args) {
110871
111637
  try {
110872
- await execFileAsync7(command2, args, {
111638
+ await execFileAsync7(command3, args, {
110873
111639
  maxBuffer: 1024 * 1024
110874
111640
  });
110875
111641
  } catch (error) {
110876
111642
  const message = error instanceof Error ? error.message : String(error);
110877
- throw new ContextError(ExitCode.ExternalToolError, `${commandLine(command2, args)} failed: ${message}`, {
111643
+ throw new ContextError(ExitCode.ExternalToolError, `${commandLine(command3, args)} failed: ${message}`, {
110878
111644
  category: ErrorCategory.ExternalToolFailed
110879
111645
  });
110880
111646
  }
110881
111647
  }
110882
- async function runExternalOptional(command2, args) {
111648
+ async function runExternalOptional(command3, args) {
110883
111649
  try {
110884
- await runExternal(command2, args);
111650
+ await runExternal(command3, args);
110885
111651
  return true;
110886
111652
  } catch {
110887
111653
  return false;
110888
111654
  }
110889
111655
  }
110890
- async function commandAvailable(command2) {
110891
- return runExternalOptional("sh", ["-lc", `command -v ${command2} >/dev/null 2>&1`]);
111656
+ async function commandAvailable(command3) {
111657
+ return runExternalOptional("sh", ["-lc", `command -v ${command3} >/dev/null 2>&1`]);
110892
111658
  }
110893
111659
  async function claudePluginInstalled(pluginId) {
110894
111660
  try {
@@ -110902,23 +111668,23 @@ async function claudePluginInstalled(pluginId) {
110902
111668
  }
110903
111669
  }
110904
111670
  function codexHome() {
110905
- return process.env.CODEX_HOME?.trim() || join105(homedir2(), ".codex");
111671
+ return process.env.CODEX_HOME?.trim() || join106(homedir2(), ".codex");
110906
111672
  }
110907
111673
  function claudePluginCacheRoot() {
110908
111674
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
110909
111675
  if (explicitRoot)
110910
111676
  return explicitRoot;
110911
111677
  const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
110912
- return join105(home, ".claude", "plugins", "cache");
111678
+ return join106(home, ".claude", "plugins", "cache");
110913
111679
  }
110914
111680
  function sharedSkillsRoot() {
110915
- return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join105(homedir2(), ".agents", "skills");
111681
+ return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join106(homedir2(), ".agents", "skills");
110916
111682
  }
110917
111683
  function claudeSkillsRoot() {
110918
- return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join105(homedir2(), ".claude", "skills");
111684
+ return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join106(homedir2(), ".claude", "skills");
110919
111685
  }
110920
111686
  function cursorPluginRoot() {
110921
- return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join105(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
111687
+ return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join106(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
110922
111688
  }
110923
111689
  function blockHeader(line) {
110924
111690
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -110929,9 +111695,9 @@ function isStaleMarketplaceBlock(header, block) {
110929
111695
  return true;
110930
111696
  if (header !== `marketplaces.${MARKETPLACE_NAME}`)
110931
111697
  return false;
110932
- const text9 = block.join(`
111698
+ const text10 = block.join(`
110933
111699
  `);
110934
- return text9.includes('source_type = "local"') || text9.includes("/c4a-plugins") || text9.includes("context4ai/context");
111700
+ return text10.includes('source_type = "local"') || text10.includes("/c4a-plugins") || text10.includes("context4ai/context");
110935
111701
  }
110936
111702
  function isStalePluginBlock(header) {
110937
111703
  return header === `plugins."context@context"` || header === `plugins."context@c4a"` || header === "plugins.context";
@@ -110969,27 +111735,27 @@ function pruneLegacyCodexConfigContent(content3) {
110969
111735
  `), removed };
110970
111736
  }
110971
111737
  async function pruneLegacyCodexConfig(dryRun, steps) {
110972
- const configPath = join105(codexHome(), "config.toml");
110973
- const current2 = await readFile85(configPath, "utf8").catch(() => "");
111738
+ const configPath = join106(codexHome(), "config.toml");
111739
+ const current2 = await readFile87(configPath, "utf8").catch(() => "");
110974
111740
  if (!current2)
110975
111741
  return;
110976
- const next = pruneLegacyCodexConfigContent(current2);
110977
- if (next.removed.length === 0)
111742
+ const next2 = pruneLegacyCodexConfigContent(current2);
111743
+ if (next2.removed.length === 0)
110978
111744
  return;
110979
111745
  steps.push({
110980
111746
  agent: "codex",
110981
- command: `prune stale Codex config blocks: ${next.removed.join(", ")}`,
111747
+ command: `prune stale Codex config blocks: ${next2.removed.join(", ")}`,
110982
111748
  status: dryRun ? "planned" : "ran"
110983
111749
  });
110984
111750
  if (!dryRun) {
110985
- await writeFile25(configPath, next.content, "utf8");
111751
+ await writeFile25(configPath, next2.content, "utf8");
110986
111752
  }
110987
111753
  }
110988
111754
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
110989
- const cacheRoot = join105(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
111755
+ const cacheRoot = join106(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
110990
111756
  if (!existsSync34(cacheRoot))
110991
111757
  return;
110992
- const versions = (await readdir24(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
111758
+ const versions = (await readdir26(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
110993
111759
  if (versions.length === 0)
110994
111760
  return;
110995
111761
  steps.push({
@@ -110998,7 +111764,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
110998
111764
  status: dryRun ? "planned" : "ran"
110999
111765
  });
111000
111766
  if (!dryRun)
111001
- await Promise.all(versions.map((version3) => rm22(join105(cacheRoot, version3), { recursive: true, force: true })));
111767
+ await Promise.all(versions.map((version3) => rm23(join106(cacheRoot, version3), { recursive: true, force: true })));
111002
111768
  }
111003
111769
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
111004
111770
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -111008,7 +111774,7 @@ async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
111008
111774
  }
111009
111775
  async function isEmptyDir2(dir) {
111010
111776
  try {
111011
- return (await readdir24(dir)).length === 0;
111777
+ return (await readdir26(dir)).length === 0;
111012
111778
  } catch {
111013
111779
  return false;
111014
111780
  }
@@ -111018,31 +111784,31 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
111018
111784
  if (!existsSync34(cacheRoot))
111019
111785
  return;
111020
111786
  const removed = [];
111021
- const marketplaces = await readdir24(cacheRoot, { withFileTypes: true }).catch(() => []);
111787
+ const marketplaces = await readdir26(cacheRoot, { withFileTypes: true }).catch(() => []);
111022
111788
  for (const marketplace of marketplaces) {
111023
111789
  if (!marketplace.isDirectory())
111024
111790
  continue;
111025
- const pluginDir = join105(cacheRoot, marketplace.name, PLUGIN_NAME);
111791
+ const pluginDir = join106(cacheRoot, marketplace.name, PLUGIN_NAME);
111026
111792
  if (!existsSync34(pluginDir))
111027
111793
  continue;
111028
- const versions = await readdir24(pluginDir, { withFileTypes: true }).catch(() => []);
111794
+ const versions = await readdir26(pluginDir, { withFileTypes: true }).catch(() => []);
111029
111795
  for (const version3 of versions) {
111030
111796
  if (!version3.isDirectory())
111031
111797
  continue;
111032
- const versionDir = join105(pluginDir, version3.name);
111033
- if (!existsSync34(join105(versionDir, ORPHAN_MARKER2)))
111798
+ const versionDir = join106(pluginDir, version3.name);
111799
+ if (!existsSync34(join106(versionDir, ORPHAN_MARKER2)))
111034
111800
  continue;
111035
111801
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
111036
111802
  if (!dryRun) {
111037
- await rm22(versionDir, { recursive: true, force: true });
111803
+ await rm23(versionDir, { recursive: true, force: true });
111038
111804
  }
111039
111805
  }
111040
111806
  if (!dryRun && await isEmptyDir2(pluginDir)) {
111041
- await rm22(pluginDir, { recursive: true, force: true });
111807
+ await rm23(pluginDir, { recursive: true, force: true });
111042
111808
  }
111043
- const marketplaceDir = join105(cacheRoot, marketplace.name);
111809
+ const marketplaceDir = join106(cacheRoot, marketplace.name);
111044
111810
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
111045
- await rm22(marketplaceDir, { recursive: true, force: true });
111811
+ await rm23(marketplaceDir, { recursive: true, force: true });
111046
111812
  }
111047
111813
  }
111048
111814
  if (removed.length > 0) {
@@ -111061,12 +111827,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
111061
111827
  return;
111062
111828
  const removed = [];
111063
111829
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
111064
- const pluginDir = join105(cacheRoot, MARKETPLACE_NAME, pluginName);
111830
+ const pluginDir = join106(cacheRoot, MARKETPLACE_NAME, pluginName);
111065
111831
  if (!existsSync34(pluginDir))
111066
111832
  continue;
111067
111833
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
111068
111834
  if (!dryRun) {
111069
- await rm22(pluginDir, { recursive: true, force: true });
111835
+ await rm23(pluginDir, { recursive: true, force: true });
111070
111836
  }
111071
111837
  }
111072
111838
  if (removed.length > 0) {
@@ -111078,12 +111844,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
111078
111844
  }
111079
111845
  }
111080
111846
  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);
111847
+ const manifest = await readFile87(join106(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
111082
111848
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
111083
111849
  if (!currentVersion)
111084
111850
  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);
111851
+ const pluginDir = join106(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
111852
+ const staleVersions = (await readdir26(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
111087
111853
  if (staleVersions.length === 0)
111088
111854
  return;
111089
111855
  steps.push({
@@ -111092,7 +111858,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
111092
111858
  status: dryRun ? "planned" : "ran"
111093
111859
  });
111094
111860
  if (!dryRun) {
111095
- await Promise.all(staleVersions.map((version3) => rm22(join105(pluginDir, version3), { recursive: true, force: true })));
111861
+ await Promise.all(staleVersions.map((version3) => rm23(join106(pluginDir, version3), { recursive: true, force: true })));
111096
111862
  }
111097
111863
  }
111098
111864
  function enableCodexPluginConfig(content3) {
@@ -111156,56 +111922,56 @@ source = ${JSON.stringify(root2)}
111156
111922
  `;
111157
111923
  }
111158
111924
  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");
111925
+ const configPath = join106(codexHome(), "config.toml");
111926
+ await mkdir34(dirname45(configPath), { recursive: true });
111927
+ const current2 = await readFile87(configPath, "utf8").catch(() => "");
111928
+ const next2 = enableCodexPluginConfig(current2);
111929
+ if (next2 !== current2) {
111930
+ await writeFile25(configPath, next2, "utf8");
111165
111931
  }
111166
111932
  }
111167
111933
  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");
111934
+ const configPath = join106(codexHome(), "config.toml");
111935
+ await mkdir34(dirname45(configPath), { recursive: true });
111936
+ const current2 = await readFile87(configPath, "utf8").catch(() => "");
111937
+ const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
111938
+ if (next2 !== current2) {
111939
+ await writeFile25(configPath, next2, "utf8");
111174
111940
  }
111175
111941
  }
111176
111942
  async function codexPluginVersion(root2) {
111177
- const manifestPath = join105(root2, "codex", ".codex-plugin", "plugin.json");
111178
- const manifest = JSON.parse(await readFile85(manifestPath, "utf8"));
111943
+ const manifestPath = join106(root2, "codex", ".codex-plugin", "plugin.json");
111944
+ const manifest = JSON.parse(await readFile87(manifestPath, "utf8"));
111179
111945
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
111180
111946
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
111181
111947
  }
111182
111948
  return manifest.version;
111183
111949
  }
111184
111950
  function codexPluginCacheDir(version3) {
111185
- return join105(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
111951
+ return join106(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
111186
111952
  }
111187
111953
  async function replaceDirectoryFromSource(source2, target) {
111188
- await mkdir33(dirname45(target), { recursive: true });
111954
+ await mkdir34(dirname45(target), { recursive: true });
111189
111955
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
111190
111956
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
111191
- await rm22(temporary, { recursive: true, force: true });
111957
+ await rm23(temporary, { recursive: true, force: true });
111192
111958
  await cp2(source2, temporary, { recursive: true, force: true });
111193
111959
  const hadPrevious = existsSync34(target);
111194
111960
  try {
111195
111961
  if (hadPrevious)
111196
- await rename7(target, previous3);
111197
- await rename7(temporary, target);
111962
+ await rename8(target, previous3);
111963
+ await rename8(temporary, target);
111198
111964
  if (hadPrevious)
111199
- await rm22(previous3, { recursive: true, force: true });
111965
+ await rm23(previous3, { recursive: true, force: true });
111200
111966
  } catch (error) {
111201
- await rm22(temporary, { recursive: true, force: true });
111967
+ await rm23(temporary, { recursive: true, force: true });
111202
111968
  if (hadPrevious && !existsSync34(target) && existsSync34(previous3))
111203
- await rename7(previous3, target);
111969
+ await rename8(previous3, target);
111204
111970
  throw error;
111205
111971
  }
111206
111972
  }
111207
111973
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
111208
- const source2 = join105(root2, "codex");
111974
+ const source2 = join106(root2, "codex");
111209
111975
  const target = codexPluginCacheDir(version3);
111210
111976
  steps.push({
111211
111977
  agent: "codex",
@@ -111217,16 +111983,16 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
111217
111983
  await replaceDirectoryFromSource(source2, target);
111218
111984
  }
111219
111985
  async function bundledProviderSkillNames(root2) {
111220
- const skillsRoot = join105(root2, "skills");
111221
- const entries2 = await readdir24(skillsRoot, { withFileTypes: true });
111986
+ const skillsRoot = join106(root2, "skills");
111987
+ const entries2 = await readdir26(skillsRoot, { withFileTypes: true });
111222
111988
  const names = [];
111223
111989
  for (const entry of entries2) {
111224
111990
  if (!entry.isDirectory() || entry.name === "context")
111225
111991
  continue;
111226
- const skillPath = join105(skillsRoot, entry.name, "SKILL.md");
111992
+ const skillPath = join106(skillsRoot, entry.name, "SKILL.md");
111227
111993
  if (!existsSync34(skillPath))
111228
111994
  continue;
111229
- const skill = await readFile85(skillPath, "utf8");
111995
+ const skill = await readFile87(skillPath, "utf8");
111230
111996
  if (!/^\s*context-role:\s*["']?indexer-provider["']?\s*$/mu.test(skill))
111231
111997
  continue;
111232
111998
  names.push(entry.name);
@@ -111238,10 +112004,10 @@ async function bundledProviderSkillNames(root2) {
111238
112004
  return names;
111239
112005
  }
111240
112006
  async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
111241
- const sourceRoot2 = join105(root2, "skills");
112007
+ const sourceRoot2 = join106(root2, "skills");
111242
112008
  for (const name3 of await bundledProviderSkillNames(root2)) {
111243
- const source2 = join105(sourceRoot2, name3);
111244
- const target = join105(targetRoot, name3);
112009
+ const source2 = join106(sourceRoot2, name3);
112010
+ const target = join106(targetRoot, name3);
111245
112011
  steps.push({
111246
112012
  agent,
111247
112013
  command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
@@ -111252,7 +112018,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
111252
112018
  }
111253
112019
  }
111254
112020
  async function installCursor(root2, dryRun, steps) {
111255
- const source2 = join105(root2, "cursor");
112021
+ const source2 = join106(root2, "cursor");
111256
112022
  const target = cursorPluginRoot();
111257
112023
  steps.push({
111258
112024
  agent: "cursor",
@@ -111307,12 +112073,12 @@ async function installCodex(root2, dryRun, steps) {
111307
112073
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
111308
112074
  steps.push({
111309
112075
  agent: "codex",
111310
- command: `ensure ${shellQuote8(join105(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
112076
+ command: `ensure ${shellQuote8(join106(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
111311
112077
  status: dryRun ? "planned" : "ran"
111312
112078
  });
111313
112079
  steps.push({
111314
112080
  agent: "codex",
111315
- command: `ensure ${shellQuote8(join105(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
112081
+ command: `ensure ${shellQuote8(join106(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
111316
112082
  status: dryRun ? "planned" : "ran"
111317
112083
  });
111318
112084
  if (dryRun) {
@@ -111367,13 +112133,13 @@ function pluginRootCandidates() {
111367
112133
  return [resolve40(envRoot)];
111368
112134
  const candidates = [];
111369
112135
  for (const dir of packageCandidateDirs()) {
111370
- candidates.push(join106(dir, "plugins"));
111371
- candidates.push(join106(dir, "dist", "plugins"));
112136
+ candidates.push(join107(dir, "plugins"));
112137
+ candidates.push(join107(dir, "dist", "plugins"));
111372
112138
  }
111373
112139
  return [...new Set(candidates)];
111374
112140
  }
111375
112141
  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"));
112142
+ 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
112143
  }
111378
112144
  function resolveBundledPluginsRoot() {
111379
112145
  const candidates = pluginRootCandidates();
@@ -111603,10 +112369,10 @@ function readQuickstartPath() {
111603
112369
  try {
111604
112370
  let dir = dirname47(fileURLToPath10(import.meta.url));
111605
112371
  for (let i2 = 0;i2 < 8; i2++) {
111606
- const candidate = join107(dir, "docs", "quickstart.md");
112372
+ const candidate = join108(dir, "docs", "quickstart.md");
111607
112373
  if (existsSync36(candidate))
111608
112374
  return candidate;
111609
- const pkg = join107(dir, "package.json");
112375
+ const pkg = join108(dir, "package.json");
111610
112376
  if (existsSync36(pkg))
111611
112377
  return candidate;
111612
112378
  const parent = dirname47(dir);
@@ -111615,7 +112381,7 @@ function readQuickstartPath() {
111615
112381
  dir = parent;
111616
112382
  }
111617
112383
  } catch {}
111618
- return join107(dirname47(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
112384
+ return join108(dirname47(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
111619
112385
  }
111620
112386
  var GREEN = "\x1B[32m";
111621
112387
  var RESET = "\x1B[0m";
@@ -111641,7 +112407,7 @@ ${greenBox([
111641
112407
  `;
111642
112408
  }
111643
112409
  function assertKnownTopLevelCommand(argv, program2) {
111644
- const commands = new Set(["help", ...program2.commands.flatMap((command2) => [command2.name(), ...command2.aliases()])]);
112410
+ const commands = new Set(["help", ...program2.commands.flatMap((command3) => [command3.name(), ...command3.aliases()])]);
111645
112411
  for (const token of argv.slice(2)) {
111646
112412
  if (token === "-h" || token === "--help" || token === "-V" || token === "--version")
111647
112413
  return;
@@ -111867,9 +112633,9 @@ async function cli_main(argv = process.argv) {
111867
112633
  await withContextRuntimeEventDelivery(async () => {
111868
112634
  const program2 = createCliProgram();
111869
112635
  assertKnownTopLevelCommand(argv, program2);
111870
- const overrideExit = (command2) => {
111871
- command2.exitOverride();
111872
- command2.commands.forEach(overrideExit);
112636
+ const overrideExit = (command3) => {
112637
+ command3.exitOverride();
112638
+ command3.commands.forEach(overrideExit);
111873
112639
  };
111874
112640
  overrideExit(program2);
111875
112641
  try {