@c4a/context-cli 0.7.20 → 0.7.25

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 (33) hide show
  1. package/README.md +6 -6
  2. package/README.zh-CN.md +6 -6
  3. package/cli.js +667 -651
  4. package/indexers/contracts/profile-contract.json +245 -245
  5. package/indexers/release-manifest.json +1 -1
  6. package/package.json +12 -12
  7. package/plugins/VERSION +1 -1
  8. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  9. package/plugins/claude/commands/context.md +77 -6
  10. package/plugins/codex/.codex-plugin/plugin.json +2 -2
  11. package/plugins/codex/skills/context/SKILL.md +77 -6
  12. package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
  13. package/plugins/cursor/commands/c4a-context.md +77 -6
  14. package/plugins/skills/context/SKILL.md +77 -6
  15. package/providers/context/codes.yaml +1 -1
  16. package/providers/context/graphs/indexer.yaml +11 -7
  17. package/providers/context/graphs/workspace.yaml +5 -0
  18. package/providers/context/manifest.json +30 -30
  19. package/providers/context/provider.yaml +1 -1
  20. package/providers/context/resources/manuals/guides/knowledge-updates.md +5 -1
  21. package/providers/context/resources/manuals/guides/workspace-prepare.md +4 -0
  22. package/providers/context/resources/manuals/guides/workspace-restore.md +5 -1
  23. package/providers/context/resources/procedures/knowledge-review.md +11 -4
  24. package/providers/context/resources/procedures/knowledge-updates.md +5 -1
  25. package/providers/context/resources/procedures/package-output.md +4 -0
  26. package/providers/context/resources/procedures/production-requirements.md +5 -3
  27. package/providers/context/resources/procedures/source-boundary.md +15 -5
  28. package/providers/context/resources/procedures/work-start-report.md +19 -6
  29. package/providers/context/resources/procedures/workspace-prepare.md +4 -0
  30. package/providers/context/resources/procedures/workspace-restore.md +5 -1
  31. package/providers/context/skills/resolve-current-indexer-gate/SKILL.md +7 -2
  32. package/providers/context/skills/run-indexer-lifecycle/SKILL.md +3 -2
  33. package/providers/context/skills/work-production-stage/SKILL.md +5 -3
package/cli.js CHANGED
@@ -76442,12 +76442,22 @@ var init_packageTemplateUtils = __esm(() => {
76442
76442
  TEMPLATE_ENGINE.registerHelper("json", (value) => JSON.stringify(value, null, 2));
76443
76443
  });
76444
76444
 
76445
+ // src/project/packageDistributionMetadata.ts
76446
+ import { join as join15 } from "node:path";
76447
+ function packageDistributionMetadataPath(fileName) {
76448
+ return join15(PACKAGE_DISTRIBUTION_METADATA_DIR, fileName);
76449
+ }
76450
+ var PACKAGE_DISTRIBUTION_METADATA_DIR;
76451
+ var init_packageDistributionMetadata = __esm(() => {
76452
+ PACKAGE_DISTRIBUTION_METADATA_DIR = join15("others", "context");
76453
+ });
76454
+
76445
76455
  // src/project/packageBuildInventory.ts
76446
76456
  import { createHash as createHash9 } from "node:crypto";
76447
76457
  import { mkdir as mkdir12, writeFile as writeFile7 } from "node:fs/promises";
76448
- import { dirname as dirname14, join as join15 } from "node:path";
76458
+ import { dirname as dirname14, join as join16 } from "node:path";
76449
76459
  function knowledgeStructurePath(projectRoot) {
76450
- return join15(projectRoot, "knowledge", "structure.yaml");
76460
+ return join16(projectRoot, "knowledge", "structure.yaml");
76451
76461
  }
76452
76462
  async function readKnowledgeStructure(projectRoot) {
76453
76463
  const snapshot = await reuseCommandFileRead({
@@ -76594,11 +76604,19 @@ function packageBuildInventory(input) {
76594
76604
  };
76595
76605
  }
76596
76606
  async function writePackageBuildInventory(input) {
76597
- const outputPath = join15(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
76598
- await mkdir12(dirname14(outputPath), { recursive: true });
76599
- await writeFile7(outputPath, `${JSON.stringify(input.inventory, null, 2)}
76600
- `, "utf8");
76601
- return 1;
76607
+ const outputPath = join16(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
76608
+ const distributionPath = join16(input.projectRoot, input.pkg.outDir, packageDistributionMetadataPath(PACKAGE_BUILD_INVENTORY_PATH));
76609
+ const content3 = `${JSON.stringify(input.inventory, null, 2)}
76610
+ `;
76611
+ await Promise.all([
76612
+ mkdir12(dirname14(outputPath), { recursive: true }),
76613
+ mkdir12(dirname14(distributionPath), { recursive: true })
76614
+ ]);
76615
+ await Promise.all([
76616
+ writeFile7(outputPath, content3, "utf8"),
76617
+ writeFile7(distributionPath, content3, "utf8")
76618
+ ]);
76619
+ return 2;
76602
76620
  }
76603
76621
  var PACKAGE_BUILD_INVENTORY_PATH = "context-build-inventory.json";
76604
76622
  var init_packageBuildInventory = __esm(() => {
@@ -76609,6 +76627,7 @@ var init_packageBuildInventory = __esm(() => {
76609
76627
  init_packageNavigation();
76610
76628
  init_packageDistribution();
76611
76629
  init_packageTemplateUtils();
76630
+ init_packageDistributionMetadata();
76612
76631
  });
76613
76632
 
76614
76633
  // src/project/codeAnalysisInput.ts
@@ -76763,7 +76782,7 @@ var init_indexerSourceBoundary = __esm(() => {
76763
76782
  import { execFile as execFile3 } from "node:child_process";
76764
76783
  import { lstat as lstat4, readFile as readFile18 } from "node:fs/promises";
76765
76784
  import { promisify as promisify3 } from "node:util";
76766
- import { basename as basename4, extname as extname8, join as join16 } from "node:path";
76785
+ import { basename as basename4, extname as extname8, join as join17 } from "node:path";
76767
76786
  function sourceRefName(sourceRef) {
76768
76787
  return sourceRef.startsWith("repo:") ? sourceRef.slice("repo:".length) : null;
76769
76788
  }
@@ -76800,7 +76819,7 @@ function sourceRoot(input) {
76800
76819
  const source2 = name2 === null ? undefined : input.sources.find((candidate) => candidate.name === name2 || candidate.id === name2);
76801
76820
  if (source2 === undefined)
76802
76821
  throw new TypeError(`parser plan uses unknown source ${input.sourceRef}`);
76803
- return join16(input.projectRoot, source2.materializedAt);
76822
+ return join17(input.projectRoot, source2.materializedAt);
76804
76823
  }
76805
76824
  async function materializeProjectIndexerParserEntryInput(input) {
76806
76825
  const sources = await loadSourcesRegistry({ rootDir: input.projectRoot });
@@ -76896,7 +76915,7 @@ __export(exports_processedScopeStorage, {
76896
76915
  captureProcessedScopes: () => captureProcessedScopes
76897
76916
  });
76898
76917
  import { readFile as readFile20 } from "node:fs/promises";
76899
- import { join as join17 } from "node:path";
76918
+ import { join as join18 } from "node:path";
76900
76919
  async function currentScopeSourceVersion(projectRoot, sourceRef) {
76901
76920
  const sources = await loadSourcesRegistry({ rootDir: projectRoot });
76902
76921
  const split = sourceRef.indexOf(":");
@@ -76913,7 +76932,7 @@ async function currentScopeSourceVersion(projectRoot, sourceRef) {
76913
76932
  const version3 = entries2[0].ref;
76914
76933
  if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(version3))
76915
76934
  throw new TypeError("Processing requires a fixed commit, not a moving ref");
76916
- await assertPinnedSource(join17(projectRoot, entries2[0].materializedAt), version3);
76935
+ await assertPinnedSource(join18(projectRoot, entries2[0].materializedAt), version3);
76917
76936
  return version3;
76918
76937
  }
76919
76938
  const entries = (type === "file" ? sources.files : type === "lark" ? sources.larks : []).filter((entry2) => entry2.id === name2 || entry2.name === name2);
@@ -76921,7 +76940,7 @@ async function currentScopeSourceVersion(projectRoot, sourceRef) {
76921
76940
  throw new TypeError(`Source must identify one registered document: ${sourceRef}`);
76922
76941
  const entry = entries[0];
76923
76942
  const manifest = entry.snapshot?.manifest ?? `${entry.materializedAt}/manifest.json`;
76924
- return parseDocumentSnapshotForSource(JSON.parse(await readFile20(join17(projectRoot, manifest), "utf8")), entry.name).snapshot_hash;
76943
+ return parseDocumentSnapshotForSource(JSON.parse(await readFile20(join18(projectRoot, manifest), "utf8")), entry.name).snapshot_hash;
76925
76944
  }
76926
76945
  async function captureProcessedScopes(projectRoot, requested) {
76927
76946
  const scopes = processedScopesSchema.parse(requested);
@@ -76949,7 +76968,7 @@ async function commitProcessedScopes(projectRoot, scopes) {
76949
76968
  if (structure.parsed === null)
76950
76969
  throw new TypeError("A closed knowledge structure is required before recording processed scopes");
76951
76970
  const processed = mergeProcessedScopes(readProcessedScopes(structure.parsed), scopes);
76952
- await atomicWriteFile(join17(projectRoot, structure.path), import_yaml13.default.stringify({ ...structure.parsed, processed_scopes: processed }));
76971
+ await atomicWriteFile(join18(projectRoot, structure.path), import_yaml13.default.stringify({ ...structure.parsed, processed_scopes: processed }));
76953
76972
  }
76954
76973
  async function invalidateChangedProcessedRequirements(projectRoot, previous2, current2) {
76955
76974
  const targets = new Map(current2.map((requirement2) => [requirement2.id, indexerProtocolDigest(requirement2)]));
@@ -76963,7 +76982,7 @@ async function invalidateChangedProcessedRequirements(projectRoot, previous2, cu
76963
76982
  const retained = scopes.filter((scope2) => !changed.has(scope2.requirement_ref));
76964
76983
  if (retained.length === scopes.length)
76965
76984
  return;
76966
- await atomicWriteFile(join17(projectRoot, structure.path), import_yaml13.default.stringify({ ...structure.parsed, processed_scopes: retained }));
76985
+ await atomicWriteFile(join18(projectRoot, structure.path), import_yaml13.default.stringify({ ...structure.parsed, processed_scopes: retained }));
76967
76986
  }
76968
76987
  var import_yaml13;
76969
76988
  var init_processedScopeStorage = __esm(() => {
@@ -77102,7 +77121,7 @@ __export(exports_approvedRevisionPrograms, {
77102
77121
  });
77103
77122
  import { execFile as execFile4 } from "node:child_process";
77104
77123
  import { promisify as promisify4 } from "node:util";
77105
- import { extname as extname9, join as join18 } from "node:path";
77124
+ import { extname as extname9, join as join19 } from "node:path";
77106
77125
  import { createRequire as createRequire3 } from "node:module";
77107
77126
  import { pathToFileURL } from "node:url";
77108
77127
  async function prepareRevisionProgramBlocks(root, sourceRefs, scopes, references) {
@@ -77118,7 +77137,7 @@ async function prepareRevisionProgramBlocks(root, sourceRefs, scopes, references
77118
77137
  if (entries.length !== 1)
77119
77138
  throw new TypeError(`Regeneration requires one registered source: ${source2}`);
77120
77139
  const entry = entries[0];
77121
- const directory = join18(root, entry.materializedAt);
77140
+ const directory = join19(root, entry.materializedAt);
77122
77141
  const paths = [...new Set(references.filter((reference2) => reference2.source_ref === source2).map((reference2) => reference2.locator.path))];
77123
77142
  if (!paths.length)
77124
77143
  continue;
@@ -77248,14 +77267,14 @@ var init_approvedRevisionEdits = __esm(() => {
77248
77267
  // src/project/articleRegionBaselines.ts
77249
77268
  import { createHash as createHash10 } from "node:crypto";
77250
77269
  import { lstatSync, mkdirSync, readFileSync as readFileSync3, realpathSync, writeFileSync } from "node:fs";
77251
- import { join as join19 } from "node:path";
77270
+ import { join as join20 } from "node:path";
77252
77271
  function baselinePath(root, digest2, create) {
77253
77272
  const hash2 = DIGEST.exec(digest2)?.[1];
77254
77273
  if (!hash2)
77255
77274
  throw new TypeError("Invalid source region digest");
77256
77275
  let path2 = realpathSync(root);
77257
77276
  for (const part of [".tmp", "context-runtime", "source-regions"]) {
77258
- path2 = join19(path2, part);
77277
+ path2 = join20(path2, part);
77259
77278
  if (create) {
77260
77279
  try {
77261
77280
  mkdirSync(path2);
@@ -77274,7 +77293,7 @@ function baselinePath(root, digest2, create) {
77274
77293
  throw error;
77275
77294
  }
77276
77295
  }
77277
- return join19(path2, `${hash2}.txt`);
77296
+ return join20(path2, `${hash2}.txt`);
77278
77297
  }
77279
77298
  function digestOf(text5) {
77280
77299
  return `sha256:${createHash10("sha256").update(text5, "utf8").digest("hex")}`;
@@ -77390,10 +77409,10 @@ __export(exports_maintenanceStorage, {
77390
77409
  APPROVED_REVISION_PATH: () => APPROVED_REVISION_PATH
77391
77410
  });
77392
77411
  import { readFile as readFile21 } from "node:fs/promises";
77393
- import { join as join20 } from "node:path";
77412
+ import { join as join21 } from "node:path";
77394
77413
  async function readMaintenance(root) {
77395
77414
  try {
77396
- return stateSchema.parse(JSON.parse(await readFile21(join20(root, MAINTENANCE_ROOT, "current.json"), "utf8")));
77415
+ return stateSchema.parse(JSON.parse(await readFile21(join21(root, MAINTENANCE_ROOT, "current.json"), "utf8")));
77397
77416
  } catch (error) {
77398
77417
  if (error.code === "ENOENT")
77399
77418
  return { protocol: "context.maintenance/v1", pending: [], completed: [] };
@@ -77401,18 +77420,18 @@ async function readMaintenance(root) {
77401
77420
  }
77402
77421
  }
77403
77422
  function saveMaintenance(root, state) {
77404
- return atomicWriteFile(join20(root, MAINTENANCE_ROOT, "current.json"), `${JSON.stringify(stateSchema.parse(state))}
77423
+ return atomicWriteFile(join21(root, MAINTENANCE_ROOT, "current.json"), `${JSON.stringify(stateSchema.parse(state))}
77405
77424
  `);
77406
77425
  }
77407
77426
  async function revisionStoragePath(root) {
77408
- return (await readMaintenance(root)).active ? join20(MAINTENANCE_ROOT, "revision.json") : APPROVED_REVISION_PATH;
77427
+ return (await readMaintenance(root)).active ? join21(MAINTENANCE_ROOT, "revision.json") : APPROVED_REVISION_PATH;
77409
77428
  }
77410
77429
  var MAINTENANCE_ROOT, APPROVED_REVISION_PATH, targetSchema, maintenanceInputSchema, requestSchema, stateSchema;
77411
77430
  var init_maintenanceStorage = __esm(() => {
77412
77431
  init_zod();
77413
77432
  init_atomicWrite();
77414
- MAINTENANCE_ROOT = join20(".tmp", "context-runtime", "maintenance");
77415
- APPROVED_REVISION_PATH = join20(".tmp", "context-runtime", "revision", "current.json");
77433
+ MAINTENANCE_ROOT = join21(".tmp", "context-runtime", "maintenance");
77434
+ APPROVED_REVISION_PATH = join21(".tmp", "context-runtime", "revision", "current.json");
77416
77435
  targetSchema = exports_external.object({ path: exports_external.string().min(1), instruction: exports_external.string().trim().min(1) }).strict();
77417
77436
  maintenanceInputSchema = exports_external.object({
77418
77437
  id: exports_external.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}$/u),
@@ -77439,24 +77458,24 @@ var init_maintenanceStorage = __esm(() => {
77439
77458
  });
77440
77459
 
77441
77460
  // src/project/lifecyclePaths.ts
77442
- import { join as join21 } from "node:path";
77461
+ import { join as join22 } from "node:path";
77443
77462
  var LIFECYCLE_ROOT, CANDIDATE_LEDGER_FILE, LIFECYCLE_STRUCTURE_FILE, REVIEW_RUNTIME_ROOT, REVIEW_ACTION_ROOT, STRUCTURE_REPORT_ROOT, CANDIDATE_SNAPSHOT_ROOT, INDEXER_RUNTIME_ROOT, INDEXER_WORKSET_VIEW_RUNTIME_ROOT;
77444
77463
  var init_lifecyclePaths = __esm(() => {
77445
- LIFECYCLE_ROOT = join21(".tmp", "context-runtime", "lifecycle");
77446
- CANDIDATE_LEDGER_FILE = join21(LIFECYCLE_ROOT, "candidates.jsonl");
77447
- LIFECYCLE_STRUCTURE_FILE = join21(LIFECYCLE_ROOT, "structure.yaml");
77448
- REVIEW_RUNTIME_ROOT = join21(".tmp", "context-runtime", "review");
77449
- REVIEW_ACTION_ROOT = join21(".tmp", "context-runtime", "review-actions");
77450
- STRUCTURE_REPORT_ROOT = join21(".tmp", "context-runtime", "reports");
77451
- CANDIDATE_SNAPSHOT_ROOT = join21(".tmp", "context-runtime", "extract", "candidates");
77452
- INDEXER_RUNTIME_ROOT = join21(".tmp", "context-runtime", "indexer");
77453
- INDEXER_WORKSET_VIEW_RUNTIME_ROOT = join21(INDEXER_RUNTIME_ROOT, "workset-views");
77464
+ LIFECYCLE_ROOT = join22(".tmp", "context-runtime", "lifecycle");
77465
+ CANDIDATE_LEDGER_FILE = join22(LIFECYCLE_ROOT, "candidates.jsonl");
77466
+ LIFECYCLE_STRUCTURE_FILE = join22(LIFECYCLE_ROOT, "structure.yaml");
77467
+ REVIEW_RUNTIME_ROOT = join22(".tmp", "context-runtime", "review");
77468
+ REVIEW_ACTION_ROOT = join22(".tmp", "context-runtime", "review-actions");
77469
+ STRUCTURE_REPORT_ROOT = join22(".tmp", "context-runtime", "reports");
77470
+ CANDIDATE_SNAPSHOT_ROOT = join22(".tmp", "context-runtime", "extract", "candidates");
77471
+ INDEXER_RUNTIME_ROOT = join22(".tmp", "context-runtime", "indexer");
77472
+ INDEXER_WORKSET_VIEW_RUNTIME_ROOT = join22(INDEXER_RUNTIME_ROOT, "workset-views");
77454
77473
  });
77455
77474
 
77456
77475
  // src/project/candidateLedger.ts
77457
77476
  import { existsSync as existsSync4 } from "node:fs";
77458
77477
  import { mkdir as mkdir13, readFile as readFile22, rm as rm7, writeFile as writeFile8 } from "node:fs/promises";
77459
- import { dirname as dirname16, join as join22 } from "node:path";
77478
+ import { dirname as dirname16, join as join23 } from "node:path";
77460
77479
  function isRecord6(value) {
77461
77480
  return value !== null && typeof value === "object" && !Array.isArray(value);
77462
77481
  }
@@ -77637,7 +77656,7 @@ function parseCandidateLine(line, lineNumber) {
77637
77656
  return parseCandidateRecord(parsed, lineNumber);
77638
77657
  }
77639
77658
  async function readCandidateRecords(projectRoot) {
77640
- const filePath = join22(projectRoot, CANDIDATE_LEDGER_FILE);
77659
+ const filePath = join23(projectRoot, CANDIDATE_LEDGER_FILE);
77641
77660
  if (!existsSync4(filePath))
77642
77661
  return [];
77643
77662
  const records = await reuseCommandFileRead({ key: "candidate-records", paths: [filePath], read: async () => {
@@ -77720,7 +77739,7 @@ var init_newKnowledgePage = __esm(() => {
77720
77739
 
77721
77740
  // src/project/approvedKnowledgeMetadata.ts
77722
77741
  import { existsSync as existsSync5 } from "node:fs";
77723
- import { join as join23 } from "node:path";
77742
+ import { join as join24 } from "node:path";
77724
77743
  function isRecord7(value) {
77725
77744
  return value !== null && typeof value === "object" && !Array.isArray(value);
77726
77745
  }
@@ -77750,7 +77769,7 @@ function approvedKnowledgeMetadataIndex(structure) {
77750
77769
  async function readApprovedKnowledgeMetadataIndex(projectRoot, structureOverride) {
77751
77770
  if (structureOverride !== undefined)
77752
77771
  return approvedKnowledgeMetadataIndex(structureOverride);
77753
- const path2 = join23(projectRoot, STRUCTURE_PATH);
77772
+ const path2 = join24(projectRoot, STRUCTURE_PATH);
77754
77773
  if (!existsSync5(path2))
77755
77774
  return approvedKnowledgeMetadataIndex(undefined);
77756
77775
  try {
@@ -77827,7 +77846,7 @@ var init_approvedKnowledgeMetadata = __esm(() => {
77827
77846
  init_src2();
77828
77847
  init_packageKnowledgeProjection();
77829
77848
  import_yaml15 = __toESM(require_dist(), 1);
77830
- STRUCTURE_PATH = join23("knowledge", "structure.yaml");
77849
+ STRUCTURE_PATH = join24("knowledge", "structure.yaml");
77831
77850
  FRONTMATTER_RE2 = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u;
77832
77851
  COMPACT_FIELDS = new Set([
77833
77852
  "title",
@@ -77878,7 +77897,7 @@ function selectDeliveryPages(input) {
77878
77897
  // src/project/knowledgeAssets.ts
77879
77898
  import { existsSync as existsSync6 } from "node:fs";
77880
77899
  import { readFile as readFile23, readdir as readdir8, rm as rm8 } from "node:fs/promises";
77881
- import { dirname as dirname17, extname as extname10, join as join24, relative as relative13, resolve as resolve19, sep as sep3 } from "node:path";
77900
+ import { dirname as dirname17, extname as extname10, join as join25, relative as relative13, resolve as resolve19, sep as sep3 } from "node:path";
77882
77901
  function posixPath(value) {
77883
77902
  return value.split(sep3).join("/");
77884
77903
  }
@@ -77911,7 +77930,7 @@ function sourceAssetPath(documentPath, target) {
77911
77930
  const decoded = decodedTarget(target);
77912
77931
  if (/^[a-z][a-z0-9+.-]*:/iu.test(decoded) || decoded.startsWith("#") || decoded.startsWith("/"))
77913
77932
  return;
77914
- const normalized = posixPath(join24(dirname17(documentPath), decoded));
77933
+ const normalized = posixPath(join25(dirname17(documentPath), decoded));
77915
77934
  if (normalized === "assets" || normalized.startsWith("assets/"))
77916
77935
  return normalized;
77917
77936
  return;
@@ -77923,7 +77942,7 @@ function selectedAssets(input) {
77923
77942
  const selected = new Map;
77924
77943
  for (const link of markdownInlineLinks(input.content)) {
77925
77944
  const target = link.target;
77926
- const pageTarget = posixPath(join24(dirname17(input.pageRelPath), decodedTarget(target)));
77945
+ const pageTarget = posixPath(join25(dirname17(input.pageRelPath), decodedTarget(target)));
77927
77946
  const sourceRoot2 = posixPath(input.sourceMaterializedAt).replace(/\/$/u, "") + "/";
77928
77947
  const path2 = sourceAssetPath(input.documentPath, target) ?? (pageTarget.startsWith(sourceRoot2) ? pageTarget.slice(sourceRoot2.length) : undefined);
77929
77948
  if (path2 === undefined)
@@ -77968,7 +77987,7 @@ async function projectKnowledgeAssets(input) {
77968
77987
  next: "Rerun the source capture and resolve resource materialization errors before Review."
77969
77988
  });
77970
77989
  }
77971
- const sourcePath = join24(input.projectRoot, input.sourceMaterializedAt, asset.path);
77990
+ const sourcePath = join25(input.projectRoot, input.sourceMaterializedAt, asset.path);
77972
77991
  let bytes;
77973
77992
  try {
77974
77993
  bytes = await readFile23(sourcePath);
@@ -77984,7 +78003,7 @@ async function projectKnowledgeAssets(input) {
77984
78003
  knowledgePathBySourcePath.set(asset.path, relPath);
77985
78004
  assets.push({
77986
78005
  relPath,
77987
- absPath: join24(input.projectRoot, relPath),
78006
+ absPath: join25(input.projectRoot, relPath),
77988
78007
  bytes,
77989
78008
  contentHash: asset.content_hash
77990
78009
  });
@@ -78006,7 +78025,7 @@ function canonicalizeKnowledgeAssetLinks(input) {
78006
78025
  let rewritten = 0;
78007
78026
  const content3 = replaceMarkdownInlineLinkTargets(input.content, (link) => {
78008
78027
  const sourcePath = sourceAssetPath(input.documentPath, link.target);
78009
- const projectedPath = input.pageRelPath === undefined ? undefined : posixPath(join24(dirname17(input.pageRelPath), decodedTarget(link.target)));
78028
+ const projectedPath = input.pageRelPath === undefined ? undefined : posixPath(join25(dirname17(input.pageRelPath), decodedTarget(link.target)));
78010
78029
  const asset = (sourcePath === undefined ? undefined : bySourcePath.get(sourcePath)) ?? (projectedPath === undefined ? undefined : byKnowledgePath.get(projectedPath));
78011
78030
  if (asset?.content_hash === undefined)
78012
78031
  return;
@@ -78021,7 +78040,7 @@ function knowledgeAssetReferences(input) {
78021
78040
  const target = link.target;
78022
78041
  if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("#"))
78023
78042
  continue;
78024
- const resolved = posixPath(join24(dirname17(input.pageRelPath), decodedTarget(target)));
78043
+ const resolved = posixPath(join25(dirname17(input.pageRelPath), decodedTarget(target)));
78025
78044
  if (resolved.startsWith("knowledge/assets/"))
78026
78045
  references.add(resolved);
78027
78046
  }
@@ -78042,7 +78061,7 @@ async function walkFiles2(root) {
78042
78061
  const files = [];
78043
78062
  const visit3 = async (dir) => {
78044
78063
  for (const entry of await readdir8(dir, { withFileTypes: true })) {
78045
- const path2 = join24(dir, entry.name);
78064
+ const path2 = join25(dir, entry.name);
78046
78065
  if (entry.isDirectory())
78047
78066
  await visit3(path2);
78048
78067
  else if (entry.isFile())
@@ -78053,8 +78072,8 @@ async function walkFiles2(root) {
78053
78072
  return files;
78054
78073
  }
78055
78074
  async function removeOrphanKnowledgeAssets(projectRoot, currentReferences) {
78056
- const knowledgeRoot = join24(projectRoot, "knowledge");
78057
- const assetRoot = join24(knowledgeRoot, "assets");
78075
+ const knowledgeRoot = join25(projectRoot, "knowledge");
78076
+ const assetRoot = join25(knowledgeRoot, "assets");
78058
78077
  if (!existsSync6(assetRoot))
78059
78078
  return [];
78060
78079
  const referenced = new Set(currentReferences ?? []);
@@ -78099,7 +78118,7 @@ var init_knowledgeAssets = __esm(() => {
78099
78118
  // src/project/documentEvidenceIndex.ts
78100
78119
  import { Buffer as Buffer3 } from "node:buffer";
78101
78120
  import { mkdir as mkdir14, readFile as readFile24, writeFile as writeFile9 } from "node:fs/promises";
78102
- import { dirname as dirname18, join as join25 } from "node:path";
78121
+ import { dirname as dirname18, join as join26 } from "node:path";
78103
78122
  function workspaceStateError(message, detail = {}) {
78104
78123
  return new ContextError(ExitCode.WorkspaceStateError, message, {
78105
78124
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -78113,10 +78132,10 @@ function userInputError(message, detail = {}) {
78113
78132
  });
78114
78133
  }
78115
78134
  function committedManifestRelativePath(sourceType, sourceName) {
78116
- return join25("sources", sourceType, normalizeDocumentSourceName(sourceName), "manifest.json");
78135
+ return join26("sources", sourceType, normalizeDocumentSourceName(sourceName), "manifest.json");
78117
78136
  }
78118
78137
  function runtimeEvidenceIndexRelativePath(sourceType, sourceName) {
78119
- return join25(".tmp", "context-runtime", "evidence", sourceType, normalizeDocumentSourceName(sourceName), "source-index.json");
78138
+ return join26(".tmp", "context-runtime", "evidence", sourceType, normalizeDocumentSourceName(sourceName), "source-index.json");
78120
78139
  }
78121
78140
  async function readJsonFile(path2, next) {
78122
78141
  try {
@@ -78138,7 +78157,7 @@ function assertManifestSource(input) {
78138
78157
  }
78139
78158
  }
78140
78159
  async function readCommittedSnapshotFile(input) {
78141
- const absolutePath = join25(input.projectRoot, input.materializedAt, input.path);
78160
+ const absolutePath = join26(input.projectRoot, input.materializedAt, input.path);
78142
78161
  try {
78143
78162
  return await readFile24(absolutePath);
78144
78163
  } catch (error) {
@@ -78185,9 +78204,9 @@ async function buildCommittedEvidenceIndex(input) {
78185
78204
  });
78186
78205
  }
78187
78206
  const managed = input.sourceType === "note" || input.sourceType === "sessions" ? await (await Promise.resolve().then(() => (init_managedDocumentSnapshot(), exports_managedDocumentSnapshot))).readManagedDocumentSnapshot(input.projectRoot, input.sourceType, sourceName) : undefined;
78188
- const materializedAt = managed?.materializedAt ?? input.materializedAt ?? join25("sources", input.sourceType, sourceName);
78207
+ const materializedAt = managed?.materializedAt ?? input.materializedAt ?? join26("sources", input.sourceType, sourceName);
78189
78208
  const manifestRelPath = managed ? `sources/${input.sourceType}/${sourceName}` : input.manifestPath ?? committedManifestRelativePath(input.sourceType, sourceName);
78190
- const manifestAbsPath = join25(input.projectRoot, manifestRelPath);
78209
+ const manifestAbsPath = join26(input.projectRoot, manifestRelPath);
78191
78210
  let manifest;
78192
78211
  try {
78193
78212
  manifest = managed?.manifest ?? parseDocumentSnapshotForSource(await readJsonFile(manifestAbsPath, `rerun context run capture:${input.sourceType}:${sourceName} or restore ${manifestRelPath}`), sourceName);
@@ -78267,7 +78286,7 @@ async function buildCommittedEvidenceIndex(input) {
78267
78286
  continue;
78268
78287
  let bytes;
78269
78288
  try {
78270
- bytes = await readFile24(join25(input.projectRoot, materializedAt, asset.path));
78289
+ bytes = await readFile24(join26(input.projectRoot, materializedAt, asset.path));
78271
78290
  } catch (error) {
78272
78291
  const message = error instanceof Error ? error.message : String(error);
78273
78292
  throw workspaceStateError(`document snapshot audit asset is missing: ${asset.path}`, {
@@ -78308,7 +78327,7 @@ async function buildCommittedEvidenceIndex(input) {
78308
78327
  documents
78309
78328
  };
78310
78329
  const runtimeIndexPath = runtimeEvidenceIndexRelativePath(input.sourceType, sourceName);
78311
- const absoluteRuntimeIndexPath = join25(input.projectRoot, runtimeIndexPath);
78330
+ const absoluteRuntimeIndexPath = join26(input.projectRoot, runtimeIndexPath);
78312
78331
  if (input.writeRuntimeIndex ?? true) {
78313
78332
  await mkdir14(dirname18(absoluteRuntimeIndexPath), { recursive: true });
78314
78333
  await writeFile9(absoluteRuntimeIndexPath, `${JSON.stringify(index2, null, 2)}
@@ -78332,7 +78351,7 @@ var init_documentEvidenceIndex = __esm(() => {
78332
78351
  });
78333
78352
 
78334
78353
  // src/project/assetSourceRegistry.ts
78335
- import { join as join26 } from "node:path";
78354
+ import { join as join27 } from "node:path";
78336
78355
  function emptySourceRegistryLookup(loaded) {
78337
78356
  return {
78338
78357
  loaded,
@@ -78402,10 +78421,10 @@ function registeredDocumentSource(registry2, sourceType, sourceName) {
78402
78421
  return registry2.documents[sourceType].get(sourceName);
78403
78422
  }
78404
78423
  function defaultDocumentMaterializedAt(sourceType, sourceName) {
78405
- return join26("sources", sourceType, sourceName);
78424
+ return join27("sources", sourceType, sourceName);
78406
78425
  }
78407
78426
  function defaultDocumentManifest(materializedAt) {
78408
- return join26(materializedAt, "manifest.json");
78427
+ return join27(materializedAt, "manifest.json");
78409
78428
  }
78410
78429
  async function getCommittedEvidenceIndex(input) {
78411
78430
  const key = `${input.sourceType}:${input.sourceName}:${input.materializedAt}:${input.manifestPath}`;
@@ -78698,7 +78717,7 @@ __export(exports_approvedRevisionBatch, {
78698
78717
  approvedRevisionCandidateApplied: () => approvedRevisionCandidateApplied
78699
78718
  });
78700
78719
  import { readFile as readFile26 } from "node:fs/promises";
78701
- import { join as join27 } from "node:path";
78720
+ import { join as join28 } from "node:path";
78702
78721
  async function prepareRevisionBatchContinuation(root, request, batch) {
78703
78722
  const [next, ...remaining] = request.pending_targets ?? [];
78704
78723
  if (!next)
@@ -78778,13 +78797,13 @@ async function observeApprovedRevisionBatch(root, request) {
78778
78797
  for (const original of expected) {
78779
78798
  const candidate = rows.find((row) => row.candidate_id === original.candidate_id);
78780
78799
  const revision = original.approved_revision;
78781
- const bytes = await readFile26(join27(root, "knowledge", revision.previous_path ?? original.path), "utf8").catch((error) => {
78800
+ const bytes = await readFile26(join28(root, "knowledge", revision.previous_path ?? original.path), "utf8").catch((error) => {
78782
78801
  if (error.code === "ENOENT")
78783
78802
  return;
78784
78803
  throw error;
78785
78804
  });
78786
78805
  if (!candidate) {
78787
- const applied = await readFile26(join27(root, "knowledge", original.path), "utf8").catch(() => {
78806
+ const applied = await readFile26(join28(root, "knowledge", original.path), "utf8").catch(() => {
78788
78807
  return;
78789
78808
  });
78790
78809
  if (await approvedRevisionCandidateApplied(root, original, applied))
@@ -78954,7 +78973,7 @@ var init_verifyFrontmatter = __esm(() => {
78954
78973
  // src/project/productionSubmissionFiles.ts
78955
78974
  import { constants as constants3 } from "node:fs";
78956
78975
  import { lstat as lstat5, open as open3, realpath as realpath4 } from "node:fs/promises";
78957
- import { isAbsolute as isAbsolute11, join as join28, relative as relative14 } from "node:path";
78976
+ import { isAbsolute as isAbsolute11, join as join29, relative as relative14 } from "node:path";
78958
78977
  function invalidFile(path2, message) {
78959
78978
  return new ContextError(ExitCode.UserError, message, {
78960
78979
  category: ErrorCategory.UserInputInvalid,
@@ -78965,7 +78984,7 @@ function invalidFile(path2, message) {
78965
78984
  });
78966
78985
  }
78967
78986
  function productionAgentDirectory(stage) {
78968
- return join28(".tmp", "agent-work", "production-stages", localId.parse(stage));
78987
+ return join29(".tmp", "agent-work", "production-stages", localId.parse(stage));
78969
78988
  }
78970
78989
  function assertRelativeFile(path2) {
78971
78990
  if (isAbsolute11(path2) || /^[a-zA-Z]:/u.test(path2) || path2.includes("\\") || path2.includes("\x00") || path2.split("/").some((part) => !part || part === "." || part === "..")) {
@@ -78976,14 +78995,14 @@ async function readProductionFile(input) {
78976
78995
  return readFixedProductionFile({ ...input, directory: productionAgentDirectory(input.stage) });
78977
78996
  }
78978
78997
  async function readProductionPlanningFile(input) {
78979
- return readFixedProductionFile({ ...input, directory: join28(".tmp", "agent-work") });
78998
+ return readFixedProductionFile({ ...input, directory: join29(".tmp", "agent-work") });
78980
78999
  }
78981
79000
  async function readFixedProductionFile(input) {
78982
79001
  assertRelativeFile(input.path);
78983
79002
  const limit = input.maxBytes ?? DEFAULT_LIMITS.file_bytes;
78984
79003
  if (!Number.isSafeInteger(limit) || limit < 1)
78985
79004
  throw invalidFile(input.path, "File budget must be a positive safe integer.");
78986
- const local = join28(input.directory, input.path);
79005
+ const local = join29(input.directory, input.path);
78987
79006
  let handle;
78988
79007
  try {
78989
79008
  const root = await realpath4(input.projectRoot);
@@ -78994,7 +79013,7 @@ async function readFixedProductionFile(input) {
78994
79013
  handle = await open3(absolute, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
78995
79014
  const opened = await handle.stat();
78996
79015
  const resolved = await realpath4(absolute);
78997
- const stageRoot = join28(root, input.directory);
79016
+ const stageRoot = join29(root, input.directory);
78998
79017
  const within = relative14(stageRoot, resolved);
78999
79018
  if (within.startsWith("..") || isAbsolute11(within) || opened.dev !== before.dev || opened.ino !== before.ino) {
79000
79019
  throw invalidFile(input.path, "The draft path changed while opening it; restore a stage-local file and retry.");
@@ -79120,7 +79139,7 @@ var init_productionSubmissionFiles = __esm(() => {
79120
79139
 
79121
79140
  // src/project/productionArticleTarget.ts
79122
79141
  import { readFile as readFile27 } from "node:fs/promises";
79123
- import { join as join29 } from "node:path";
79142
+ import { join as join30 } from "node:path";
79124
79143
  function productionApprovedTargetsIndex(metadata) {
79125
79144
  const articles = validateArticleStructureEntries(metadata.structure?.articles ?? []);
79126
79145
  return {
@@ -79146,7 +79165,7 @@ async function readProductionArticleTarget(input) {
79146
79165
  let markdown = existing[0]?.body;
79147
79166
  if (markdown === undefined) {
79148
79167
  try {
79149
- markdown = await readFile27(await safeProjectTarget(input.projectRoot, join29("knowledge", task.path)), "utf8");
79168
+ markdown = await readFile27(await safeProjectTarget(input.projectRoot, join30("knowledge", task.path)), "utf8");
79150
79169
  } catch (error) {
79151
79170
  if (error.code !== "ENOENT")
79152
79171
  throw error;
@@ -79166,7 +79185,7 @@ async function readProductionArticleTarget(input) {
79166
79185
  }
79167
79186
  let approvedBaseDigest = existing[0]?.approved_revision?.base_digest;
79168
79187
  if (approvedBaseDigest === undefined) {
79169
- const formalMarkdown = formal.length ? await readFile27(await safeProjectTarget(input.projectRoot, join29("knowledge", task.path)), "utf8") : undefined;
79188
+ const formalMarkdown = formal.length ? await readFile27(await safeProjectTarget(input.projectRoot, join30("knowledge", task.path)), "utf8") : undefined;
79170
79189
  approvedBaseDigest = formalMarkdown === undefined ? null : durableContentDigest(formalMarkdown);
79171
79190
  }
79172
79191
  return { visibility, approvedBaseDigest, ...sections ? { base: { markdown, sections } } : {} };
@@ -79405,10 +79424,10 @@ __export(exports_productionStageStore, {
79405
79424
  });
79406
79425
  import { constants as constants4 } from "node:fs";
79407
79426
  import { readFile as readFile28, access as access2, stat as stat7 } from "node:fs/promises";
79408
- import { join as join30 } from "node:path";
79427
+ import { join as join31 } from "node:path";
79409
79428
  function productionStageDirectory(id3) {
79410
79429
  productionAgentDirectory(id3);
79411
- return join30(PRODUCTION_STAGES_ROOT, id3);
79430
+ return join31(PRODUCTION_STAGES_ROOT, id3);
79412
79431
  }
79413
79432
  async function readOptional(root, path2) {
79414
79433
  const absolute = await safeProjectTarget(root, path2);
@@ -79459,7 +79478,7 @@ async function readProductionStageSnapshot(root, id3) {
79459
79478
  }
79460
79479
  id3 = value.stage;
79461
79480
  }
79462
- feedback.file = join30(productionStageDirectory(id3), "manifest.json");
79481
+ feedback.file = join31(productionStageDirectory(id3), "manifest.json");
79463
79482
  const content3 = await readOptional(root, feedback.file);
79464
79483
  if (content3 === undefined)
79465
79484
  return;
@@ -79472,7 +79491,7 @@ async function readProductionStageSnapshot(root, id3) {
79472
79491
  async function saveProductionStage(root, value) {
79473
79492
  const stage = validateProductionStage(value);
79474
79493
  await withProjectWriteLock(root, "production-stage", async () => {
79475
- await writeProductionProjection(root, join30(productionStageDirectory(stage.id), "manifest.json"), `${JSON.stringify(stage)}
79494
+ await writeProductionProjection(root, join31(productionStageDirectory(stage.id), "manifest.json"), `${JSON.stringify(stage)}
79476
79495
  `);
79477
79496
  await writeProductionProjection(root, CURRENT_PATH, `${JSON.stringify({ stage: stage.id })}
79478
79497
  `);
@@ -79496,15 +79515,15 @@ function productionPlanMarkdown(stage) {
79496
79515
  ...stage.tasks.filter((task) => task.status === "replaced").map((task) => `- ${task.path}: ${task.reason ?? "Replaced by the current plan"}`)
79497
79516
  ] : [],
79498
79517
  "",
79499
- `Planned skill guidance: ${join30(directory, "indexer-usage.yaml")}`,
79500
- `Available skill entries: ${join30(directory, "skills.md")}`,
79518
+ `Planned skill guidance: ${join31(directory, "indexer-usage.yaml")}`,
79519
+ `Available skill entries: ${join31(directory, "skills.md")}`,
79501
79520
  "",
79502
79521
  `Remaining investigation: ${stage.pending_scopes.join(", ") || "none"}`,
79503
79522
  "",
79504
79523
  ...!stage.report_approved && stage.planning_complete ? [
79505
- `If the user requests changes, edit ${productionAgentDirectory(stage.id)}/submissions/plan.yaml using ${join30(directory, "planning.schema.json")}.`,
79524
+ `If the user requests changes, edit ${productionAgentDirectory(stage.id)}/submissions/plan.yaml using ${join31(directory, "planning.schema.json")}.`,
79506
79525
  `Resubmit: context action complete-current --revision ${stage.id} --input ${productionAgentDirectory(stage.id)}/submissions/plan.yaml --format json`,
79507
- "Then present the updated report and wait for approval; an old report confirmation does not approve changed article goals.",
79526
+ "Then present the updated report and apply context.gate.work_start_scope; an old decision does not approve changed article goals.",
79508
79527
  ""
79509
79528
  ] : [],
79510
79529
  ...stage.gaps.map((gap) => `- ${gap.scope}: ${gap.reason}`),
@@ -79528,12 +79547,12 @@ async function materializeProductionStage(input) {
79528
79547
  changed += 1;
79529
79548
  };
79530
79549
  if (input.materials) {
79531
- await write(join30(directory, "shared/requirements.md"), input.materials.requirements);
79532
- } else if (dispatch.batches.length && !await hasReadableProjection(input.projectRoot, join30(directory, "shared/requirements.md"))) {
79550
+ await write(join31(directory, "shared/requirements.md"), input.materials.requirements);
79551
+ } else if (dispatch.batches.length && !await hasReadableProjection(input.projectRoot, join31(directory, "shared/requirements.md"))) {
79533
79552
  throw new TypeError("Stage materials are missing. Re-prepare the current plan's directory; accepted tasks remain saved.");
79534
79553
  }
79535
- await write(join30(directory, "capabilities.yaml"), import_yaml21.default.stringify(input.capabilities));
79536
- await write(join30(directory, "skills.md"), [
79554
+ await write(join31(directory, "capabilities.yaml"), import_yaml21.default.stringify(input.capabilities));
79555
+ await write(join31(directory, "skills.md"), [
79537
79556
  "# Available skills",
79538
79557
  "",
79539
79558
  ...input.capabilities.skills.map((skill) => `- ${skill.name}${skill.entry ? `: ${skill.entry}` : " (read through the host)"}`),
@@ -79542,13 +79561,13 @@ async function materializeProductionStage(input) {
79542
79561
  ""
79543
79562
  ].join(`
79544
79563
  `));
79545
- await write(join30(directory, "indexer-usage.yaml"), import_yaml21.default.stringify(stage.indexer_usage));
79546
- await write(join30(directory, "plan.md"), productionPlanMarkdown(stage));
79564
+ await write(join31(directory, "indexer-usage.yaml"), import_yaml21.default.stringify(stage.indexer_usage));
79565
+ await write(join31(directory, "plan.md"), productionPlanMarkdown(stage));
79547
79566
  const issued = new Set(dispatch.batches.flatMap((batch) => batch.tasks));
79548
79567
  const neededScopes = new Set(stage.tasks.filter((task) => issued.has(task.id)).flatMap((task) => task.sources.map((source2) => source2.scope)));
79549
79568
  const scopePaths = new Map;
79550
79569
  for (const scope2 of stage.scopes) {
79551
- const path2 = join30(directory, productionSourceFile(scope2.scope));
79570
+ const path2 = join31(directory, productionSourceFile(scope2.scope));
79552
79571
  scopePaths.set(scope2.scope, path2);
79553
79572
  if (input.materials) {
79554
79573
  const content3 = input.materials.sources.get(scope2.scope);
@@ -79562,15 +79581,15 @@ async function materializeProductionStage(input) {
79562
79581
  for (const [path2, content3] of input.materials?.guidance ?? []) {
79563
79582
  if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*\.md$/u.test(path2))
79564
79583
  throw new TypeError("Guidance files need a local Markdown basename");
79565
- await write(join30(directory, "guidance", path2), content3);
79584
+ await write(join31(directory, "guidance", path2), content3);
79566
79585
  }
79567
79586
  const submittedTasks = [];
79568
79587
  let candidates;
79569
79588
  let approved;
79570
79589
  const tasksById = new Map(stage.tasks.map((task) => [task.id, task]));
79571
79590
  for (const batch of dispatch.batches) {
79572
- const batchPath = join30(directory, "batches", batch.id);
79573
- await write(join30(batchPath, "batch.md"), `# Batch ${batch.id}
79591
+ const batchPath = join31(directory, "batches", batch.id);
79592
+ await write(join31(batchPath, "batch.md"), `# Batch ${batch.id}
79574
79593
 
79575
79594
  Tasks: ${batch.tasks.join(", ")}
79576
79595
 
@@ -79579,10 +79598,10 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
79579
79598
  for (let offset2 = 0;offset2 < batch.tasks.length; offset2 += 8) {
79580
79599
  const projections = await Promise.allSettled(batch.tasks.slice(offset2, offset2 + 8).map(async (id3) => {
79581
79600
  const task = tasksById.get(id3);
79582
- const taskRoot = join30(batchPath, "tasks", id3);
79601
+ const taskRoot = join31(batchPath, "tasks", id3);
79583
79602
  if (task.base !== null) {
79584
- const basePath = join30(taskRoot, "base.md");
79585
- const referencesPath = join30(taskRoot, "base-references.yaml");
79603
+ const basePath = join31(taskRoot, "base.md");
79604
+ const referencesPath = join31(taskRoot, "base-references.yaml");
79586
79605
  let missing = false;
79587
79606
  try {
79588
79607
  await access2(await safeProjectTarget(input.projectRoot, basePath));
@@ -79606,7 +79625,7 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
79606
79625
  await write(referencesPath, import_yaml21.default.stringify({ sections: target.base.sections }));
79607
79626
  }
79608
79627
  }
79609
- await write(join30(taskRoot, "task.md"), [
79628
+ await write(join31(taskRoot, "task.md"), [
79610
79629
  `# ${task.question}`,
79611
79630
  "",
79612
79631
  `Target: ${task.path}`,
@@ -79616,16 +79635,16 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
79616
79635
  task.brief ?? "Read the authorized sources and write the complete article, or revise the existing article's affected fragments.",
79617
79636
  "",
79618
79637
  ...task.base !== null ? [
79619
- `Revision base: ${join30(taskRoot, "base.md")}`,
79620
- `Existing sections and references: ${join30(taskRoot, "base-references.yaml")}`,
79638
+ `Revision base: ${join31(taskRoot, "base.md")}`,
79639
+ `Existing sections and references: ${join31(taskRoot, "base-references.yaml")}`,
79621
79640
  ""
79622
79641
  ] : [],
79623
- `Shared requirements: ${join30(directory, "shared/requirements.md")}`,
79624
- `Relevant planned skills: ${join30(directory, "indexer-usage.yaml")}`,
79642
+ `Shared requirements: ${join31(directory, "shared/requirements.md")}`,
79643
+ `Relevant planned skills: ${join31(directory, "indexer-usage.yaml")}`,
79625
79644
  ""
79626
79645
  ].join(`
79627
79646
  `));
79628
- await write(join30(taskRoot, "sources.md"), [
79647
+ await write(join31(taskRoot, "sources.md"), [
79629
79648
  "# Authorized sources",
79630
79649
  "",
79631
79650
  ...task.sources.map((source2) => `- ${source2.scope}: ${scopePaths.get(source2.scope)}`),
@@ -79644,24 +79663,24 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
79644
79663
  }
79645
79664
  }
79646
79665
  }
79647
- const submission = dispatch.batches.length ? join30(directory, "submission.yaml") : undefined;
79666
+ const submission = dispatch.batches.length ? join31(directory, "submission.yaml") : undefined;
79648
79667
  if (submission)
79649
79668
  await write(submission, import_yaml21.default.stringify({ stage: stage.id, tasks: submittedTasks }));
79650
- await write(join30(directory, "stage.md"), [
79669
+ await write(join31(directory, "stage.md"), [
79651
79670
  `# ${stage.purpose}`,
79652
79671
  "",
79653
79672
  `Stage: ${stage.id}`,
79654
79673
  `State: ${dispatch.state}`,
79655
79674
  `Scheduling: ${dispatch.mode}`,
79656
79675
  "",
79657
- ...dispatch.batches.map((batch) => `- Batch ${batch.id}: ${join30(directory, "batches", batch.id, "batch.md")}`),
79676
+ ...dispatch.batches.map((batch) => `- Batch ${batch.id}: ${join31(directory, "batches", batch.id, "batch.md")}`),
79658
79677
  "",
79659
79678
  `Agent output directory: ${agent}`,
79660
79679
  `Remaining investigation: ${stage.pending_scopes.join(", ") || "none"}`,
79661
79680
  "",
79662
79681
  ...stage.tasks.filter((task) => task.status === "blocked").map((task) => `- Blocked task ${task.id}: ${task.path} — ${task.reason ?? "Investigate the task's source and dependencies."}`),
79663
79682
  "",
79664
- `To add articles within this confirmed purpose and source scope, submit a plan amendment using ${join30(directory, "planning.schema.json")}.`,
79683
+ `To add articles within this confirmed purpose and source scope, submit a plan amendment using ${join31(directory, "planning.schema.json")}.`,
79665
79684
  "During writing, articles adds tasks; replaces explicitly names unfinished task IDs. Existing task IDs may be used in after. Do not resubmit the whole original plan or widen the purpose without user confirmation.",
79666
79685
  `Plan amendment: context action complete-current --revision ${stage.id} --input ${agent}/submissions/plan-amendment.yaml --format json`,
79667
79686
  "",
@@ -79689,7 +79708,7 @@ async function prepareNextProductionStage(input) {
79689
79708
  return materializeProductionStage({ projectRoot: input.projectRoot, stage: input.stage, capabilities });
79690
79709
  }
79691
79710
  async function readProductionCapabilities(root, stage) {
79692
- const saved = await readOptional(root, join30(productionStageDirectory(stage), "capabilities.yaml"));
79711
+ const saved = await readOptional(root, join31(productionStageDirectory(stage), "capabilities.yaml"));
79693
79712
  return productionCapabilitiesSchema.parse(saved ? import_yaml21.default.parse(saved) : {});
79694
79713
  }
79695
79714
  var import_yaml21, PRODUCTION_STAGES_ROOT = ".tmp/context-runtime/production-stages", CURRENT_PATH;
@@ -79705,19 +79724,19 @@ var init_productionStageStore = __esm(() => {
79705
79724
  init_productionFeedback();
79706
79725
  init_productionStage();
79707
79726
  import_yaml21 = __toESM(require_dist(), 1);
79708
- CURRENT_PATH = join30(PRODUCTION_STAGES_ROOT, "current.json");
79727
+ CURRENT_PATH = join31(PRODUCTION_STAGES_ROOT, "current.json");
79709
79728
  });
79710
79729
 
79711
79730
  // src/project/indexerTemplateSnapshots.ts
79712
79731
  import { readFile as readFile29, mkdir as mkdir16 } from "node:fs/promises";
79713
- import { join as join31 } from "node:path";
79732
+ import { join as join32 } from "node:path";
79714
79733
  function object3(value) {
79715
79734
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
79716
79735
  }
79717
79736
  function snapshotPath(root, digest3) {
79718
79737
  if (!/^sha256:[a-f0-9]{64}$/u.test(digest3))
79719
79738
  throw new TypeError("Invalid template snapshot digest");
79720
- return join31(root, ...ROOT, `${digest3.slice(7)}.json`);
79739
+ return join32(root, ...ROOT, `${digest3.slice(7)}.json`);
79721
79740
  }
79722
79741
  async function encodeTemplateSnapshots(root, value) {
79723
79742
  const spec = object3(value);
@@ -79756,7 +79775,7 @@ async function encodeTemplateSnapshots(root, value) {
79756
79775
  if (indexerProtocolDigest(JSON.parse(existing)) !== digest3)
79757
79776
  throw new TypeError("Template snapshot integrity mismatch");
79758
79777
  } else {
79759
- await mkdir16(join31(root, ...ROOT), { recursive: true });
79778
+ await mkdir16(join32(root, ...ROOT), { recursive: true });
79760
79779
  await atomicWriteFile(path2, canonicalIndexerJson(shared));
79761
79780
  }
79762
79781
  return { protocol: REF, digest: digest3, ...binding ? { binding } : {} };
@@ -79838,7 +79857,7 @@ __export(exports_indexerMainRunStoreRecords, {
79838
79857
  INDEXER_MAIN_RUN_CURRENT_PATH: () => INDEXER_MAIN_RUN_CURRENT_PATH
79839
79858
  });
79840
79859
  import { readFile as readFile30 } from "node:fs/promises";
79841
- import { join as join32 } from "node:path";
79860
+ import { join as join33 } from "node:path";
79842
79861
  function isRecord9(value) {
79843
79862
  return value !== null && typeof value === "object" && !Array.isArray(value);
79844
79863
  }
@@ -79849,13 +79868,13 @@ function digestName(digest3) {
79849
79868
  return digest3.slice("sha256:".length);
79850
79869
  }
79851
79870
  function runSpecPath(requestDigest) {
79852
- return join32(INDEXER_MAIN_RUN_STORE_ROOT, "requests", `${digestName(requestDigest)}.json`);
79871
+ return join33(INDEXER_MAIN_RUN_STORE_ROOT, "requests", `${digestName(requestDigest)}.json`);
79853
79872
  }
79854
79873
  function acceptedCachePath(requestDigest) {
79855
- return join32(INDEXER_MAIN_RUN_STORE_ROOT, "accepted", `${digestName(requestDigest)}.json`);
79874
+ return join33(INDEXER_MAIN_RUN_STORE_ROOT, "accepted", `${digestName(requestDigest)}.json`);
79856
79875
  }
79857
79876
  function partitionConvergencePath(attemptDigest) {
79858
- return join32(INDEXER_MAIN_RUN_STORE_ROOT, "partition-convergence", `${digestName(attemptDigest)}.json`);
79877
+ return join33(INDEXER_MAIN_RUN_STORE_ROOT, "partition-convergence", `${digestName(attemptDigest)}.json`);
79859
79878
  }
79860
79879
  function jsonContent(value) {
79861
79880
  const canonical = canonicalIndexerJson(value);
@@ -79866,7 +79885,7 @@ function jsonContent(value) {
79866
79885
  }
79867
79886
  async function readMaybe3(projectRoot, path2) {
79868
79887
  try {
79869
- return await readFile30(join32(projectRoot, path2), "utf8");
79888
+ return await readFile30(join33(projectRoot, path2), "utf8");
79870
79889
  } catch (error) {
79871
79890
  if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
79872
79891
  return;
@@ -79951,7 +79970,7 @@ async function currentLedger(projectRoot) {
79951
79970
  async function currentSpec(input) {
79952
79971
  return reuseCommandFileRead({
79953
79972
  key: "validated-main-run-spec",
79954
- paths: [join32(input.projectRoot, runSpecPath(input.request_digest))],
79973
+ paths: [join33(input.projectRoot, runSpecPath(input.request_digest))],
79955
79974
  read: async () => {
79956
79975
  const value = await readJsonMaybe(input.projectRoot, runSpecPath(input.request_digest));
79957
79976
  if (value === undefined)
@@ -80039,8 +80058,8 @@ var init_indexerMainRunStoreRecords = __esm(() => {
80039
80058
  init_src2();
80040
80059
  init_durableSingleFileTransaction();
80041
80060
  init_durableMultiFileTransaction();
80042
- INDEXER_MAIN_RUN_STORE_ROOT = join32(".tmp", "context-runtime", "indexer", "main-index");
80043
- INDEXER_MAIN_RUN_CURRENT_PATH = join32(INDEXER_MAIN_RUN_STORE_ROOT, "current.json");
80061
+ INDEXER_MAIN_RUN_STORE_ROOT = join33(".tmp", "context-runtime", "indexer", "main-index");
80062
+ INDEXER_MAIN_RUN_CURRENT_PATH = join33(INDEXER_MAIN_RUN_STORE_ROOT, "current.json");
80044
80063
  });
80045
80064
 
80046
80065
  // src/project/indexerPartitionConvergenceStore.ts
@@ -80058,7 +80077,7 @@ var init_indexerMainRunBatchStore = __esm(() => {
80058
80077
  });
80059
80078
 
80060
80079
  // src/project/indexerMainRunStore.ts
80061
- import { join as join33 } from "node:path";
80080
+ import { join as join34 } from "node:path";
80062
80081
  async function readAcceptedMainResultRecordsUnlocked(projectRoot, stage, allowPending = false) {
80063
80082
  await recoverDurableMultiFileTransactions(projectRoot);
80064
80083
  const ledger = await currentLedger(projectRoot);
@@ -80075,7 +80094,7 @@ async function readAcceptedMainResultRecordsUnlocked(projectRoot, stage, allowPe
80075
80094
  paths: [INDEXER_MAIN_RUN_CURRENT_PATH, ...ledger.entries.filter((entry) => entry.state === "accepted").flatMap((entry) => [
80076
80095
  runSpecPath(entry.execution_request_digest),
80077
80096
  acceptedCachePath(entry.execution_request_digest)
80078
- ])].map((path2) => join33(projectRoot, path2)),
80097
+ ])].map((path2) => join34(projectRoot, path2)),
80079
80098
  read: async () => {
80080
80099
  const records = [];
80081
80100
  for (const entry of ledger.entries) {
@@ -80124,7 +80143,7 @@ var init_indexerMainRunStore = __esm(() => {
80124
80143
  import { execFile as execFile5 } from "node:child_process";
80125
80144
  import { promisify as promisify5 } from "node:util";
80126
80145
  import { readFile as readFile31 } from "node:fs/promises";
80127
- import { basename as basename6, join as join34 } from "node:path";
80146
+ import { basename as basename6, join as join35 } from "node:path";
80128
80147
  function productionDocumentSkeleton(path2, markdown) {
80129
80148
  const lines = markdown.split(/\r?\n/u);
80130
80149
  let title;
@@ -80204,7 +80223,7 @@ This entire source is explicitly excluded from every selected requirement; no in
80204
80223
  if (selected.length !== 1)
80205
80224
  throw new TypeError(`Source must identify one registered input: ${scope2}`);
80206
80225
  const entry = selected[0];
80207
- const root = join34(input.projectRoot, entry.materializedAt);
80226
+ const root = join35(input.projectRoot, entry.materializedAt);
80208
80227
  if (type === "repo") {
80209
80228
  const repo = registry2.repos.find((repo2) => repo2.id === name3 || repo2.name === name3);
80210
80229
  if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(repo.ref))
@@ -80255,7 +80274,7 @@ This entire source is explicitly excluded from every selected requirement; no in
80255
80274
  }
80256
80275
  const managed = type === "note" || type === "sessions";
80257
80276
  const manifestPath = "snapshot" in entry ? entry.snapshot?.manifest : undefined;
80258
- const paths = managed ? [basename6(entry.materializedAt)] : parseDocumentSnapshotForSource(JSON.parse(await readFile31(join34(input.projectRoot, manifestPath ?? `${entry.materializedAt}/manifest.json`), "utf8")), entry.name).files.map((file) => file.path);
80277
+ const paths = managed ? [basename6(entry.materializedAt)] : parseDocumentSnapshotForSource(JSON.parse(await readFile31(join35(input.projectRoot, manifestPath ?? `${entry.materializedAt}/manifest.json`), "utf8")), entry.name).files.map((file) => file.path);
80259
80278
  const overviews = [];
80260
80279
  const included = paths.filter((path2) => !sourceExcludes(input.requirements, scope2, path2));
80261
80280
  for (const path2 of included) {
@@ -80616,9 +80635,9 @@ var init_productionArticle = __esm(() => {
80616
80635
 
80617
80636
  // src/project/productionRepairDraft.ts
80618
80637
  import { readFile as readFile32 } from "node:fs/promises";
80619
- import { join as join35 } from "node:path";
80638
+ import { join as join36 } from "node:path";
80620
80639
  function draftPath(stage, task) {
80621
- return join35(productionStageDirectory(stage), "repair-drafts", `${task.id}.json`);
80640
+ return join36(productionStageDirectory(stage), "repair-drafts", `${task.id}.json`);
80622
80641
  }
80623
80642
  async function retainProductionRepairDraft(input) {
80624
80643
  if (!input.files.content || !input.files.references)
@@ -80659,7 +80678,7 @@ var init_productionRepairDraft = __esm(() => {
80659
80678
 
80660
80679
  // src/project/productionSubmission.ts
80661
80680
  import { readFile as readFile33 } from "node:fs/promises";
80662
- import { join as join36 } from "node:path";
80681
+ import { join as join37 } from "node:path";
80663
80682
  function submissionStateError(reason, message, command = "context status --format json") {
80664
80683
  return new ContextError(ExitCode.WorkspaceStateError, message, {
80665
80684
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -80697,7 +80716,7 @@ async function completeProductionSubmission(input) {
80697
80716
  if (!stage || stage.id !== input.stage)
80698
80717
  throw submissionStateError("stale-production-stage", "Task stage no longer exists. Start a new production run; do not reuse a stale submission.");
80699
80718
  if (!stage.report_approved)
80700
- throw submissionStateError("production-report-approval-required", "Present the planned report and wait for user feedback before submitting bulk writing.");
80719
+ throw submissionStateError("production-report-approval-required", "Present the planned report and apply context.gate.work_start_scope before submitting bulk writing.");
80701
80720
  if (stage.delivery)
80702
80721
  throw submissionStateError("production-delivery-paused", "Writing is paused for delivery. Finish Review and build, or run context run --resume-writing --format json; existing task inputs remain valid.");
80703
80722
  if ((await readMaintenance(input.projectRoot)).active)
@@ -80716,7 +80735,7 @@ async function completeProductionSubmission(input) {
80716
80735
  byPath.set(key, [...byPath.get(key) ?? [], candidate]);
80717
80736
  byArticle.set(candidate.article_id, [...byArticle.get(candidate.article_id) ?? [], candidate]);
80718
80737
  }
80719
- const manifestPath = join36(productionStageDirectory(stage.id), "manifest.json");
80738
+ const manifestPath = join37(productionStageDirectory(stage.id), "manifest.json");
80720
80739
  const manifestText = snapshot.content;
80721
80740
  const baselines = new Map;
80722
80741
  let sourceReader;
@@ -80908,9 +80927,9 @@ var init_productionSubmission = __esm(() => {
80908
80927
  // src/project/productionExistingArticles.ts
80909
80928
  import { constants as constants5 } from "node:fs";
80910
80929
  import { open as open4 } from "node:fs/promises";
80911
- import { join as join37 } from "node:path";
80930
+ import { join as join38 } from "node:path";
80912
80931
  async function readerHeader(root, path2) {
80913
- const absolute = await safeProjectTarget(root, join37("knowledge", path2));
80932
+ const absolute = await safeProjectTarget(root, join38("knowledge", path2));
80914
80933
  const handle = await open4(absolute, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
80915
80934
  try {
80916
80935
  if (!(await handle.stat()).isFile())
@@ -81031,7 +81050,7 @@ async function resolveProductionExclusions(requirements, readBaseline) {
81031
81050
  // src/project/productionPlanning.ts
81032
81051
  import { randomUUID as randomUUID3 } from "node:crypto";
81033
81052
  import { readFile as readFile34, access as access3 } from "node:fs/promises";
81034
- import { join as join38 } from "node:path";
81053
+ import { join as join39 } from "node:path";
81035
81054
  function refreshRequired(stage, message) {
81036
81055
  return new ContextError(ExitCode.UserError, message, {
81037
81056
  category: ErrorCategory.UserInputInvalid,
@@ -81050,9 +81069,9 @@ async function productionPlanningIsPrepared(root, stage) {
81050
81069
  try {
81051
81070
  const directory = productionStageDirectory(stage.id);
81052
81071
  const current2 = await productionPlanningRequest(root);
81053
- const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root, join38(directory, "shared/requirements.md")), "utf8"));
81054
- await access3(await safeProjectTarget(root, join38(directory, "planning.md")));
81055
- await access3(await safeProjectTarget(root, join38(directory, "planning.schema.json")));
81072
+ const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root, join39(directory, "shared/requirements.md")), "utf8"));
81073
+ await access3(await safeProjectTarget(root, join39(directory, "planning.md")));
81074
+ await access3(await safeProjectTarget(root, join39(directory, "planning.schema.json")));
81056
81075
  return !!current2 && current2.revision === indexerProtocolDigest(supplied);
81057
81076
  } catch (error) {
81058
81077
  if (error.code === "ENOENT")
@@ -81063,7 +81082,7 @@ async function productionPlanningIsPrepared(root, stage) {
81063
81082
  async function productionRequirementsAreCurrent(root, stage) {
81064
81083
  try {
81065
81084
  const current2 = await productionPlanningRequest(root);
81066
- const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root, join38(productionStageDirectory(stage.id), "shared/requirements.md")), "utf8"));
81085
+ const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root, join39(productionStageDirectory(stage.id), "shared/requirements.md")), "utf8"));
81067
81086
  return !!current2 && current2.revision === indexerProtocolDigest(supplied);
81068
81087
  } catch (error) {
81069
81088
  if (error.code !== "ENOENT")
@@ -81122,17 +81141,17 @@ Restore the authorized source and retry preparation.
81122
81141
  gaps: prepared.gaps
81123
81142
  });
81124
81143
  const directory = productionStageDirectory(stage.id);
81125
- await writeProductionProjection(input.projectRoot, join38(directory, "planning.schema.json"), `${JSON.stringify(zodToJsonSchema(productionPlanInputSchema), null, 2)}
81144
+ await writeProductionProjection(input.projectRoot, join39(directory, "planning.schema.json"), `${JSON.stringify(zodToJsonSchema(productionPlanInputSchema), null, 2)}
81126
81145
  `);
81127
- await writeProductionProjection(input.projectRoot, join38(directory, "planning.md"), [
81146
+ await writeProductionProjection(input.projectRoot, join39(directory, "planning.md"), [
81128
81147
  "# Investigate and plan",
81129
81148
  "",
81130
- `Requirements: ${join38(directory, "shared/requirements.md")}`,
81131
- `Submission schema: ${join38(directory, "planning.schema.json")}`,
81132
- `Existing reader topics: ${join38(directory, "guidance/existing-articles.md")}`,
81149
+ `Requirements: ${join39(directory, "shared/requirements.md")}`,
81150
+ `Submission schema: ${join39(directory, "planning.schema.json")}`,
81151
+ `Existing reader topics: ${join39(directory, "guidance/existing-articles.md")}`,
81133
81152
  `Stage: ${stage.id}`,
81134
81153
  "",
81135
- ...scopes.map((scope2) => `- ${scope2.scope}: ${join38(directory, productionSourceFile(scope2.scope))}`),
81154
+ ...scopes.map((scope2) => `- ${scope2.scope}: ${join39(directory, productionSourceFile(scope2.scope))}`),
81136
81155
  "",
81137
81156
  "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.",
81138
81157
  "Configured sources are the knowledge workspace coverage boundary, not a new investigation assignment on every request. First distinguish the user's current task, its actual source dependencies, and unrelated configured sources. Reuse approved content; a source-level pending entry alone does not prove missing knowledge or require new articles.",
@@ -81212,7 +81231,7 @@ async function submitProductionPlan(input) {
81212
81231
  }
81213
81232
  const prior = candidates.find((candidate) => candidate.path === article.path);
81214
81233
  const formal = approved.byPath.get(article.path);
81215
- const markdown = prior?.body ?? (formal ? await readFile34(await safeProjectTarget(input.projectRoot, join38("knowledge", formal.path)), "utf8") : undefined);
81234
+ const markdown = prior?.body ?? (formal ? await readFile34(await safeProjectTarget(input.projectRoot, join39("knowledge", formal.path)), "utf8") : undefined);
81216
81235
  const sections = prior?.indexer_candidate?.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
81217
81236
  const task = {
81218
81237
  id: identities.get(article.path),
@@ -81305,7 +81324,7 @@ var init_productionPlanning = __esm(() => {
81305
81324
 
81306
81325
  // src/project/productionDeliveryScope.ts
81307
81326
  import { readFile as readFile35 } from "node:fs/promises";
81308
- import { join as join39, posix as posix2 } from "node:path";
81327
+ import { join as join40, posix as posix2 } from "node:path";
81309
81328
  async function productionDeliverableArticles(root, phase = "delivery") {
81310
81329
  return withProductionFeedback({ operation: "delivery-scope" }, async () => {
81311
81330
  const stage = await readProductionStage(root);
@@ -81332,7 +81351,7 @@ async function productionDeliverableArticles(root, phase = "delivery") {
81332
81351
  if (phase === "review")
81333
81352
  return [...selected.values()];
81334
81353
  for (const article of selected.values()) {
81335
- const markdown = await readFile35(await safeProjectTarget(root, join39("knowledge", article.path)), "utf8");
81354
+ const markdown = await readFile35(await safeProjectTarget(root, join40("knowledge", article.path)), "utf8");
81336
81355
  for (const link of markdownReaderLinks(markdown)) {
81337
81356
  if (link.image || /^(?:[a-z][a-z\d+.-]*:|\/|#)/iu.test(link.target))
81338
81357
  continue;
@@ -81348,7 +81367,7 @@ async function productionDeliverableArticles(root, phase = "delivery") {
81348
81367
  if (path2.startsWith("../") || unresolved.has(path2) || !formal.byPath.has(path2)) {
81349
81368
  throw new TypeError(`Partial delivery needs its linked approved article: ${article.path} → ${path2}. Finish that article's Review before delivery.`);
81350
81369
  }
81351
- await readFile35(await safeProjectTarget(root, join39("knowledge", path2)), "utf8");
81370
+ await readFile35(await safeProjectTarget(root, join40("knowledge", path2)), "utf8");
81352
81371
  }
81353
81372
  }
81354
81373
  return [...selected.values()];
@@ -81367,9 +81386,9 @@ var init_productionDeliveryScope = __esm(() => {
81367
81386
 
81368
81387
  // src/project/siteTheme.ts
81369
81388
  import { mkdir as mkdir17, readFile as readFile36, writeFile as writeFile11 } from "node:fs/promises";
81370
- import { dirname as dirname20, join as join40 } from "node:path";
81389
+ import { dirname as dirname20, join as join41 } from "node:path";
81371
81390
  async function resolveSiteTheme(root, overrides, scaffold = false) {
81372
- const path2 = join40(root, SITE_THEME_FILE);
81391
+ const path2 = join41(root, SITE_THEME_FILE);
81373
81392
  let file = {};
81374
81393
  try {
81375
81394
  file = siteThemeSchema.parse(JSON.parse(await readFile36(path2, "utf8")));
@@ -81470,10 +81489,10 @@ import { createHash as createHash11 } from "node:crypto";
81470
81489
  import { execFile as execFile7 } from "node:child_process";
81471
81490
  import { promisify as promisify7 } from "node:util";
81472
81491
  import { readFile as readFile37, lstat as lstat6, readdir as readdir9, realpath as realpath6 } from "node:fs/promises";
81473
- import { join as join41 } from "node:path";
81492
+ import { join as join42 } from "node:path";
81474
81493
  async function optionalWorkspaceText(root, path2) {
81475
81494
  try {
81476
- return await readFile37(join41(root, path2), "utf8");
81495
+ return await readFile37(join42(root, path2), "utf8");
81477
81496
  } catch (error) {
81478
81497
  if (error.code === "ENOENT")
81479
81498
  return;
@@ -81485,7 +81504,7 @@ async function readWorkspaceChangelog(root) {
81485
81504
  return value === undefined ? [] : ledgerSchema.parse(import_yaml28.parse(value)).entries;
81486
81505
  }
81487
81506
  async function workspaceVersion(root) {
81488
- const manifest = JSON.parse(await readFile37(join41(root, "package.json"), "utf8"));
81507
+ const manifest = JSON.parse(await readFile37(join42(root, "package.json"), "utf8"));
81489
81508
  return semver.parse(manifest.version ?? "0.0.0");
81490
81509
  }
81491
81510
  function excluded(path2) {
@@ -81506,7 +81525,7 @@ async function workspaceContentSnapshot(root) {
81506
81525
  if (paths === undefined) {
81507
81526
  const discovered = [];
81508
81527
  const visit3 = async (dir) => {
81509
- for (const entry of await readdir9(join41(root, dir), { withFileTypes: true })) {
81528
+ for (const entry of await readdir9(join42(root, dir), { withFileTypes: true })) {
81510
81529
  const path2 = dir ? `${dir}/${entry.name}` : entry.name;
81511
81530
  if (excluded(path2))
81512
81531
  continue;
@@ -81523,9 +81542,9 @@ async function workspaceContentSnapshot(root) {
81523
81542
  for (const path2 of [...new Set(paths)].filter((path3) => !excluded(path3)).sort()) {
81524
81543
  let bytes;
81525
81544
  try {
81526
- if (!(await lstat6(join41(root, path2))).isFile())
81545
+ if (!(await lstat6(join42(root, path2))).isFile())
81527
81546
  continue;
81528
- bytes = await readFile37(join41(root, path2));
81547
+ bytes = await readFile37(join42(root, path2));
81529
81548
  } catch (error) {
81530
81549
  if (error.code === "ENOENT")
81531
81550
  continue;
@@ -81610,7 +81629,7 @@ async function recordWorkspaceVersion(root, value) {
81610
81629
  const { expected_digest: _, base_ref: _base, ...fields } = input;
81611
81630
  const entry = changelogEntrySchema.parse({ ...fields, date: new Date().toISOString(), ...actor ? { actor } : {} });
81612
81631
  const entries = [entry, ...amend ? previousEntries.slice(1) : previousEntries];
81613
- const manifest = JSON.parse(await readFile37(join41(root, "package.json"), "utf8"));
81632
+ const manifest = JSON.parse(await readFile37(join42(root, "package.json"), "utf8"));
81614
81633
  manifest.version = entry.version;
81615
81634
  const writes = {
81616
81635
  "package.json": JSON.stringify(manifest, null, 2) + `
@@ -81625,7 +81644,7 @@ async function recordWorkspaceVersion(root, value) {
81625
81644
  targets.sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
81626
81645
  await runDurableMultiFileTransaction({ projectRoot: root, kind: "record-workspace-version", proposal_digest: hash2(writes), targets });
81627
81646
  try {
81628
- await atomicWriteFile(join41(root, VERSION_CHECKPOINT), JSON.stringify({ version: entry.version, digest: status.content_digest }) + `
81647
+ await atomicWriteFile(join42(root, VERSION_CHECKPOINT), JSON.stringify({ version: entry.version, digest: status.content_digest }) + `
81629
81648
  `);
81630
81649
  } catch {}
81631
81650
  return { version: entry.version, next_action: { command: "context status --format json" } };
@@ -81664,7 +81683,7 @@ __export(exports_workspacePreparation, {
81664
81683
  PREPARATION_ROOTS: () => PREPARATION_ROOTS
81665
81684
  });
81666
81685
  import { lstat as lstat7, readFile as readFile38, readdir as readdir10 } from "node:fs/promises";
81667
- import { join as join42 } from "node:path";
81686
+ import { join as join43 } from "node:path";
81668
81687
  function failure(reason, message, next) {
81669
81688
  throw new ContextError(ExitCode.WorkspaceStateError, message, {
81670
81689
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -81676,7 +81695,7 @@ async function entries(root, path2) {
81676
81695
  await safeProjectTarget(root, path2);
81677
81696
  let stat8;
81678
81697
  try {
81679
- stat8 = await lstat7(join42(root, path2));
81698
+ stat8 = await lstat7(join43(root, path2));
81680
81699
  } catch (error) {
81681
81700
  if (error.code === "ENOENT")
81682
81701
  return [];
@@ -81689,8 +81708,8 @@ async function entries(root, path2) {
81689
81708
  if (!stat8.isDirectory())
81690
81709
  failure("preparation-file-type", `Unsupported task-state file: ${path2}`, "Inspect this file before preparing the workspace.");
81691
81710
  const result = [];
81692
- for (const name3 of (await readdir10(join42(root, path2))).sort())
81693
- result.push(...await entries(root, join42(path2, name3)));
81711
+ for (const name3 of (await readdir10(join43(root, path2))).sort())
81712
+ result.push(...await entries(root, join43(path2, name3)));
81694
81713
  return result;
81695
81714
  }
81696
81715
  async function pendingJournals(root) {
@@ -81698,7 +81717,7 @@ async function pendingJournals(root) {
81698
81717
  const result = [];
81699
81718
  for (const path2 of files.filter((path3) => path3.endsWith("/journal.json") || path3.endsWith(".journal.json"))) {
81700
81719
  try {
81701
- result.push({ ...JSON.parse(await readFile38(join42(root, path2), "utf8")), path: path2 });
81720
+ result.push({ ...JSON.parse(await readFile38(join43(root, path2), "utf8")), path: path2 });
81702
81721
  } catch {
81703
81722
  result.push({ path: path2 });
81704
81723
  }
@@ -81728,7 +81747,7 @@ async function prepareWorkspace(input) {
81728
81747
  const targets = [];
81729
81748
  for (const directory of PREPARATION_ROOTS)
81730
81749
  for (const path2 of await entries(input.projectRoot, directory)) {
81731
- const bytes = await readFile38(join42(input.projectRoot, path2));
81750
+ const bytes = await readFile38(join43(input.projectRoot, path2));
81732
81751
  let content3;
81733
81752
  try {
81734
81753
  content3 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
@@ -81740,7 +81759,7 @@ async function prepareWorkspace(input) {
81740
81759
  const markerContent = JSON.stringify(taskPreparationRecord("cleared"));
81741
81760
  let oldMarker;
81742
81761
  try {
81743
- oldMarker = await readFile38(join42(input.projectRoot, TASK_PREPARATION_PATH), "utf8");
81762
+ oldMarker = await readFile38(join43(input.projectRoot, TASK_PREPARATION_PATH), "utf8");
81744
81763
  } catch (error) {
81745
81764
  if (error.code !== "ENOENT")
81746
81765
  throw error;
@@ -81814,14 +81833,14 @@ __export(exports_taskResumption, {
81814
81833
  TASK_PREPARATION_PATH: () => TASK_PREPARATION_PATH
81815
81834
  });
81816
81835
  import { readFile as readFile39 } from "node:fs/promises";
81817
- import { join as join43 } from "node:path";
81836
+ import { join as join44 } from "node:path";
81818
81837
  function taskPreparationRecord(state) {
81819
81838
  return { protocol: "context.task-preparation/v1", state };
81820
81839
  }
81821
81840
  async function readTaskPreparation(root) {
81822
81841
  let text7;
81823
81842
  try {
81824
- text7 = await readFile39(join43(root, TASK_PREPARATION_PATH), "utf8");
81843
+ text7 = await readFile39(join44(root, TASK_PREPARATION_PATH), "utf8");
81825
81844
  } catch (error) {
81826
81845
  if (error.code !== "ENOENT")
81827
81846
  throw error;
@@ -81867,9 +81886,9 @@ var init_taskResumption = __esm(() => {
81867
81886
 
81868
81887
  // src/project/productionCleanup.ts
81869
81888
  import { readFile as readFile40, readdir as readdir11, rm as rm9 } from "node:fs/promises";
81870
- import { join as join44 } from "node:path";
81889
+ import { join as join45 } from "node:path";
81871
81890
  async function clearCompletedProduction(root, stage) {
81872
- const pointerPath = join44(PRODUCTION_STAGES_ROOT, "current.json");
81891
+ const pointerPath = join45(PRODUCTION_STAGES_ROOT, "current.json");
81873
81892
  const pointer = await readFile40(await safeProjectTarget(root, pointerPath), "utf8");
81874
81893
  const current2 = JSON.parse(pointer);
81875
81894
  if (!current2 || typeof current2 !== "object" || !("stage" in current2) || current2.stage !== stage.id) {
@@ -81881,9 +81900,9 @@ async function clearCompletedProduction(root, stage) {
81881
81900
  const entries2 = await readdir11(await safeProjectTarget(root, directory));
81882
81901
  for (const entry of entries2)
81883
81902
  if (entry !== "manifest.json")
81884
- await remove(join44(directory, entry));
81903
+ await remove(join45(directory, entry));
81885
81904
  const targets = [];
81886
- for (const path2 of [join44(directory, "manifest.json"), pointerPath]) {
81905
+ for (const path2 of [join45(directory, "manifest.json"), pointerPath]) {
81887
81906
  const content4 = path2 === pointerPath ? pointer : await readFile40(await safeProjectTarget(root, path2), "utf8");
81888
81907
  targets.push({ path: path2, operation: "delete", base_digest: durableContentDigest(content4), target_digest: null });
81889
81908
  }
@@ -81923,7 +81942,7 @@ __export(exports_lifecycleCleanup, {
81923
81942
  clearCompletedLifecycle: () => clearCompletedLifecycle
81924
81943
  });
81925
81944
  import { readdir as readdir12, rm as rm10 } from "node:fs/promises";
81926
- import { join as join45 } from "node:path";
81945
+ import { join as join46 } from "node:path";
81927
81946
  async function clearCompletedLifecycle(projectRoot) {
81928
81947
  const production = await readProductionStage(projectRoot);
81929
81948
  if (production) {
@@ -81940,9 +81959,9 @@ async function clearCompletedLifecycle(projectRoot) {
81940
81959
  }
81941
81960
  for (const path2 of COMPLETED_RUNTIME_PATHS) {
81942
81961
  if (path2 !== INDEXER_RUNTIME_ROOT)
81943
- await rm10(join45(projectRoot, path2), { recursive: true, force: true });
81962
+ await rm10(join46(projectRoot, path2), { recursive: true, force: true });
81944
81963
  }
81945
- const indexer = join45(projectRoot, INDEXER_RUNTIME_ROOT);
81964
+ const indexer = join46(projectRoot, INDEXER_RUNTIME_ROOT);
81946
81965
  const entries2 = await readdir12(indexer).catch((error) => {
81947
81966
  if (error.code === "ENOENT")
81948
81967
  return [];
@@ -81950,9 +81969,9 @@ async function clearCompletedLifecycle(projectRoot) {
81950
81969
  });
81951
81970
  for (const name3 of entries2)
81952
81971
  if (name3 !== "candidate-compile") {
81953
- await rm10(join45(indexer, name3), { recursive: true, force: true });
81972
+ await rm10(join46(indexer, name3), { recursive: true, force: true });
81954
81973
  }
81955
- const compile = join45(indexer, "candidate-compile");
81974
+ const compile = join46(indexer, "candidate-compile");
81956
81975
  const compiled = await readdir12(compile).catch((error) => {
81957
81976
  if (error.code === "ENOENT")
81958
81977
  return [];
@@ -81960,11 +81979,11 @@ async function clearCompletedLifecycle(projectRoot) {
81960
81979
  });
81961
81980
  for (const name3 of compiled)
81962
81981
  if (name3 !== "current.json") {
81963
- await rm10(join45(compile, name3), { recursive: true, force: true });
81982
+ await rm10(join46(compile, name3), { recursive: true, force: true });
81964
81983
  }
81965
- await rm10(join45(compile, "current.json"), { force: true });
81984
+ await rm10(join46(compile, "current.json"), { force: true });
81966
81985
  await rm10(indexer, { recursive: true, force: true });
81967
- await rm10(join45(projectRoot, APPROVED_REVISION_PATH), { force: true });
81986
+ await rm10(join46(projectRoot, APPROVED_REVISION_PATH), { force: true });
81968
81987
  if (production)
81969
81988
  await clearCompletedProduction(projectRoot, production);
81970
81989
  }
@@ -82138,7 +82157,7 @@ var init_indexerRequiredArticleReview = __esm(() => {
82138
82157
  // src/project/partialDelivery.ts
82139
82158
  import { existsSync as existsSync8 } from "node:fs";
82140
82159
  import { readFile as readFile41 } from "node:fs/promises";
82141
- import { join as join46, posix as posix3 } from "node:path";
82160
+ import { join as join47, posix as posix3 } from "node:path";
82142
82161
  async function selectPartialDelivery(root) {
82143
82162
  const candidates = await readCandidateRecords(root);
82144
82163
  if (!candidates.some((item) => item.status === "draft"))
@@ -82152,7 +82171,7 @@ async function selectPartialDelivery(root) {
82152
82171
  }
82153
82172
  const pages = [...revision.batch_candidates ?? [], ...revision.candidate ? [revision.candidate] : []].map((item) => ({ path: `knowledge/${item.path}`, ref: item.article_id }));
82154
82173
  const unresolved = new Set(candidates.map((item) => `knowledge/${item.path}`));
82155
- const approved = pages.filter((item) => !unresolved.has(item.path) && existsSync8(join46(root, item.path)));
82174
+ const approved = pages.filter((item) => !unresolved.has(item.path) && existsSync8(join47(root, item.path)));
82156
82175
  if (approved.length === 0)
82157
82176
  return;
82158
82177
  await assertIndependentPages(root, approved.map((item) => item.path), unresolved);
@@ -82162,7 +82181,7 @@ async function assertIndependentPages(root, paths, unresolved) {
82162
82181
  for (const path2 of paths) {
82163
82182
  if (unresolved.has(path2))
82164
82183
  throw new TypeError(`Selected delivery page now needs Review: ${path2}. Return to the current Route.`);
82165
- const markdown = await readFile41(join46(root, path2), "utf8");
82184
+ const markdown = await readFile41(join47(root, path2), "utf8");
82166
82185
  for (const link of markdownReaderLinks(markdown)) {
82167
82186
  if (link.image || /^(?:[a-z][a-z\d+.-]*:|\/|#)/iu.test(link.target))
82168
82187
  continue;
@@ -82173,7 +82192,7 @@ async function assertIndependentPages(root, paths, unresolved) {
82173
82192
  continue;
82174
82193
  }
82175
82194
  const target = posix3.normalize(posix3.join(posix3.dirname(path2), href));
82176
- if (target.startsWith("knowledge/") && /\.md$/iu.test(target) && (unresolved.has(target) || !existsSync8(join46(root, target)))) {
82195
+ if (target.startsWith("knowledge/") && /\.md$/iu.test(target) && (unresolved.has(target) || !existsSync8(join47(root, target)))) {
82177
82196
  throw new TypeError(`Partial delivery must include its linked page: ${path2} → ${target}. Finish that page's Review/repair, then request delivery again; existing approvals remain.`);
82178
82197
  }
82179
82198
  }
@@ -82201,10 +82220,10 @@ var init_partialDelivery = __esm(() => {
82201
82220
 
82202
82221
  // src/project/revisionDelivery.ts
82203
82222
  import { readFile as readFile42, rm as rm11 } from "node:fs/promises";
82204
- import { join as join47 } from "node:path";
82223
+ import { join as join48 } from "node:path";
82205
82224
  async function readRevisionDelivery(root) {
82206
82225
  try {
82207
- return stateSchema2.parse(JSON.parse(await readFile42(join47(root, FILE), "utf8")));
82226
+ return stateSchema2.parse(JSON.parse(await readFile42(join48(root, FILE), "utf8")));
82208
82227
  } catch (error) {
82209
82228
  if (error.code === "ENOENT")
82210
82229
  return;
@@ -82215,7 +82234,7 @@ function requestRevisionDelivery(root) {
82215
82234
  return withProjectWriteLock(root, "request-revision-delivery", async () => {
82216
82235
  const partial = await selectPartialDelivery(root);
82217
82236
  if (partial) {
82218
- await atomicWriteFile(join47(root, FILE), JSON.stringify(stateSchema2.parse({ partial, closed: false })) + `
82237
+ await atomicWriteFile(join48(root, FILE), JSON.stringify(stateSchema2.parse({ partial, closed: false })) + `
82219
82238
  `);
82220
82239
  return;
82221
82240
  }
@@ -82233,7 +82252,7 @@ function closeRevisionDelivery(root) {
82233
82252
  const state = await readRevisionDelivery(root);
82234
82253
  if (!state)
82235
82254
  return false;
82236
- await atomicWriteFile(join47(root, FILE), JSON.stringify({ ...state, closed: true }) + `
82255
+ await atomicWriteFile(join48(root, FILE), JSON.stringify({ ...state, closed: true }) + `
82237
82256
  `);
82238
82257
  return true;
82239
82258
  });
@@ -82241,7 +82260,7 @@ function closeRevisionDelivery(root) {
82241
82260
  function completeRevisionDelivery(root) {
82242
82261
  return withProjectWriteLock(root, "complete-revision-delivery", async () => {
82243
82262
  if ((await readRevisionDelivery(root))?.closed)
82244
- await rm11(join47(root, FILE), { force: true });
82263
+ await rm11(join48(root, FILE), { force: true });
82245
82264
  });
82246
82265
  }
82247
82266
  var FILE, stateSchema2;
@@ -82256,7 +82275,7 @@ var init_revisionDelivery = __esm(() => {
82256
82275
  init_partialDelivery();
82257
82276
  init_approvedRevision();
82258
82277
  init_candidateLedger();
82259
- FILE = join47(LIFECYCLE_ROOT, "revision-delivery.json");
82278
+ FILE = join48(LIFECYCLE_ROOT, "revision-delivery.json");
82260
82279
  stateSchema2 = exports_external.object({
82261
82280
  partial: exports_external.object({
82262
82281
  kind: exports_external.literal("revision"),
@@ -82269,7 +82288,7 @@ var init_revisionDelivery = __esm(() => {
82269
82288
 
82270
82289
  // src/project/approvedKnowledgeSnapshots.ts
82271
82290
  import { readFile as readFile43 } from "node:fs/promises";
82272
- import { join as join48 } from "node:path";
82291
+ import { join as join49 } from "node:path";
82273
82292
  function approvedKnowledgeSnapshotsFromStructure(structure) {
82274
82293
  return validateArticleStructureEntries(structure?.articles ?? []);
82275
82294
  }
@@ -82278,7 +82297,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
82278
82297
  return;
82279
82298
  let before;
82280
82299
  try {
82281
- before = await readFile43(join48(input.projectRoot, STRUCTURE_PATH2), "utf8");
82300
+ before = await readFile43(join49(input.projectRoot, STRUCTURE_PATH2), "utf8");
82282
82301
  } catch (error) {
82283
82302
  if (error.code !== "ENOENT")
82284
82303
  throw error;
@@ -82341,7 +82360,7 @@ import {
82341
82360
  unlinkSync,
82342
82361
  writeFileSync as writeFileSync2
82343
82362
  } from "node:fs";
82344
- import { dirname as dirname21, join as join49 } from "node:path";
82363
+ import { dirname as dirname21, join as join50 } from "node:path";
82345
82364
  function isRecord10(value) {
82346
82365
  return value !== null && typeof value === "object" && !Array.isArray(value);
82347
82366
  }
@@ -82359,7 +82378,7 @@ function parseEvent(value) {
82359
82378
  };
82360
82379
  }
82361
82380
  function runtimeEventOutboxPath(projectRoot) {
82362
- return join49(projectRoot, OUTBOX_RELATIVE_PATH);
82381
+ return join50(projectRoot, OUTBOX_RELATIVE_PATH);
82363
82382
  }
82364
82383
  function readRuntimeEventOutboxFile(path2) {
82365
82384
  if (!existsSync9(path2))
@@ -82490,7 +82509,7 @@ function acknowledgeRuntimeEventOutbox(projectRoot, eventIds) {
82490
82509
  }
82491
82510
  var OUTBOX_EVENT_SCHEMA = "context.runtime-event-outbox.event.v1", OUTBOX_ACK_SCHEMA = "context.runtime-event-outbox.ack.v1", OUTBOX_RELATIVE_PATH, OUTBOX_LOCK_STALE_MS = 30000, OUTBOX_LOCK_RETRY_MS = 10, OUTBOX_LOCK_RETRIES = 100;
82492
82511
  var init_runtimeEventOutbox = __esm(() => {
82493
- OUTBOX_RELATIVE_PATH = join49(".tmp", "context-runtime", "logs", "outbox.jsonl");
82512
+ OUTBOX_RELATIVE_PATH = join50(".tmp", "context-runtime", "logs", "outbox.jsonl");
82494
82513
  });
82495
82514
 
82496
82515
  // src/runtimeEvents.ts
@@ -82503,7 +82522,7 @@ import {
82503
82522
  writeFileSync as writeFileSync3
82504
82523
  } from "node:fs";
82505
82524
  import { spawn as spawn2 } from "node:child_process";
82506
- import { dirname as dirname22, join as join50 } from "node:path";
82525
+ import { dirname as dirname22, join as join51 } from "node:path";
82507
82526
  import { fileURLToPath as fileURLToPath3 } from "node:url";
82508
82527
  function isRecord11(value) {
82509
82528
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -82606,7 +82625,7 @@ function readRuntimePackageMetadata() {
82606
82625
  try {
82607
82626
  let dir = dirname22(fileURLToPath3(import.meta.url));
82608
82627
  for (let index2 = 0;index2 < 8; index2++) {
82609
- const packagePath = join50(dir, "package.json");
82628
+ const packagePath = join51(dir, "package.json");
82610
82629
  if (existsSync10(packagePath)) {
82611
82630
  const parsed = JSON.parse(readFileSync5(packagePath, "utf8"));
82612
82631
  if (isRecord11(parsed)) {
@@ -82743,7 +82762,7 @@ function dispatchCommand(sink, batch, cwd) {
82743
82762
  });
82744
82763
  }
82745
82764
  function runtimeEventStatePath(cwd) {
82746
- return join50(cwd, ".tmp", "context-runtime", RUNTIME_EVENT_STATE_FILE);
82765
+ return join51(cwd, ".tmp", "context-runtime", RUNTIME_EVENT_STATE_FILE);
82747
82766
  }
82748
82767
  function readRuntimeEventState(cwd) {
82749
82768
  try {
@@ -83099,10 +83118,10 @@ var init_approvedStructureInputHash = () => {};
83099
83118
 
83100
83119
  // src/project/verifyApprovedStructure.ts
83101
83120
  import { existsSync as existsSync11 } from "node:fs";
83102
- import { join as join51 } from "node:path";
83121
+ import { join as join52 } from "node:path";
83103
83122
  async function validateApprovedStructure(input) {
83104
83123
  const issue = (code, path3, message) => input.issues.push({ severity: "error", code, path: path3, message });
83105
- const path2 = join51(input.projectRoot, STRUCTURE_PATH3);
83124
+ const path2 = join52(input.projectRoot, STRUCTURE_PATH3);
83106
83125
  if (!input.structureOverride && !existsSync11(path2))
83107
83126
  return;
83108
83127
  let parsed;
@@ -83170,7 +83189,7 @@ var init_verifyApprovedStructure = __esm(() => {
83170
83189
  import { createHash as createHash13 } from "node:crypto";
83171
83190
  import { existsSync as existsSync12 } from "node:fs";
83172
83191
  import { mkdir as mkdir18, readFile as readFile44, readdir as readdir13, writeFile as writeFile12 } from "node:fs/promises";
83173
- import { dirname as dirname23, join as join52, relative as relative15, resolve as resolve20 } from "node:path";
83192
+ import { dirname as dirname23, join as join53, relative as relative15, resolve as resolve20 } from "node:path";
83174
83193
  async function templateFiles(root) {
83175
83194
  if (!existsSync12(root))
83176
83195
  return [];
@@ -83178,7 +83197,7 @@ async function templateFiles(root) {
83178
83197
  const visit3 = async (dir) => {
83179
83198
  const entries2 = await readdir13(dir, { withFileTypes: true });
83180
83199
  for (const entry of entries2) {
83181
- const absolutePath = join52(dir, entry.name);
83200
+ const absolutePath = join53(dir, entry.name);
83182
83201
  if (entry.isDirectory()) {
83183
83202
  await visit3(absolutePath);
83184
83203
  continue;
@@ -83205,7 +83224,7 @@ function isMarker(value) {
83205
83224
  return marker.schema === PACKAGE_TEMPLATE_REVIEW_SCHEMA && /^sha256:[a-f0-9]{64}$/u.test(marker.starter_digest ?? "") && (marker.disposition === "review-required" || marker.disposition === "starter-accepted");
83206
83225
  }
83207
83226
  async function readMarker(templateRoot) {
83208
- const markerPath = join52(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
83227
+ const markerPath = join53(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
83209
83228
  if (!existsSync12(markerPath))
83210
83229
  return null;
83211
83230
  try {
@@ -83216,7 +83235,7 @@ async function readMarker(templateRoot) {
83216
83235
  }
83217
83236
  }
83218
83237
  async function writeStarterTemplateReviewMarker(templateRoot) {
83219
- const markerPath = join52(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
83238
+ const markerPath = join53(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
83220
83239
  if (existsSync12(markerPath))
83221
83240
  return false;
83222
83241
  const marker = {
@@ -83244,7 +83263,7 @@ async function inspectPackageTemplateReview(projectRoot, pkg) {
83244
83263
  packageName: pkg.name,
83245
83264
  templatePath: pkg.template.path,
83246
83265
  state: "invalid",
83247
- diagnostic: `${join52(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
83266
+ diagnostic: `${join53(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
83248
83267
  };
83249
83268
  }
83250
83269
  const currentDigest2 = await templateDigest(templateRoot);
@@ -83285,8 +83304,8 @@ async function acceptStarterPackageTemplates(input) {
83285
83304
  alreadyResolved.push(pkg.name);
83286
83305
  continue;
83287
83306
  }
83288
- const markerPath = join52(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
83289
- const marker = await readMarker(join52(input.projectRoot, pkg.template.path));
83307
+ const markerPath = join53(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
83308
+ const marker = await readMarker(join53(input.projectRoot, pkg.template.path));
83290
83309
  if (marker === null || marker === "invalid") {
83291
83310
  throw new ContextError(ExitCode.WorkspaceStateError, "package template review marker changed before acceptance", {
83292
83311
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -83457,8 +83476,8 @@ function renderAgents(projectName, language) {
83457
83476
  "",
83458
83477
  "## 工作区契约",
83459
83478
  "",
83460
- "版本以 package.json.version 为准。正式内容变化收尾时通过 context version inspect / record 同步递增版本并生成 changelog.yaml 和 CHANGELOG.md,具体说明由 Agent 根据 diff 和会话撰写。新增模块或扩大知识覆盖升 minor,普通修补、目录和正式状态变化升 patch;major 只由人工明确指定。.tmp 进度不算变化,build 只记录 hash。仅主协调者记录版本,不自动 commit 或发布。触发来源必填;触发用户优先使用会话中明确的飞书显示名,否则由 CLI 读取 Git 用户名。",
83461
- "版本差异使用 Git 比较正文、结构、资源、导航和模板;可通过 version inspect --base 指定交付 commit/tag。构建预览不锁定版本;复用版本前核对目标平台与 Git tag,已发布版本必须递增。无需维护根目录 Context 版本、构建或发布回执。",
83479
+ "版本以 package.json.version 为准。正式内容变化收尾时通过 context version inspect / record 同步递增版本并生成 changelog.yaml 和 CHANGELOG.md,具体说明由 Agent 根据 diff 和会话撰写。新增模块或扩大知识覆盖升 minor,普通修补、目录和正式状态变化升 patch;major 只由人工明确指定。.tmp 进度不算变化,build 只记录 hash。仅主协调者记录版本;版本记录本身不提交或发布,后续交付按本次授权和已安装的分发技能执行。触发来源必填;触发用户优先使用会话中明确的飞书显示名,否则由 CLI 读取 Git 用户名。",
83480
+ "版本差异使用 Git 比较正文、结构、资源、导航和模板;可通过 version inspect --base 指定交付 commit/tag。构建预览不锁定版本,已发布内容发生变化时必须递增版本。无需维护根目录 Context 版本、构建或发布回执。",
83462
83481
  "每个版本的 Changelog 详情不得超过 1500 字:标题、变更列表、触发来源说明及用户显示名的可见字符合计计数,含标点,不计协议字段名、版本号和日期。超出时由 Agent 在提交前合并同类变化、删除重复过程描述,压缩至上限内;保留主要变化、影响和触发来源,不直接截断,也不把一轮拆成多个版本规避限制。",
83463
83482
  "",
83464
83483
  "- 通过已安装的 Context Skill 开始或恢复工作;直接使用 CLI 时,从 `context status --format json` 开始。",
@@ -83503,8 +83522,8 @@ function renderAgents(projectName, language) {
83503
83522
  "",
83504
83523
  "## Workspace Contract",
83505
83524
  "",
83506
- "package.json.version is the workspace version. At formal-content completion, use context version inspect / record to increment SemVer and generate changelog.yaml and CHANGELOG.md together. Write descriptions from the diff and conversation. Added modules/coverage increment minor; repairs, navigation and persistent status changes increment patch. Major requires an explicit user instruction. Ignore .tmp progress; build only records hashes. The coordinator alone records versions, without automatic commits or publishing. Triggers are required; use an explicitly known conversational Lark display name, otherwise let CLI use Git user.name.",
83507
- "Compare bodies, structure, assets, navigation and templates using Git; version inspect --base selects a delivery commit/tag. Preview builds do not seal versions. Check the remote target and Git tags before amending; published versions must increase. No root Context version/build/publication receipts are required.",
83525
+ "package.json.version is the workspace version. At formal-content completion, use context version inspect / record to increment SemVer and generate changelog.yaml and CHANGELOG.md together. Write descriptions from the diff and conversation. Added modules/coverage increment minor; repairs, navigation and persistent status changes increment patch. Major requires an explicit user instruction. Ignore .tmp progress; build only records hashes. The coordinator alone records versions; recording a version does not commit or publish, and later delivery follows this task's authorization and the installed distribution skill. Triggers are required; use an explicitly known conversational Lark display name, otherwise let CLI use Git user.name.",
83526
+ "Compare bodies, structure, assets, navigation and templates using Git; version inspect --base selects a delivery commit/tag. Preview builds do not seal versions. Changes to already published content must increment the version. No root Context version/build/publication receipts are required.",
83508
83527
  "Each version's changelog details must total at most 1500 visible characters, including punctuation across the title, changes, trigger descriptions and user display name; exclude protocol keys, version and date. Before submission, compress longer entries by merging related changes and removing repeated process narration. Preserve the main changes, impact and triggers; never truncate blindly or split one iteration into multiple versions to evade the limit.",
83509
83528
  "",
83510
83529
  "- Start or resume through the installed Context Skill. When using the CLI directly, begin with `context status --format json`.",
@@ -83574,14 +83593,14 @@ __export(exports_workspace, {
83574
83593
  import { existsSync as existsSync13, readFileSync as readFileSync6, statSync as statSync3 } from "node:fs";
83575
83594
  import { mkdir as mkdir19, readFile as readFile45, readdir as readdir14, writeFile as writeFile13 } from "node:fs/promises";
83576
83595
  import { createRequire as createRequire4 } from "node:module";
83577
- import { basename as basename7, dirname as dirname24, isAbsolute as isAbsolute12, join as join53, parse as parse9, relative as relative16, resolve as resolve21 } from "node:path";
83596
+ import { basename as basename7, dirname as dirname24, isAbsolute as isAbsolute12, join as join54, parse as parse9, relative as relative16, resolve as resolve21 } from "node:path";
83578
83597
  import { fileURLToPath as fileURLToPath4 } from "node:url";
83579
83598
  import { createJiti } from "jiti";
83580
83599
  function isRecord12(value) {
83581
83600
  return value !== null && typeof value === "object" && !Array.isArray(value);
83582
83601
  }
83583
83602
  function readPackageJson(root) {
83584
- const packagePath = join53(root, "package.json");
83603
+ const packagePath = join54(root, "package.json");
83585
83604
  if (!existsSync13(packagePath))
83586
83605
  return null;
83587
83606
  try {
@@ -83605,22 +83624,22 @@ function resolveExportImportTarget(packageJsonPath) {
83605
83624
  return null;
83606
83625
  const exportsField = parsed.exports;
83607
83626
  if (typeof exportsField === "string") {
83608
- return join53(dirname24(packageJsonPath), exportsField);
83627
+ return join54(dirname24(packageJsonPath), exportsField);
83609
83628
  }
83610
83629
  if (isRecord12(exportsField)) {
83611
83630
  const rootExport = exportsField["."];
83612
83631
  if (typeof rootExport === "string") {
83613
- return join53(dirname24(packageJsonPath), rootExport);
83632
+ return join54(dirname24(packageJsonPath), rootExport);
83614
83633
  }
83615
83634
  if (isRecord12(rootExport) && typeof rootExport.import === "string") {
83616
- return join53(dirname24(packageJsonPath), rootExport.import);
83635
+ return join54(dirname24(packageJsonPath), rootExport.import);
83617
83636
  }
83618
83637
  }
83619
83638
  if (typeof parsed.module === "string") {
83620
- return join53(dirname24(packageJsonPath), parsed.module);
83639
+ return join54(dirname24(packageJsonPath), parsed.module);
83621
83640
  }
83622
83641
  if (typeof parsed.main === "string") {
83623
- return join53(dirname24(packageJsonPath), parsed.main);
83642
+ return join54(dirname24(packageJsonPath), parsed.main);
83624
83643
  }
83625
83644
  return null;
83626
83645
  }
@@ -83638,7 +83657,7 @@ function resolveContextSdkImportAlias(entryPath) {
83638
83657
  function readCurrentPackageVersion() {
83639
83658
  let dir = dirname24(fileURLToPath4(import.meta.url));
83640
83659
  for (let index2 = 0;index2 < 8; index2++) {
83641
- const packagePath = join53(dir, "package.json");
83660
+ const packagePath = join54(dir, "package.json");
83642
83661
  if (existsSync13(packagePath)) {
83643
83662
  const parsed = readPackageJson(dir);
83644
83663
  if (typeof parsed?.version === "string" && parsed.version.trim().length > 0) {
@@ -83821,7 +83840,7 @@ async function listStaticTemplateFiles(root, dir = root) {
83821
83840
  const entries2 = await readdir14(dir, { withFileTypes: true });
83822
83841
  const files = [];
83823
83842
  for (const entry of entries2) {
83824
- const absolutePath = join53(dir, entry.name);
83843
+ const absolutePath = join54(dir, entry.name);
83825
83844
  if (entry.isDirectory()) {
83826
83845
  files.push(...await listStaticTemplateFiles(root, absolutePath));
83827
83846
  continue;
@@ -83838,7 +83857,7 @@ async function listStaticTemplateFiles(root, dir = root) {
83838
83857
  function resolveContextPackageTemplatesRoot() {
83839
83858
  try {
83840
83859
  const packageJsonPath = createRequire4(import.meta.url).resolve("@c4a/context/package.json");
83841
- const templateRoot = join53(dirname24(packageJsonPath), "templates", "package-templates");
83860
+ const templateRoot = join54(dirname24(packageJsonPath), "templates", "package-templates");
83842
83861
  if (existsSync13(templateRoot))
83843
83862
  return templateRoot;
83844
83863
  } catch {}
@@ -83850,7 +83869,7 @@ function resolveContextPackageTemplatesRoot() {
83850
83869
  }
83851
83870
  async function writeDefaultPackageTemplates(projectRoot, result, language) {
83852
83871
  const defaultRoot = resolveContextPackageTemplatesRoot();
83853
- const templateRoot = language === "zh-CN" ? join53(dirname24(defaultRoot), "package-templates.zh-CN") : defaultRoot;
83872
+ const templateRoot = language === "zh-CN" ? join54(dirname24(defaultRoot), "package-templates.zh-CN") : defaultRoot;
83854
83873
  if (!existsSync13(templateRoot)) {
83855
83874
  throw new ContextError(ExitCode.WorkspaceStateError, `missing ${language} @c4a/context package templates`, {
83856
83875
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -83860,15 +83879,15 @@ async function writeDefaultPackageTemplates(projectRoot, result, language) {
83860
83879
  }
83861
83880
  const files = await listStaticTemplateFiles(templateRoot);
83862
83881
  for (const file of files) {
83863
- await writeIfMissing(join53(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile45(file.absolutePath, "utf8"), result);
83882
+ await writeIfMissing(join54(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile45(file.absolutePath, "utf8"), result);
83864
83883
  }
83865
83884
  const templateKinds = [...new Set(files.map((file) => file.relativePath.split("/")[0]).filter((value) => value !== undefined && value.length > 0))];
83866
83885
  for (const templateKind of templateKinds) {
83867
- const root = join53(projectRoot, "src", "package-templates", templateKind);
83886
+ const root = join54(projectRoot, "src", "package-templates", templateKind);
83868
83887
  if (await writeStarterTemplateReviewMarker(root)) {
83869
- result.created.push(join53(root, PACKAGE_TEMPLATE_REVIEW_FILE));
83888
+ result.created.push(join54(root, PACKAGE_TEMPLATE_REVIEW_FILE));
83870
83889
  } else {
83871
- result.kept.push(join53(root, PACKAGE_TEMPLATE_REVIEW_FILE));
83890
+ result.kept.push(join54(root, PACKAGE_TEMPLATE_REVIEW_FILE));
83872
83891
  }
83873
83892
  }
83874
83893
  }
@@ -83958,23 +83977,23 @@ async function initContextProject(input) {
83958
83977
  kept: []
83959
83978
  };
83960
83979
  for (const dir of PROJECT_DIRS) {
83961
- await mkdir19(join53(projectRoot, dir), { recursive: true });
83980
+ await mkdir19(join54(projectRoot, dir), { recursive: true });
83962
83981
  }
83963
83982
  for (const dir of PROJECT_SCRATCH_DIRS) {
83964
- await mkdir19(join53(projectRoot, dir), { recursive: true });
83983
+ await mkdir19(join54(projectRoot, dir), { recursive: true });
83965
83984
  }
83966
- await mkdir19(join53(projectRoot, "sources", "repo"), { recursive: true });
83967
- await mkdir19(join53(projectRoot, "sources", "file"), { recursive: true });
83968
- await mkdir19(join53(projectRoot, "sources", "lark"), { recursive: true });
83969
- await writeIfMissing(join53(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
83970
- await writeIfMissing(join53(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
83985
+ await mkdir19(join54(projectRoot, "sources", "repo"), { recursive: true });
83986
+ await mkdir19(join54(projectRoot, "sources", "file"), { recursive: true });
83987
+ await mkdir19(join54(projectRoot, "sources", "lark"), { recursive: true });
83988
+ await writeIfMissing(join54(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
83989
+ await writeIfMissing(join54(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
83971
83990
  await writeDefaultPackageTemplates(projectRoot, result, language);
83972
- await writeIfMissing(join53(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
83973
- await writeIfMissing(join53(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
83974
- await writeIfMissing(join53(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
83975
- await writeIfMissing(join53(projectRoot, ".gitignore"), renderGitignore(), result);
83976
- await writeIfMissing(join53(projectRoot, "README.md"), renderReadme(projectName, language), result);
83977
- await writeIfMissing(join53(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
83991
+ await writeIfMissing(join54(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
83992
+ await writeIfMissing(join54(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
83993
+ await writeIfMissing(join54(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
83994
+ await writeIfMissing(join54(projectRoot, ".gitignore"), renderGitignore(), result);
83995
+ await writeIfMissing(join54(projectRoot, "README.md"), renderReadme(projectName, language), result);
83996
+ await writeIfMissing(join54(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
83978
83997
  if (input.debug === true)
83979
83998
  await enableContextDebug(projectRoot, "init");
83980
83999
  return result;
@@ -83988,7 +84007,7 @@ async function loadContextProjectModule(root) {
83988
84007
  next: "Ensure package.json declares context.project=true and context.entry points to src/index.ts, then rerun the command."
83989
84008
  });
83990
84009
  }
83991
- const entryPath = join53(root, projectConfig.entry);
84010
+ const entryPath = join54(root, projectConfig.entry);
83992
84011
  const jiti = createJiti(entryPath, {
83993
84012
  alias: {
83994
84013
  "@c4a/context": resolveContextSdkImportAlias(entryPath)
@@ -84058,7 +84077,7 @@ var init_workspace = __esm(() => {
84058
84077
  init_debugTrace();
84059
84078
  init_projectModulePolicy();
84060
84079
  PROJECT_DIRS = ["src", "sources", "knowledge", "dist"];
84061
- PROJECT_SCRATCH_DIRS = [join53(".tmp", "agent-payloads")];
84080
+ PROJECT_SCRATCH_DIRS = [join54(".tmp", "agent-payloads")];
84062
84081
  PROJECT_LANGUAGES = ["en", "zh-CN"];
84063
84082
  });
84064
84083
 
@@ -84156,7 +84175,7 @@ var init_verifyDiagnostics = __esm(() => {
84156
84175
 
84157
84176
  // src/project/verify.ts
84158
84177
  import { existsSync as existsSync14 } from "node:fs";
84159
- import { join as join54 } from "node:path";
84178
+ import { join as join55 } from "node:path";
84160
84179
  function evidenceStatusForIssues(issues) {
84161
84180
  if (issues.some((issue) => issue.severity === "error"))
84162
84181
  return "fail";
@@ -84230,7 +84249,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
84230
84249
  pageRelPath: `knowledge/${file.relPath}`,
84231
84250
  content: content3
84232
84251
  })) {
84233
- if (!existsSync14(join54(projectRoot, assetPath))) {
84252
+ if (!existsSync14(join55(projectRoot, assetPath))) {
84234
84253
  issues.push({
84235
84254
  severity: "error",
84236
84255
  code: "approved-resource-missing",
@@ -84367,7 +84386,7 @@ __export(exports_close, {
84367
84386
  });
84368
84387
  import { existsSync as existsSync15 } from "node:fs";
84369
84388
  import { mkdir as mkdir20, writeFile as writeFile14 } from "node:fs/promises";
84370
- import { dirname as dirname25, join as join55 } from "node:path";
84389
+ import { dirname as dirname25, join as join56 } from "node:path";
84371
84390
  function parseFrontmatter4(content3) {
84372
84391
  const match = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(content3);
84373
84392
  if (match?.[1] === undefined)
@@ -84431,7 +84450,7 @@ async function deriveApprovedStructure(projectRoot) {
84431
84450
  }
84432
84451
  async function writeApprovedStructureProjection(projectRoot) {
84433
84452
  const { inputHash, structure, compactFiles } = await deriveApprovedStructure(projectRoot);
84434
- const outputPath = join55(projectRoot, STRUCTURE_PATH4);
84453
+ const outputPath = join56(projectRoot, STRUCTURE_PATH4);
84435
84454
  await mkdir20(dirname25(outputPath), { recursive: true });
84436
84455
  await writeFile14(outputPath, import_yaml30.default.stringify(structure), "utf8");
84437
84456
  await Promise.all(compactFiles.map((file) => writeFile14(file.absPath, file.content, "utf8")));
@@ -84442,7 +84461,7 @@ function referencesReceipt() {
84442
84461
  }
84443
84462
  async function readProjectCloseStatus(projectRoot) {
84444
84463
  const approved = await approvedKnowledgeFiles(projectRoot);
84445
- const structurePath = join55(projectRoot, STRUCTURE_PATH4);
84464
+ const structurePath = join56(projectRoot, STRUCTURE_PATH4);
84446
84465
  if (approved.length === 0 && !existsSync15(structurePath))
84447
84466
  return { state: "missing", diagnostics: [] };
84448
84467
  const inputHash = await approvedKnowledgeInputHash(projectRoot);
@@ -84499,7 +84518,7 @@ async function closeProjectWorkspace(projectRoot) {
84499
84518
  next: "Fix context verify errors, then rerun context close --format json."
84500
84519
  });
84501
84520
  }
84502
- const outputPath = join55(projectRoot, STRUCTURE_PATH4);
84521
+ const outputPath = join56(projectRoot, STRUCTURE_PATH4);
84503
84522
  await mkdir20(dirname25(outputPath), { recursive: true });
84504
84523
  await writeFile14(outputPath, `${import_yaml30.default.stringify(structure)}`, "utf8");
84505
84524
  await Promise.all(compactFiles.map((file) => writeFile14(file.absPath, file.content, "utf8")));
@@ -84576,7 +84595,7 @@ var init_close = __esm(() => {
84576
84595
  init_knowledgeAssetRepair();
84577
84596
  init_approvedKnowledgeMetadata();
84578
84597
  import_yaml30 = __toESM(require_dist(), 1);
84579
- STRUCTURE_PATH4 = join55(KNOWLEDGE_ROOT, "structure.yaml");
84598
+ STRUCTURE_PATH4 = join56(KNOWLEDGE_ROOT, "structure.yaml");
84580
84599
  });
84581
84600
 
84582
84601
  // src/project/packageOutputPaths.ts
@@ -84608,7 +84627,7 @@ var init_packageOutputPaths = __esm(() => {
84608
84627
 
84609
84628
  // src/project/packageSiteAddress.ts
84610
84629
  import { readFile as readFile46, writeFile as writeFile15, rename as rename6 } from "node:fs/promises";
84611
- import { join as join56 } from "node:path";
84630
+ import { join as join57 } from "node:path";
84612
84631
  function normalizeSiteUrl(value) {
84613
84632
  const url = new URL(value);
84614
84633
  if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.search || url.hash) {
@@ -84621,7 +84640,7 @@ async function readPackageSiteUrl(root, pkg) {
84621
84640
  if (pkg.kind !== "package.kb" || !pkg.site)
84622
84641
  return;
84623
84642
  try {
84624
- const map2 = JSON.parse(await readFile46(join56(root, packageSiteOutputDir(pkg), SITE_MAP_FILE), "utf8"));
84643
+ const map2 = JSON.parse(await readFile46(join57(root, packageSiteOutputDir(pkg), SITE_MAP_FILE), "utf8"));
84625
84644
  return typeof map2.site_url === "string" ? normalizeSiteUrl(map2.site_url) : undefined;
84626
84645
  } catch (error) {
84627
84646
  if (error.code === "ENOENT" || error instanceof SyntaxError || error instanceof TypeError)
@@ -84638,7 +84657,7 @@ async function recordPackageSiteUrl(root, packageName, value) {
84638
84657
  if (!pkg || pkg.kind !== "package.kb" || !pkg.site) {
84639
84658
  throw new TypeError("Select a declared knowledge package with a website");
84640
84659
  }
84641
- const siteMap = join56(root, packageSiteOutputDir(pkg), SITE_MAP_FILE);
84660
+ const siteMap = join57(root, packageSiteOutputDir(pkg), SITE_MAP_FILE);
84642
84661
  let map2;
84643
84662
  try {
84644
84663
  map2 = JSON.parse(await readFile46(siteMap, "utf8"));
@@ -84652,7 +84671,11 @@ async function recordPackageSiteUrl(root, packageName, value) {
84652
84671
  }
84653
84672
  const content3 = JSON.stringify({ ...map2, site_url: siteUrl }, null, 2) + `
84654
84673
  `;
84655
- for (const path2 of [siteMap, join56(root, pkg.outDir, SITE_MAP_FILE)]) {
84674
+ for (const path2 of [
84675
+ siteMap,
84676
+ join57(root, pkg.outDir, SITE_MAP_FILE),
84677
+ join57(root, pkg.outDir, packageDistributionMetadataPath(SITE_MAP_FILE))
84678
+ ]) {
84656
84679
  await writeFile15(`${path2}.tmp`, content3);
84657
84680
  await rename6(`${path2}.tmp`, path2);
84658
84681
  }
@@ -84662,6 +84685,7 @@ async function recordPackageSiteUrl(root, packageName, value) {
84662
84685
  var SITE_MAP_FILE = "context-site-map.json";
84663
84686
  var init_packageSiteAddress = __esm(() => {
84664
84687
  init_packageOutputPaths();
84688
+ init_packageDistributionMetadata();
84665
84689
  init_writeLock();
84666
84690
  });
84667
84691
 
@@ -84713,7 +84737,7 @@ var init_productionReviewCandidates = __esm(() => {
84713
84737
  import { createHash as createHash14 } from "node:crypto";
84714
84738
  import { existsSync as existsSync16 } from "node:fs";
84715
84739
  import { readFile as readFile47 } from "node:fs/promises";
84716
- import { join as join57, relative as relative17 } from "node:path";
84740
+ import { join as join58, relative as relative17 } from "node:path";
84717
84741
  function parsePackageLinkWarnings(value) {
84718
84742
  if (!Array.isArray(value))
84719
84743
  return [];
@@ -84728,7 +84752,7 @@ async function walkPackageFiles(root) {
84728
84752
  for (const entry of entries2) {
84729
84753
  if (IGNORED_PACKAGE_FS_ENTRIES.has(entry.name))
84730
84754
  continue;
84731
- const absPath = join57(dir, entry.name);
84755
+ const absPath = join58(dir, entry.name);
84732
84756
  if (entry.isDirectory()) {
84733
84757
  await visit3(absPath);
84734
84758
  continue;
@@ -84759,16 +84783,16 @@ function classifyOutputFile(path2, knowledgeGroups) {
84759
84783
  }
84760
84784
  async function packageOutputSnapshot(projectRoot, pkg, knowledgeGroups, previousOutputs = []) {
84761
84785
  const previousByPath = new Map(previousOutputs.map((file) => [file.path, file]));
84762
- const files = (await Promise.all(packageOutputDirs(pkg).map(async (output) => (await walkPackageFiles(join57(projectRoot, output))).map((file) => ({
84786
+ const files = (await Promise.all(packageOutputDirs(pkg).map(async (output) => (await walkPackageFiles(join58(projectRoot, output))).map((file) => ({
84763
84787
  ...file,
84764
- relPath: toPosixPath6(relative17(join57(projectRoot, pkg.outDir), file.absPath))
84788
+ relPath: toPosixPath6(relative17(join58(projectRoot, pkg.outDir), file.absPath))
84765
84789
  }))))).flat();
84766
84790
  return Promise.all(files.map(async (file) => {
84767
84791
  const current2 = classifyOutputFile(file.relPath, knowledgeGroups);
84768
84792
  const previous2 = previousByPath.get(file.relPath);
84769
84793
  const classification = current2.kind === "file" && previous2 !== undefined ? { path: file.relPath, kind: previous2.kind, ...previous2.group === undefined ? {} : { group: previous2.group } } : current2;
84770
84794
  let content3 = await readFile47(file.absPath);
84771
- if (file.absPath === join57(projectRoot, pkg.outDir, "context-site-map.json") || file.absPath === join57(projectRoot, packageSiteOutputDir(pkg), "context-site-map.json")) {
84795
+ if (file.absPath === join58(projectRoot, pkg.outDir, "context-site-map.json") || file.absPath === join58(projectRoot, pkg.outDir, packageDistributionMetadataPath("context-site-map.json")) || file.absPath === join58(projectRoot, packageSiteOutputDir(pkg), "context-site-map.json")) {
84772
84796
  try {
84773
84797
  const map2 = JSON.parse(content3.toString());
84774
84798
  if (map2.protocol === "context.site-output/v1" && Array.isArray(map2.pages)) {
@@ -84787,8 +84811,8 @@ async function packageOutputFingerprint(projectRoot, pkg, observed) {
84787
84811
  const snapshot = observed ?? await packageOutputSnapshot(projectRoot, pkg, new Map);
84788
84812
  return {
84789
84813
  fingerprint: createHash14("sha256").update(JSON.stringify({
84790
- outDirExists: existsSync16(join57(projectRoot, pkg.outDir)),
84791
- siteDirExists: pkg.kind === "package.kb" && pkg.site ? existsSync16(join57(projectRoot, packageSiteOutputDir(pkg))) : undefined,
84814
+ outDirExists: existsSync16(join58(projectRoot, pkg.outDir)),
84815
+ siteDirExists: pkg.kind === "package.kb" && pkg.site ? existsSync16(join58(projectRoot, packageSiteOutputDir(pkg))) : undefined,
84792
84816
  files: snapshot.map(({ path: path2, sha256 }) => ({ path: path2, sha256 }))
84793
84817
  })).digest("hex"),
84794
84818
  files: snapshot.length
@@ -84872,12 +84896,13 @@ var init_packageBuildReceipt = __esm(() => {
84872
84896
  init_packageIndexes();
84873
84897
  init_packageTemplateUtils();
84874
84898
  init_packageOutputPaths();
84899
+ init_packageDistributionMetadata();
84875
84900
  IGNORED_PACKAGE_FS_ENTRIES = new Set([".DS_Store"]);
84876
84901
  });
84877
84902
 
84878
84903
  // src/project/knowledgeMapCoverage.ts
84879
84904
  import { readFile as readFile48 } from "node:fs/promises";
84880
- import { join as join58 } from "node:path";
84905
+ import { join as join59 } from "node:path";
84881
84906
  function knowledgeMapArticleTargets(files) {
84882
84907
  return files.flatMap((file) => {
84883
84908
  const meta = parseKnowledgeFrontmatter(file.content);
@@ -84893,7 +84918,7 @@ function knowledgeMapArticleTargets(files) {
84893
84918
  async function approvedKnowledgeMapTargets(root) {
84894
84919
  const metadata = await readApprovedKnowledgeMetadataIndex(root);
84895
84920
  const articles = new Map(validateArticleStructureEntries(metadata.structure?.articles ?? []).map((article) => [article.path, article]));
84896
- const files = await walkPackageFiles(join58(root, "knowledge"));
84921
+ const files = await walkPackageFiles(join59(root, "knowledge"));
84897
84922
  const content3 = await Promise.all(files.filter((file) => isApprovedKnowledgeMarkdownPath(file.relPath) && !file.relPath.startsWith("assets/")).map(async (file) => ({
84898
84923
  article: articles.get(file.relPath),
84899
84924
  content: hydrateApprovedKnowledgeMarkdown({ content: await readFile48(file.absPath, "utf8"), relPath: file.relPath, metadata })
@@ -84943,10 +84968,10 @@ var init_knowledgeMapCoverage = __esm(() => {
84943
84968
 
84944
84969
  // src/project/knowledgeMap.ts
84945
84970
  import { readFile as readFile49 } from "node:fs/promises";
84946
- import { join as join59 } from "node:path";
84971
+ import { join as join60 } from "node:path";
84947
84972
  async function optionalText(root, path2) {
84948
84973
  try {
84949
- return await readFile49(join59(root, path2), "utf8");
84974
+ return await readFile49(join60(root, path2), "utf8");
84950
84975
  } catch (error) {
84951
84976
  if (error.code === "ENOENT")
84952
84977
  return;
@@ -85007,7 +85032,7 @@ var init_knowledgeMap2 = __esm(() => {
85007
85032
 
85008
85033
  // src/project/packageKnowledgeMap.ts
85009
85034
  import { readFile as readFile50, writeFile as writeFile16 } from "node:fs/promises";
85010
- import { join as join60 } from "node:path";
85035
+ import { join as join61 } from "node:path";
85011
85036
  function knowledgeMapSectionAnchor(key) {
85012
85037
  return `section-${encodeURIComponent(key)}`;
85013
85038
  }
@@ -85032,8 +85057,8 @@ async function writePackageKnowledgeMap(input) {
85032
85057
  return [];
85033
85058
  const projected = projectKnowledgeMap(input.structure, packageKnowledgeMapTargets(input.pkg, input.selected));
85034
85059
  projected.warnings = projected.warnings.filter((warning) => !warning.target.startsWith("site:"));
85035
- const root = join60(input.projectRoot, input.pkg.outDir);
85036
- const mapPath = join60(root, "context-knowledge-map.json");
85060
+ const root = join61(input.projectRoot, input.pkg.outDir);
85061
+ const mapPath = join61(root, "context-knowledge-map.json");
85037
85062
  try {
85038
85063
  await readFile50(mapPath);
85039
85064
  throw new TypeError("package template uses reserved context-knowledge-map.json; rename that template output");
@@ -85054,7 +85079,7 @@ async function writePackageKnowledgeMap(input) {
85054
85079
  }
85055
85080
  render(projected.entries, 0);
85056
85081
  if (lines.length) {
85057
- const indexPath = join60(root, "index.md");
85082
+ const indexPath = join61(root, "index.md");
85058
85083
  let existing = "";
85059
85084
  try {
85060
85085
  existing = await readFile50(indexPath, "utf8");
@@ -85081,7 +85106,7 @@ var init_packageKnowledgeMap = __esm(() => {
85081
85106
  // src/project/packageLlms.ts
85082
85107
  import { createHash as createHash15 } from "node:crypto";
85083
85108
  import { access as access4, mkdir as mkdir21, writeFile as writeFile17 } from "node:fs/promises";
85084
- import { dirname as dirname26, join as join61, posix as posix5 } from "node:path";
85109
+ import { dirname as dirname26, join as join62, posix as posix5 } from "node:path";
85085
85110
  function llmsArticles(pkg, selected) {
85086
85111
  return selected.map((file) => {
85087
85112
  const meta = parseKnowledgeFrontmatter(file.content);
@@ -85181,7 +85206,7 @@ async function writeLlmsDocuments(root, documents, options = {}) {
85181
85206
  for (const [path2, content3] of documents.files) {
85182
85207
  let exists = false;
85183
85208
  try {
85184
- await access4(join61(root, path2));
85209
+ await access4(join62(root, path2));
85185
85210
  exists = true;
85186
85211
  } catch (error) {
85187
85212
  if (error.code !== "ENOENT")
@@ -85191,8 +85216,8 @@ async function writeLlmsDocuments(root, documents, options = {}) {
85191
85216
  continue;
85192
85217
  if (exists)
85193
85218
  throw new Error(`Package template uses reserved LLMS output ${path2}; rename that template output.`);
85194
- await mkdir21(dirname26(join61(root, path2)), { recursive: true });
85195
- await writeFile17(join61(root, path2), options.utf8Bom ? "\uFEFF" + content3.replace(/^\uFEFF/u, "") : content3, "utf8");
85219
+ await mkdir21(dirname26(join62(root, path2)), { recursive: true });
85220
+ await writeFile17(join62(root, path2), options.utf8Bom ? "\uFEFF" + content3.replace(/^\uFEFF/u, "") : content3, "utf8");
85196
85221
  }
85197
85222
  }
85198
85223
  var PACKAGE_LLMS_VERSION = "knowledge-map-llms-v1", label = (text7) => text7.replace(/[\\[\]<>`*]/gu, "\\$&").replace(/[\r\n]/gu, " "), articlePath = (identity) => `llms/pages/${createHash15("sha256").update(identity).digest("hex").slice(0, 32)}.txt`;
@@ -86191,7 +86216,7 @@ var init_packageSiteBranding = __esm(() => {
86191
86216
  // src/project/packageSiteExtensions.ts
86192
86217
  import { createHash as createHash16 } from "node:crypto";
86193
86218
  import { lstat as lstat8, readdir as readdir15, readFile as readFile51, mkdir as mkdir22, writeFile as writeFile18, symlink } from "node:fs/promises";
86194
- import { join as join62, dirname as dirname27, resolve as resolve22 } from "node:path";
86219
+ import { join as join63, dirname as dirname27, resolve as resolve22 } from "node:path";
86195
86220
  function invalidSiteExtension(message) {
86196
86221
  throw new ContextError(ExitCode.UserError, `Site extensions: ${message}. Update site.extensions, its src files or the knowledge-map target, then retry the build.`, {
86197
86222
  reason_code: "invalid-site-extension"
@@ -86210,7 +86235,7 @@ async function readSiteExtensions(projectRoot, extensions) {
86210
86235
  invalid(`unsafe root ${root}`);
86211
86236
  let cursor = projectRoot;
86212
86237
  for (const part of root.split("/")) {
86213
- cursor = join62(cursor, part);
86238
+ cursor = join63(cursor, part);
86214
86239
  const info = await lstat8(cursor).catch((error) => {
86215
86240
  if (error.code === "ENOENT")
86216
86241
  invalid(`missing directory ${root}`);
@@ -86230,9 +86255,9 @@ async function readSiteExtensions(projectRoot, extensions) {
86230
86255
  if (entry.isSymbolicLink())
86231
86256
  invalid(`symlink at ${path2}`);
86232
86257
  if (entry.isDirectory())
86233
- await walk(join62(directory, entry.name), path2 + "/");
86258
+ await walk(join63(directory, entry.name), path2 + "/");
86234
86259
  else if (entry.isFile())
86235
- files.push({ path: path2, bytes: await readFile51(join62(directory, entry.name)) });
86260
+ files.push({ path: path2, bytes: await readFile51(join63(directory, entry.name)) });
86236
86261
  }
86237
86262
  }
86238
86263
  await walk(cursor, "");
@@ -86252,7 +86277,7 @@ async function readSiteExtensions(projectRoot, extensions) {
86252
86277
  hash3.update(file.path + "\x00").update(file.bytes).update("\x00");
86253
86278
  for (const name3 of ["package.json", "bun.lock", "pnpm-lock.yaml", "package-lock.json"]) {
86254
86279
  try {
86255
- hash3.update(name3).update(await readFile51(join62(projectRoot, name3)));
86280
+ hash3.update(name3).update(await readFile51(join63(projectRoot, name3)));
86256
86281
  } catch (error) {
86257
86282
  if (error.code !== "ENOENT")
86258
86283
  throw error;
@@ -86265,9 +86290,9 @@ function siteExtensionTargets(site) {
86265
86290
  }
86266
86291
  async function writeSiteExtensions(projectRoot, temporary, extensions) {
86267
86292
  const { files } = await readSiteExtensions(projectRoot, extensions);
86268
- const root = join62(temporary, "_site");
86293
+ const root = join63(temporary, "_site");
86269
86294
  for (const file of files) {
86270
- const path2 = join62(root, file.path);
86295
+ const path2 = join63(root, file.path);
86271
86296
  await mkdir22(dirname27(path2), { recursive: true });
86272
86297
  await writeFile18(path2, file.bytes);
86273
86298
  }
@@ -86276,7 +86301,7 @@ async function writeSiteExtensions(projectRoot, temporary, extensions) {
86276
86301
  const modules = resolve22(projectRoot, "node_modules");
86277
86302
  if ((await lstat8(modules)).isDirectory() || (await lstat8(modules)).isSymbolicLink()) {
86278
86303
  await mkdir22(root, { recursive: true });
86279
- await symlink(modules, join62(root, "node_modules"), "dir");
86304
+ await symlink(modules, join63(root, "node_modules"), "dir");
86280
86305
  }
86281
86306
  } catch (error) {
86282
86307
  if (error.code !== "ENOENT")
@@ -86295,16 +86320,16 @@ async function writeSiteExtensions(projectRoot, temporary, extensions) {
86295
86320
  imports.push(`const ${name3} = defineAsyncComponent(() => import(${JSON.stringify(`../../_site/${path2}`)}));`);
86296
86321
  slots.push(`${JSON.stringify(name3)}: ${name3 === "floating" ? `() => h(resolveComponent('ClientOnly'), null, { default: () => h(${name3}) })` : `() => h(${name3})`}`);
86297
86322
  }
86298
- await writeFile18(join62(temporary, ".vitepress/theme/extensions.js"), imports.join(`
86323
+ await writeFile18(join63(temporary, ".vitepress/theme/extensions.js"), imports.join(`
86299
86324
  `) + `
86300
86325
  export default {${slots.join(",")}};
86301
86326
  `);
86302
86327
  for (const [key, path2] of Object.entries(extensions?.pages ?? {})) {
86303
- await mkdir22(join62(temporary, "custom"), { recursive: true });
86328
+ await mkdir22(join63(temporary, "custom"), { recursive: true });
86304
86329
  const content3 = files.find((file) => file.path === path2).bytes.toString("utf8");
86305
86330
  const metadata = parseKnowledgeFrontmatter(content3);
86306
86331
  const title = metadata.title ?? /^#\s+(.+)$/m.exec(content3)?.[1] ?? key;
86307
- await writeFile18(join62(temporary, "custom", `${key}.md`), `---
86332
+ await writeFile18(join63(temporary, "custom", `${key}.md`), `---
86308
86333
  ${JSON.stringify({ layout: "page", ...metadata, title })}
86309
86334
  ---
86310
86335
  <script setup>
@@ -86328,7 +86353,7 @@ import { createHash as createHash17 } from "node:crypto";
86328
86353
  import { spawn as spawn3 } from "node:child_process";
86329
86354
  import { mkdir as mkdir23, mkdtemp as mkdtemp2, readFile as readFile52, writeFile as writeFile19, rm as rm12, symlink as symlink2, cp, access as access5, stat as stat8 } from "node:fs/promises";
86330
86355
  import { createRequire as createRequire5 } from "node:module";
86331
- import { dirname as dirname28, join as join63, posix as posix6 } from "node:path";
86356
+ import { dirname as dirname28, join as join64, posix as posix6 } from "node:path";
86332
86357
  function sitePagePath(identity) {
86333
86358
  return `pages/${createHash17("sha256").update(identity).digest("hex").slice(0, 32)}.html`;
86334
86359
  }
@@ -86449,7 +86474,7 @@ function siteSections(entries2) {
86449
86474
  async function compileSite(root, outDir) {
86450
86475
  const vitepressRoot = dirname28(require2.resolve("vitepress/package.json"));
86451
86476
  await new Promise((resolve8, reject) => {
86452
- const child = spawn3(process.versions.bun ? "node" : process.execPath, [join63(vitepressRoot, "bin/vitepress.js"), "build", root, "--outDir", outDir], { stdio: ["ignore", "pipe", "pipe"] });
86477
+ const child = spawn3(process.versions.bun ? "node" : process.execPath, [join64(vitepressRoot, "bin/vitepress.js"), "build", root, "--outDir", outDir], { stdio: ["ignore", "pipe", "pipe"] });
86453
86478
  let tail = "";
86454
86479
  const receive = (chunk) => {
86455
86480
  tail = (tail + chunk.toString()).slice(-16000);
@@ -86480,8 +86505,8 @@ async function writePackageSite(input) {
86480
86505
  const base = options.base ?? "/";
86481
86506
  const history = await readWorkspaceChangelog(projectRoot);
86482
86507
  const historyDate = history[0]?.date ?? null;
86483
- const root = join63(projectRoot, pkg.outDir);
86484
- const output = join63(projectRoot, packageSiteOutputDir(pkg));
86508
+ const root = join64(projectRoot, pkg.outDir);
86509
+ const output = join64(projectRoot, packageSiteOutputDir(pkg));
86485
86510
  try {
86486
86511
  await access5(output);
86487
86512
  throw new Error("Website output already exists; build through the staged package workflow.");
@@ -86489,9 +86514,9 @@ async function writePackageSite(input) {
86489
86514
  if (error.code !== "ENOENT")
86490
86515
  throw error;
86491
86516
  }
86492
- const temporaryRoot = join63(projectRoot, ".tmp");
86517
+ const temporaryRoot = join64(projectRoot, ".tmp");
86493
86518
  await mkdir23(temporaryRoot, { recursive: true });
86494
- const temporary = await mkdtemp2(join63(temporaryRoot, "website-"));
86519
+ const temporary = await mkdtemp2(join64(temporaryRoot, "website-"));
86495
86520
  try {
86496
86521
  const registry2 = await loadSourcesRegistry({ rootDir: projectRoot });
86497
86522
  const sourceContent = new Map(selected.map((file) => [packageKnowledgeOutputPath(pkg, file.relPath), file]));
@@ -86512,22 +86537,22 @@ async function writePackageSite(input) {
86512
86537
  }
86513
86538
  const sections = siteSections(mapping.entries);
86514
86539
  const resources = new Set(delivered.filter((file) => file.relPath.startsWith("others/assets/") || file.relPath.startsWith("skills/") && !file.relPath.endsWith(".md")).map((file) => file.relPath));
86515
- const configRoot = join63(temporary, ".vitepress");
86516
- await mkdir23(join63(configRoot, "theme"), { recursive: true });
86517
- await mkdir23(join63(temporary, "node_modules"), { recursive: true });
86540
+ const configRoot = join64(temporary, ".vitepress");
86541
+ await mkdir23(join64(configRoot, "theme"), { recursive: true });
86542
+ await mkdir23(join64(temporary, "node_modules"), { recursive: true });
86518
86543
  const vitepressRoot = dirname28(require2.resolve("vitepress/package.json"));
86519
- const vueRequire = createRequire5(join63(vitepressRoot, "package.json"));
86544
+ const vueRequire = createRequire5(join64(vitepressRoot, "package.json"));
86520
86545
  for (const [name3, path2] of [
86521
86546
  ["vitepress", vitepressRoot],
86522
86547
  ["vue", dirname28(vueRequire.resolve("vue/package.json"))],
86523
86548
  ["@mermaid-js/layout-elk", dirname28(require2.resolve("@mermaid-js/layout-elk/package.json"))],
86524
86549
  ["mermaid", dirname28(require2.resolve("mermaid/package.json"))]
86525
86550
  ]) {
86526
- await mkdir23(dirname28(join63(temporary, "node_modules", name3)), { recursive: true });
86527
- await symlink2(path2, join63(temporary, "node_modules", name3), "dir");
86551
+ await mkdir23(dirname28(join64(temporary, "node_modules", name3)), { recursive: true });
86552
+ await symlink2(path2, join64(temporary, "node_modules", name3), "dir");
86528
86553
  }
86529
- await writeFile19(join63(configRoot, "theme/index.js"), siteThemeScript);
86530
- await writeFile19(join63(configRoot, "theme/style.css"), siteThemeCss + siteThemeVariables(await resolveSiteTheme(projectRoot, options.theme, true)));
86554
+ await writeFile19(join64(configRoot, "theme/index.js"), siteThemeScript);
86555
+ await writeFile19(join64(configRoot, "theme/style.css"), siteThemeCss + siteThemeVariables(await resolveSiteTheme(projectRoot, options.theme, true)));
86531
86556
  await writeSiteExtensions(projectRoot, temporary, options.extensions);
86532
86557
  const config = {
86533
86558
  title: options.title ?? pkg.name,
@@ -86553,11 +86578,11 @@ async function writePackageSite(input) {
86553
86578
  nav: [...sections.map((section) => ({ text: section.title, link: section.href })), { text: "更多", items: [{ text: "LLM Docs", link: "/llms/index.html" }, { text: "Changelog", link: "/changelog.html" }] }]
86554
86579
  }
86555
86580
  };
86556
- await writeFile19(join63(configRoot, "config.mjs"), `export default { ...${JSON.stringify(config)}, markdown: { ${siteMarkdownConfig} } };
86581
+ await writeFile19(join64(configRoot, "config.mjs"), `export default { ...${JSON.stringify(config)}, markdown: { ${siteMarkdownConfig} } };
86557
86582
  `);
86558
- await mkdir23(join63(temporary, "pages"), { recursive: true });
86583
+ await mkdir23(join64(temporary, "pages"), { recursive: true });
86559
86584
  for (const page of byPath.values()) {
86560
- const content3 = await readFile52(join63(root, page.package_path), "utf8");
86585
+ const content3 = await readFile52(join64(root, page.package_path), "utf8");
86561
86586
  const original = sourceContent.get(page.package_path);
86562
86587
  const provenance = articleProvenanceMarkdown(original?.article, registry2);
86563
86588
  const pageContent = provenance && content3.endsWith(provenance) ? content3.slice(0, -provenance.length) : content3;
@@ -86565,7 +86590,7 @@ async function writePackageSite(input) {
86565
86590
  const sources = siteArticleSources(original?.article, registry2);
86566
86591
  const timestamp = parseKnowledgeFrontmatter(original?.content ?? content3).timestamp;
86567
86592
  const updated = typeof timestamp === "string" && Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
86568
- await writeFile19(join63(temporary, page.site_path.replace(/\.html$/u, ".md")), `---
86593
+ await writeFile19(join64(temporary, page.site_path.replace(/\.html$/u, ".md")), `---
86569
86594
  title: ${JSON.stringify(page.title)}
86570
86595
  contextSources: ${JSON.stringify(sources)}
86571
86596
  contextUpdated: ${JSON.stringify(updated)}
@@ -86577,11 +86602,11 @@ ${body}`);
86577
86602
  lines.push(`${" ".repeat(level)}- ${entry.href ? `[${mdLabel(entry.title)}](${entry.href})` : mdLabel(entry.title)}`);
86578
86603
  menu(lines, entry.children, level + 1);
86579
86604
  });
86580
- await mkdir23(join63(temporary, "sections"), { recursive: true });
86605
+ await mkdir23(join64(temporary, "sections"), { recursive: true });
86581
86606
  for (const section of sections) {
86582
86607
  const lines = [`# ${mdLabel(section.title)}`, ""];
86583
86608
  menu(lines, section.entries, 0);
86584
- await writeFile19(join63(temporary, section.href.slice(1).replace(/\.html$/u, ".md")), lines.join(`
86609
+ await writeFile19(join64(temporary, section.href.slice(1).replace(/\.html$/u, ".md")), lines.join(`
86585
86610
  `) + `
86586
86611
  `);
86587
86612
  }
@@ -86600,12 +86625,12 @@ ${body}`);
86600
86625
  };
86601
86626
  const homeHero = options.extensions?.slots?.banner === undefined ? `hero: ${JSON.stringify(hero)}
86602
86627
  ` : "";
86603
- await writeFile19(join63(temporary, "index.md"), `---
86628
+ await writeFile19(join64(temporary, "index.md"), `---
86604
86629
  layout: home
86605
86630
  title: ${JSON.stringify(options.home?.title ?? options.title ?? pkg.name)}
86606
86631
  ${homeHero}---
86607
86632
  `);
86608
- await writeFile19(join63(temporary, "changelog.md"), `---
86633
+ await writeFile19(join64(temporary, "changelog.md"), `---
86609
86634
  title: Changelog
86610
86635
  contextHistory: ${JSON.stringify(Buffer.from(JSON.stringify(history)).toString("base64"))}
86611
86636
  ---
@@ -86618,19 +86643,19 @@ contextHistory: ${JSON.stringify(Buffer.from(JSON.stringify(history)).toString("
86618
86643
  assetsPrefix: "resources/",
86619
86644
  articles: await Promise.all(llmsArticles(pkg, selected).map(async (article) => ({
86620
86645
  ...article,
86621
- content: await readFile52(join63(root, article.path), "utf8")
86646
+ content: await readFile52(join64(root, article.path), "utf8")
86622
86647
  }))),
86623
86648
  ...structure ? { map: structure } : {}
86624
86649
  });
86625
- await writeLlmsDocuments(join63(temporary, "public"), llms, { utf8Bom: true });
86626
- await mkdir23(join63(temporary, "llms"), { recursive: true });
86650
+ await writeLlmsDocuments(join64(temporary, "public"), llms, { utf8Bom: true });
86651
+ await mkdir23(join64(temporary, "llms"), { recursive: true });
86627
86652
  let landingNavigation = llms.navigationMarkdown;
86628
86653
  for (const link of markdownReaderLinks(landingNavigation).reverse()) {
86629
86654
  if (!link.target.startsWith(base))
86630
86655
  continue;
86631
86656
  landingNavigation = landingNavigation.slice(0, link.start) + `[${link.label}](</${link.target.slice(base.length)}>)` + landingNavigation.slice(link.end);
86632
86657
  }
86633
- await writeFile19(join63(temporary, "llms/index.md"), `---
86658
+ await writeFile19(join64(temporary, "llms/index.md"), `---
86634
86659
  title: LLM Docs
86635
86660
  ---
86636
86661
 
@@ -86640,9 +86665,9 @@ title: LLM Docs
86640
86665
 
86641
86666
  ` + landingNavigation);
86642
86667
  for (const path2 of resources) {
86643
- const destination = join63(temporary, "public/resources", path2);
86668
+ const destination = join64(temporary, "public/resources", path2);
86644
86669
  await mkdir23(dirname28(destination), { recursive: true });
86645
- await cp(join63(root, path2), destination);
86670
+ await cp(join64(root, path2), destination);
86646
86671
  }
86647
86672
  await compileSite(temporary, output);
86648
86673
  for (const file of await walkPackageFiles(output)) {
@@ -86666,8 +86691,14 @@ title: LLM Docs
86666
86691
  warnings: mapping.warnings
86667
86692
  }, null, 2) + `
86668
86693
  `;
86669
- await writeFile19(join63(output, "context-site-map.json"), siteMapContent);
86670
- await writeFile19(join63(projectRoot, pkg.outDir, "context-site-map.json"), siteMapContent);
86694
+ const packageSiteMap = join64(projectRoot, pkg.outDir, "context-site-map.json");
86695
+ const distributedSiteMap = join64(projectRoot, pkg.outDir, packageDistributionMetadataPath("context-site-map.json"));
86696
+ await mkdir23(dirname28(distributedSiteMap), { recursive: true });
86697
+ await Promise.all([
86698
+ writeFile19(join64(output, "context-site-map.json"), siteMapContent),
86699
+ writeFile19(packageSiteMap, siteMapContent),
86700
+ writeFile19(distributedSiteMap, siteMapContent)
86701
+ ]);
86671
86702
  return mapping;
86672
86703
  } finally {
86673
86704
  await rm12(temporary, { recursive: true, force: true });
@@ -86688,12 +86719,13 @@ var init_packageSite2 = __esm(() => {
86688
86719
  init_packageSiteTheme();
86689
86720
  init_packageSiteBranding();
86690
86721
  init_packageSiteExtensions();
86722
+ init_packageDistributionMetadata();
86691
86723
  PACKAGE_SITE_VERSION = `vitepress-site-v44-site-address:${createHash17("sha256").update(JSON.stringify([siteThemeVariables.toString(), siteMarkdownConfig, siteThemeCss, siteThemeScript, siteThemeLabels("zh"), siteThemeLabels("en")])).digest("hex")}`;
86692
86724
  require2 = createRequire5(import.meta.url);
86693
86725
  });
86694
86726
 
86695
86727
  // src/project/workspaceBuildVersion.ts
86696
- import { join as join64 } from "node:path";
86728
+ import { join as join65 } from "node:path";
86697
86729
  import { mkdir as mkdir24, writeFile as writeFile20 } from "node:fs/promises";
86698
86730
  async function workspaceVersionFingerprint(root) {
86699
86731
  return { version: await workspaceVersion(root), changelog: await readWorkspaceChangelog(root) };
@@ -86705,8 +86737,8 @@ async function writePackageVersion(projectRoot, output) {
86705
86737
  throw new TypeError(`Package template uses reserved version output ${path2}; rename that template output.`);
86706
86738
  }
86707
86739
  await mkdir24(output, { recursive: true });
86708
- await writeFile20(join64(output, "CHANGELOG.md"), renderChangelog(info.changelog));
86709
- await writeFile20(join64(output, "context-version.json"), JSON.stringify({ version: info.version }) + `
86740
+ await writeFile20(join65(output, "CHANGELOG.md"), renderChangelog(info.changelog));
86741
+ await writeFile20(join65(output, "context-version.json"), JSON.stringify({ version: info.version }) + `
86710
86742
  `);
86711
86743
  }
86712
86744
  var init_workspaceBuildVersion = __esm(() => {
@@ -86716,11 +86748,11 @@ var init_workspaceBuildVersion = __esm(() => {
86716
86748
  // src/project/packageRenderCache.ts
86717
86749
  import { createHash as createHash18 } from "node:crypto";
86718
86750
  import { readFile as readFile53 } from "node:fs/promises";
86719
- import { join as join65 } from "node:path";
86751
+ import { join as join66 } from "node:path";
86720
86752
  async function cachedPackageKnowledgeMarkdown(input) {
86721
86753
  const fingerprint = digest3(`${PACKAGE_READER_MARKDOWN_VERSION}
86722
86754
  ${input.content}`);
86723
- const path2 = join65(input.projectRoot, ".tmp/context-runtime/package-render", `${digest3(input.key)}.json`);
86755
+ const path2 = join66(input.projectRoot, ".tmp/context-runtime/package-render", `${digest3(input.key)}.json`);
86724
86756
  try {
86725
86757
  const cached = JSON.parse(await readFile53(path2, "utf8"));
86726
86758
  if (cached !== null && typeof cached === "object" && "fingerprint" in cached && cached.fingerprint === fingerprint && "markdown" in cached && typeof cached.markdown === "string") {
@@ -86842,22 +86874,22 @@ var init_packageMarkdownAnchors = __esm(() => {
86842
86874
 
86843
86875
  // src/project/packageBuildStage.ts
86844
86876
  import { mkdir as mkdir25, mkdtemp as mkdtemp3, readFile as readFile55, rename as rename7, rm as rm13, rmdir } from "node:fs/promises";
86845
- import { dirname as dirname29, join as join66, relative as relative18 } from "node:path";
86877
+ import { dirname as dirname29, join as join67, relative as relative18 } from "node:path";
86846
86878
  async function withStagedPackageOutput(projectRoot, pkg, render) {
86847
- const tempRoot = join66(projectRoot, ".tmp");
86879
+ const tempRoot = join67(projectRoot, ".tmp");
86848
86880
  await mkdir25(tempRoot, { recursive: true });
86849
- const stage = await mkdtemp3(join66(tempRoot, "package-build-"));
86850
- const stagedPackage = { ...pkg, outDir: relative18(projectRoot, join66(stage, pkg.name)) };
86881
+ const stage = await mkdtemp3(join67(tempRoot, "package-build-"));
86882
+ const stagedPackage = { ...pkg, outDir: relative18(projectRoot, join67(stage, pkg.name)) };
86851
86883
  try {
86852
- await mkdir25(join66(projectRoot, stagedPackage.outDir), { recursive: true });
86884
+ await mkdir25(join67(projectRoot, stagedPackage.outDir), { recursive: true });
86853
86885
  const value = await render(stagedPackage);
86854
86886
  await validatePackageIndexLinks({ projectRoot, pkg: stagedPackage });
86855
86887
  const destinations = packageOutputDirs(pkg);
86856
86888
  const staged = packageOutputDirs(stagedPackage);
86857
86889
  for (const [index2, destination] of destinations.entries()) {
86858
- const target = join66(projectRoot, destination);
86890
+ const target = join67(projectRoot, destination);
86859
86891
  const previous2 = await walkPackageFiles(target);
86860
- const next = await walkPackageFiles(join66(projectRoot, staged[index2]));
86892
+ const next = await walkPackageFiles(join67(projectRoot, staged[index2]));
86861
86893
  const desired = new Set(next.map((file) => file.relPath));
86862
86894
  for (const file of previous2) {
86863
86895
  if (desired.has(file.relPath))
@@ -86875,7 +86907,7 @@ async function withStagedPackageOutput(projectRoot, pkg, render) {
86875
86907
  }
86876
86908
  for (let offset2 = 0;offset2 < next.length; offset2 += 8) {
86877
86909
  const results = await Promise.allSettled(next.slice(offset2, offset2 + 8).map(async (file) => {
86878
- const output = join66(target, file.relPath);
86910
+ const output = join67(target, file.relPath);
86879
86911
  const bytes = await readFile55(file.absPath);
86880
86912
  const old = await readFile55(output).catch((error) => {
86881
86913
  if (error.code === "ENOENT")
@@ -87283,7 +87315,7 @@ var init_packageAssetOptimization = __esm(() => {
87283
87315
  // src/project/packageAssetDelivery.ts
87284
87316
  import { execFile as execFile8 } from "node:child_process";
87285
87317
  import { realpath as realpath7 } from "node:fs/promises";
87286
- import { join as join67, relative as relative20, sep as sep5 } from "node:path";
87318
+ import { join as join68, relative as relative20, sep as sep5 } from "node:path";
87287
87319
  import { promisify as promisify8 } from "node:util";
87288
87320
  async function git(projectRoot, args) {
87289
87321
  try {
@@ -87303,7 +87335,7 @@ async function git(projectRoot, args) {
87303
87335
  }
87304
87336
  }
87305
87337
  function repositoryPath(repoRoot, projectRoot, asset) {
87306
- const path2 = relative20(repoRoot, join67(projectRoot, asset.knowledgeRelPath)).split(sep5).join("/");
87338
+ const path2 = relative20(repoRoot, join68(projectRoot, asset.knowledgeRelPath)).split(sep5).join("/");
87307
87339
  if (path2 === ".." || path2.startsWith("../") || path2.startsWith("/")) {
87308
87340
  throw new ContextError(ExitCode.WorkspaceStateError, "knowledge asset is outside the current Git repository", {
87309
87341
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -87484,7 +87516,7 @@ var init_packageAssetDelivery = __esm(() => {
87484
87516
  // src/project/packageBuildContent.ts
87485
87517
  import { existsSync as existsSync17 } from "node:fs";
87486
87518
  import { mkdir as mkdir26, readFile as readFile57, writeFile as writeFile21 } from "node:fs/promises";
87487
- import { dirname as dirname32, join as join68 } from "node:path";
87519
+ import { dirname as dirname32, join as join69 } from "node:path";
87488
87520
  function globToRegExp(pattern) {
87489
87521
  const normalized = toPosixPath6(pattern);
87490
87522
  if (normalized.endsWith("/**")) {
@@ -87625,7 +87657,7 @@ async function writeRenderedPackageTemplate(input) {
87625
87657
  templateRelPath: renderedRelPath,
87626
87658
  logicalTemplateRelPath: renderedLogicalRelPath
87627
87659
  });
87628
- const outputPath = join68(input.projectRoot, input.pkg.outDir, renderedRelPath);
87660
+ const outputPath = join69(input.projectRoot, input.pkg.outDir, renderedRelPath);
87629
87661
  await mkdir26(dirname32(outputPath), { recursive: true });
87630
87662
  await writeFile21(outputPath, renderTemplateText(file.content, contentVars), "utf8");
87631
87663
  written++;
@@ -87658,7 +87690,7 @@ async function writeSelectedPackageKnowledge(input) {
87658
87690
  for (let offset2 = 0;offset2 < projectedPages.length; offset2 += 8) {
87659
87691
  const results = await Promise.allSettled(projectedPages.slice(offset2, offset2 + 8).map(async (projected) => {
87660
87692
  assertSafeRenderedPath2(projected.pageOutputPath, "knowledge path");
87661
- const outputPath = join68(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
87693
+ const outputPath = join69(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
87662
87694
  let mediaContent = projected.content;
87663
87695
  const omitted = new Set((delivered.omittedImages ?? []).map((path2) => packageMarkdownTarget(projected.pageOutputPath, path2)));
87664
87696
  for (const link of markdownReaderLinks(mediaContent).reverse()) {
@@ -87695,7 +87727,7 @@ async function writeSelectedPackageKnowledge(input) {
87695
87727
  const deliveredAssets = new Map(delivered.assets.map((asset) => [asset.packageRelPath, asset]));
87696
87728
  for (const asset of deliveredAssets.values()) {
87697
87729
  assertSafeRenderedPath2(asset.packageRelPath, "package resource path");
87698
- const outputPath = join68(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
87730
+ const outputPath = join69(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
87699
87731
  await mkdir26(dirname32(outputPath), { recursive: true });
87700
87732
  await writeFile21(outputPath, asset.bytes);
87701
87733
  }
@@ -87710,7 +87742,7 @@ async function writeSelectedPackageKnowledge(input) {
87710
87742
  async function appendLlmsKnowledge(input) {
87711
87743
  if (packageKind2(input.pkg) !== "llms" || input.templateConsumesKnowledge || input.knowledgeCount === 0)
87712
87744
  return 0;
87713
- const outputPath = join68(input.projectRoot, input.pkg.outDir, "llms.txt");
87745
+ const outputPath = join69(input.projectRoot, input.pkg.outDir, "llms.txt");
87714
87746
  const existed = existsSync17(outputPath);
87715
87747
  const existing = existed ? await readFile57(outputPath, "utf8") : "";
87716
87748
  const content3 = existing.trim().length > 0 ? `${existing.trimEnd()}
@@ -87937,7 +87969,7 @@ __export(exports_packageBuilder, {
87937
87969
  import { createHash as createHash20 } from "node:crypto";
87938
87970
  import { existsSync as existsSync18 } from "node:fs";
87939
87971
  import { mkdir as mkdir27, readdir as readdir16, readFile as readFile58, rm as rm14, writeFile as writeFile22 } from "node:fs/promises";
87940
- import { dirname as dirname33, join as join69, resolve as resolve23 } from "node:path";
87972
+ import { dirname as dirname33, join as join70, resolve as resolve23 } from "node:path";
87941
87973
  function packageAssetDeliverySummary(value) {
87942
87974
  if (value === null || typeof value !== "object" || Array.isArray(value))
87943
87975
  return;
@@ -87959,7 +87991,7 @@ function assertPackageOutputDir(pkg) {
87959
87991
  }
87960
87992
  function packageFingerprintPath(projectRoot, pkg) {
87961
87993
  assertSafeRenderedPath2(`${pkg.name}.json`, "package fingerprint path");
87962
- return join69(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
87994
+ return join70(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
87963
87995
  }
87964
87996
  async function listApprovedKnowledge(projectRoot) {
87965
87997
  const metadata = await readApprovedKnowledgeMetadataIndex(projectRoot);
@@ -88112,12 +88144,12 @@ async function writePackageFingerprint(input) {
88112
88144
  `, "utf8");
88113
88145
  }
88114
88146
  async function removeOrphanPackageDirs(projectRoot, packages) {
88115
- const distRoot = join69(projectRoot, "dist");
88147
+ const distRoot = join70(projectRoot, "dist");
88116
88148
  if (!existsSync18(distRoot))
88117
88149
  return;
88118
88150
  const declaredNames = new Set(packages.flatMap((pkg) => packageOutputDirs(pkg).map((path2) => path2.slice("dist/".length))));
88119
88151
  const entries2 = await readdir16(distRoot, { withFileTypes: true });
88120
- await Promise.all(entries2.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm14(join69(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
88152
+ await Promise.all(entries2.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm14(join70(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
88121
88153
  }
88122
88154
  async function collectPackageFreshness(projectRoot, packages) {
88123
88155
  assertDistinctPackageOutputs(packages);
@@ -88126,7 +88158,7 @@ async function collectPackageFreshness(projectRoot, packages) {
88126
88158
  assertPackageOutputDir(pkg);
88127
88159
  const selected = selectPackageKnowledge(approved, pkg);
88128
88160
  assertSafeRenderedPath2(pkg.template.path, "package template path");
88129
- const templateRoot = join69(projectRoot, pkg.template.path);
88161
+ const templateRoot = join70(projectRoot, pkg.template.path);
88130
88162
  const templateExists = existsSync18(templateRoot);
88131
88163
  if (!templateExists) {
88132
88164
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${pkg.template.path}`, {
@@ -88355,19 +88387,19 @@ async function buildProjectPackagesInternal(projectRoot, options) {
88355
88387
  if (stagedPkg.kind === "package.llms") {
88356
88388
  const articles = await Promise.all(llmsArticles(stagedPkg, selected).map(async (article) => ({
88357
88389
  ...article,
88358
- content: await readFile58(join69(projectRoot, stagedPkg.outDir, article.path), "utf8")
88390
+ content: await readFile58(join70(projectRoot, stagedPkg.outDir, article.path), "utf8")
88359
88391
  })));
88360
- await writeLlmsDocuments(join69(projectRoot, stagedPkg.outDir), buildLlmsDocuments({
88392
+ await writeLlmsDocuments(join70(projectRoot, stagedPkg.outDir), buildLlmsDocuments({
88361
88393
  title: stagedPkg.name,
88362
88394
  articles,
88363
88395
  ...reading ? { map: reading } : {}
88364
88396
  }), { preserveIndex: true });
88365
88397
  }
88366
- await writePackageVersion(projectRoot, join69(projectRoot, stagedPkg.outDir));
88398
+ await writePackageVersion(projectRoot, join70(projectRoot, stagedPkg.outDir));
88367
88399
  await writePackageSite({ projectRoot, pkg: stagedPkg, selected, ...siteUrl ? { siteUrl } : {}, ...reading ? { structure: reading } : {} });
88368
88400
  const linkWarnings = [
88369
88401
  ...writtenKnowledge2.linkWarnings,
88370
- ...await inspectPackageMarkdownDirectory(join69(projectRoot, stagedPkg.outDir))
88402
+ ...await inspectPackageMarkdownDirectory(join70(projectRoot, stagedPkg.outDir))
88371
88403
  ];
88372
88404
  return { ...writtenKnowledge2, linkWarnings };
88373
88405
  });
@@ -88559,7 +88591,7 @@ var init_packageBuilder = __esm(() => {
88559
88591
  init_packageTemplateReview();
88560
88592
  init_approvedKnowledgeMetadata();
88561
88593
  import_yaml35 = __toESM(require_dist(), 1);
88562
- PACKAGE_FINGERPRINT_ROOT = join69(".tmp", "context-runtime", "packages");
88594
+ PACKAGE_FINGERPRINT_ROOT = join70(".tmp", "context-runtime", "packages");
88563
88595
  });
88564
88596
 
88565
88597
  // src/project/taskRollback.ts
@@ -88570,7 +88602,7 @@ __export(exports_taskRollback, {
88570
88602
  finishTaskRollback: () => finishTaskRollback
88571
88603
  });
88572
88604
  import { readFile as readFile59 } from "node:fs/promises";
88573
- import { join as join70 } from "node:path";
88605
+ import { join as join71 } from "node:path";
88574
88606
  async function readTaskRollback(projectRoot) {
88575
88607
  const raw = await readJsonMaybe(projectRoot, await revisionStoragePath(projectRoot));
88576
88608
  if (!raw || typeof raw !== "object" || !("protocol" in raw) || raw.protocol !== "context.task-rollback/v1")
@@ -88579,7 +88611,7 @@ async function readTaskRollback(projectRoot) {
88579
88611
  }
88580
88612
  async function contents(projectRoot, path2) {
88581
88613
  try {
88582
- return await readFile59(join70(projectRoot, path2), "utf8");
88614
+ return await readFile59(join71(projectRoot, path2), "utf8");
88583
88615
  } catch (error) {
88584
88616
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
88585
88617
  return;
@@ -88747,11 +88779,11 @@ __export(exports_knowledgeUpdate, {
88747
88779
  beginKnowledgeUpdate: () => beginKnowledgeUpdate
88748
88780
  });
88749
88781
  import { readFile as readFile60 } from "node:fs/promises";
88750
- import { join as join71 } from "node:path";
88782
+ import { join as join72 } from "node:path";
88751
88783
  async function readKnowledgeUpdate(projectRoot) {
88752
88784
  let value;
88753
88785
  try {
88754
- value = JSON.parse(await readFile60(join71(projectRoot, await revisionStoragePath(projectRoot)), "utf8"));
88786
+ value = JSON.parse(await readFile60(join72(projectRoot, await revisionStoragePath(projectRoot)), "utf8"));
88755
88787
  } catch (error) {
88756
88788
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
88757
88789
  return;
@@ -88802,7 +88834,7 @@ async function beginKnowledgeUpdate(projectRoot, value) {
88802
88834
  ...input.changes === undefined ? {} : { changes: input.changes }
88803
88835
  };
88804
88836
  const request = updateSchema.parse({ ...payload, revision: indexerProtocolDigest(payload) });
88805
- await atomicWriteFile(join71(projectRoot, await revisionStoragePath(projectRoot)), `${JSON.stringify(request)}
88837
+ await atomicWriteFile(join72(projectRoot, await revisionStoragePath(projectRoot)), `${JSON.stringify(request)}
88806
88838
  `);
88807
88839
  return {
88808
88840
  outcome: "update-prepared",
@@ -88847,7 +88879,7 @@ async function completeKnowledgeUpdate(input) {
88847
88879
  if (input.new_topics.length && !input.structure_approved) {
88848
88880
  const { revision: _revision, ...rest } = request;
88849
88881
  const payload = { ...rest, structure_proposal: { decisions: input.decisions, scope_summary: input.scope_summary, new_topics: input.new_topics } };
88850
- await atomicWriteFile(join71(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify({ ...payload, revision: indexerProtocolDigest(payload) })}
88882
+ await atomicWriteFile(join72(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify({ ...payload, revision: indexerProtocolDigest(payload) })}
88851
88883
  `);
88852
88884
  return { outcome: "structure-review-required" };
88853
88885
  }
@@ -88884,7 +88916,7 @@ async function completeUpdateStructureReview(input) {
88884
88916
  const { revision: _revision, structure_proposal: _proposal, ...rest } = request;
88885
88917
  const payload = { ...rest, changes: `${rest.changes ?? ""}
88886
88918
  Structure feedback: ${input.feedback}` };
88887
- await atomicWriteFile(join71(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify({ ...payload, revision: indexerProtocolDigest(payload) })}
88919
+ await atomicWriteFile(join72(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify({ ...payload, revision: indexerProtocolDigest(payload) })}
88888
88920
  `);
88889
88921
  return { outcome: "structure-adjustment-required" };
88890
88922
  });
@@ -89058,14 +89090,14 @@ __export(exports_knowledgeMaintenance, {
89058
89090
  advanceKnowledgeMaintenance: () => advanceKnowledgeMaintenance
89059
89091
  });
89060
89092
  import { readFile as readFile61, readdir as readdir17, rm as rm15 } from "node:fs/promises";
89061
- import { join as join72 } from "node:path";
89093
+ import { join as join73 } from "node:path";
89062
89094
  async function deliveryDigest(root) {
89063
- const directory = join72(root, ".tmp/context-runtime/packages");
89095
+ const directory = join73(root, ".tmp/context-runtime/packages");
89064
89096
  try {
89065
89097
  const files = (await readdir17(directory)).filter((name3) => name3.endsWith(".json")).sort();
89066
89098
  if (!files.length)
89067
89099
  return indexerProtocolDigest(null);
89068
- return indexerProtocolDigest(await Promise.all(files.map((name3) => readFile61(join72(directory, name3), "utf8"))));
89100
+ return indexerProtocolDigest(await Promise.all(files.map((name3) => readFile61(join73(directory, name3), "utf8"))));
89069
89101
  } catch (error) {
89070
89102
  if (error.code === "ENOENT")
89071
89103
  return indexerProtocolDigest(null);
@@ -89164,7 +89196,7 @@ async function observeKnowledgeMaintenance(root) {
89164
89196
  async function maintenanceRevision(root) {
89165
89197
  const observed = await observeKnowledgeMaintenance(root);
89166
89198
  const localInputs = observed.state.active ? {
89167
- revision: await readFile61(join72(root, MAINTENANCE_ROOT, "revision.json"), "utf8").catch((error) => {
89199
+ revision: await readFile61(join73(root, MAINTENANCE_ROOT, "revision.json"), "utf8").catch((error) => {
89168
89200
  if (error.code === "ENOENT")
89169
89201
  return null;
89170
89202
  throw error;
@@ -89241,7 +89273,7 @@ async function finishMaintenanceRevision(root, outcome = "completed") {
89241
89273
  outcome = state.active.completion_outcome;
89242
89274
  state.active.phase = "finishing";
89243
89275
  await saveMaintenance(root, state);
89244
- await rm15(join72(root, MAINTENANCE_ROOT, "revision.json"), { force: true });
89276
+ await rm15(join73(root, MAINTENANCE_ROOT, "revision.json"), { force: true });
89245
89277
  state.completed.push({ id: state.active.input.id, input_digest: indexerProtocolDigest(state.active.input), outcome });
89246
89278
  delete state.active;
89247
89279
  await saveMaintenance(root, state);
@@ -89275,8 +89307,8 @@ async function discardMaintenanceDraft(root) {
89275
89307
  const owned = new Set([...request?.batch_candidates ?? [], ...request?.candidate ? [request.candidate] : []].map((item) => item.candidate_id));
89276
89308
  if (candidates.some((item) => !owned.has(item.candidate_id)))
89277
89309
  throw new TypeError("Unrelated Candidates are present; no draft was discarded. Inspect the current review before retrying cancellation.");
89278
- await rm15(join72(root, CANDIDATE_LEDGER_FILE), { force: true });
89279
- await rm15(join72(root, MAINTENANCE_ROOT, "revision.json"), { force: true });
89310
+ await rm15(join73(root, CANDIDATE_LEDGER_FILE), { force: true });
89311
+ await rm15(join73(root, MAINTENANCE_ROOT, "revision.json"), { force: true });
89280
89312
  const { closeProjectWorkspace: closeProjectWorkspace2 } = await Promise.resolve().then(() => (init_close(), exports_close));
89281
89313
  const { buildProjectPackages: buildProjectPackages2 } = await Promise.resolve().then(() => (init_packageBuilder(), exports_packageBuilder));
89282
89314
  await closeProjectWorkspace2(root);
@@ -89315,7 +89347,7 @@ __export(exports_approvedRevision, {
89315
89347
  APPROVED_REVISION_PATH: () => APPROVED_REVISION_PATH
89316
89348
  });
89317
89349
  import { readFile as readFile62, realpath as realpath8, rm as rm16 } from "node:fs/promises";
89318
- import { join as join73, relative as relative21, isAbsolute as isAbsolute13 } from "node:path";
89350
+ import { join as join74, relative as relative21, isAbsolute as isAbsolute13 } from "node:path";
89319
89351
  function requestDigest(input) {
89320
89352
  const scopes = input.processed_scopes?.filter((scope2) => input.target.source_refs.some((ref2) => ref2 === scope2.source_ref || ref2.startsWith(`${scope2.source_ref}#`) || ref2.startsWith(`${scope2.source_ref}/`)));
89321
89353
  const ids = new Set(scopes?.map((scope2) => scope2.requirement_ref));
@@ -89353,7 +89385,7 @@ function revisionCandidateFingerprint(revision, markdown, sections) {
89353
89385
  }
89354
89386
  async function readApprovedRevision(projectRoot) {
89355
89387
  try {
89356
- return parseApprovedRevision(JSON.parse(await readFile62(join73(projectRoot, await revisionStoragePath(projectRoot)), "utf8")));
89388
+ return parseApprovedRevision(JSON.parse(await readFile62(join74(projectRoot, await revisionStoragePath(projectRoot)), "utf8")));
89357
89389
  } catch (error) {
89358
89390
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
89359
89391
  return;
@@ -89412,12 +89444,12 @@ async function resolveApprovedRevisionAuthor(projectRoot, request) {
89412
89444
  }
89413
89445
  async function targetBytes(projectRoot, path2) {
89414
89446
  const project = await realpath8(projectRoot);
89415
- const root = await realpath8(join73(projectRoot, "knowledge"));
89447
+ const root = await realpath8(join74(projectRoot, "knowledge"));
89416
89448
  const rootRelative = relative21(project, root);
89417
89449
  if (isAbsolute13(rootRelative) || rootRelative === ".." || rootRelative.startsWith("../")) {
89418
89450
  throw new TypeError("Approved knowledge directory leaves the Context workspace");
89419
89451
  }
89420
- const target = await realpath8(join73(root, path2));
89452
+ const target = await realpath8(join74(root, path2));
89421
89453
  const rel = relative21(root, target);
89422
89454
  if (isAbsolute13(rel) || rel === ".." || rel.startsWith("../"))
89423
89455
  throw new TypeError("Approved revision target leaves knowledge/");
@@ -89573,7 +89605,7 @@ ${import_yaml36.default.stringify({ ...import_yaml36.default.parse(fields), type
89573
89605
  revision: requestDigest(payload)
89574
89606
  });
89575
89607
  if (input.persist !== false)
89576
- await atomicWriteFile(join73(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify(request)}
89608
+ await atomicWriteFile(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify(request)}
89577
89609
  `);
89578
89610
  return {
89579
89611
  status: "author-reopened",
@@ -89684,17 +89716,17 @@ async function completeApprovedRevision(input) {
89684
89716
  const { prepareRevisionBatchContinuation: prepareRevisionBatchContinuation3 } = await Promise.resolve().then(() => (init_approvedRevisionBatch(), exports_approvedRevisionBatch));
89685
89717
  const next2 = await prepareRevisionBatchContinuation3(input.projectRoot, request, request.batch_candidates ?? []);
89686
89718
  if (next2 || request.batch_candidates?.length || request.build_pending) {
89687
- await atomicWriteFile(join73(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify(next2 ?? { ...request, review_ready: true })}
89719
+ await atomicWriteFile(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify(next2 ?? { ...request, review_ready: true })}
89688
89720
  `);
89689
89721
  } else {
89690
89722
  await advanceApprovedRevision(input.projectRoot, request);
89691
89723
  }
89692
89724
  return;
89693
89725
  }
89694
- const current2 = await readFile62(join73(input.projectRoot, await revisionStoragePath(input.projectRoot)), "utf8");
89726
+ const current2 = await readFile62(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), "utf8");
89695
89727
  let previous2;
89696
89728
  try {
89697
- previous2 = await readFile62(join73(input.projectRoot, CANDIDATE_LEDGER_FILE), "utf8");
89729
+ previous2 = await readFile62(join74(input.projectRoot, CANDIDATE_LEDGER_FILE), "utf8");
89698
89730
  } catch (error) {
89699
89731
  if (!(error && typeof error === "object" && ("code" in error) && error.code === "ENOENT"))
89700
89732
  throw error;
@@ -89776,7 +89808,7 @@ async function advanceApprovedRevision(projectRoot, request, buildPending = fals
89776
89808
  return;
89777
89809
  const { readProductionStage: readProductionStage2 } = await Promise.resolve().then(() => (init_productionStageStore(), exports_productionStageStore));
89778
89810
  if (await readProductionStage2(projectRoot)) {
89779
- await rm16(join73(projectRoot, await revisionStoragePath(projectRoot)), { force: true });
89811
+ await rm16(join74(projectRoot, await revisionStoragePath(projectRoot)), { force: true });
89780
89812
  return;
89781
89813
  }
89782
89814
  const { clearCompletedLifecycle: clearCompletedLifecycle2 } = await Promise.resolve().then(() => (init_lifecycleCleanup(), exports_lifecycleCleanup));
@@ -89847,12 +89879,12 @@ async function reopenApprovedRevision(input) {
89847
89879
  }))
89848
89880
  } : {}
89849
89881
  } };
89850
- const current2 = await readFile62(join73(input.projectRoot, await revisionStoragePath(input.projectRoot)), "utf8");
89882
+ const current2 = await readFile62(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), "utf8");
89851
89883
  const content3 = `${JSON.stringify({ ...payload, revision: requestDigest(payload) })}
89852
89884
  `;
89853
89885
  let ledger;
89854
89886
  try {
89855
- ledger = await readFile62(join73(input.projectRoot, CANDIDATE_LEDGER_FILE), "utf8");
89887
+ ledger = await readFile62(join74(input.projectRoot, CANDIDATE_LEDGER_FILE), "utf8");
89856
89888
  } catch (error) {
89857
89889
  if (!(error && typeof error === "object" && ("code" in error) && error.code === "ENOENT"))
89858
89890
  throw error;
@@ -89965,7 +89997,7 @@ var init_sourceInputMutation = __esm(() => {
89965
89997
  // src/project/documentCapture.ts
89966
89998
  import { createHash as createHash21 } from "node:crypto";
89967
89999
  import { mkdir as mkdir28, readdir as readdir18, readFile as readFile63, rm as rm17, stat as stat9, writeFile as writeFile23 } from "node:fs/promises";
89968
- import { basename as basename8, dirname as dirname34, extname as extname12, join as join74, relative as relative22, resolve as resolve24 } from "node:path";
90000
+ import { basename as basename8, dirname as dirname34, extname as extname12, join as join75, relative as relative22, resolve as resolve24 } from "node:path";
89969
90001
  function toPosixPath7(path2) {
89970
90002
  return path2.split(/[\\/]+/u).filter((part) => part.length > 0).join("/");
89971
90003
  }
@@ -90088,7 +90120,7 @@ async function walkMarkdownFiles(input) {
90088
90120
  const visit3 = async (dir) => {
90089
90121
  const entries2 = await readdir18(dir, { withFileTypes: true });
90090
90122
  for (const entry of entries2) {
90091
- const absolutePath = join74(dir, entry.name);
90123
+ const absolutePath = join75(dir, entry.name);
90092
90124
  if (entry.isDirectory()) {
90093
90125
  await visit3(absolutePath);
90094
90126
  continue;
@@ -90117,7 +90149,7 @@ async function writeTextIfChanged(path2, content3) {
90117
90149
  await writeFile23(path2, content3, "utf8");
90118
90150
  }
90119
90151
  function sourceManifestPath(entry) {
90120
- return entry.snapshot?.manifest ?? join74(entry.materializedAt, "manifest.json");
90152
+ return entry.snapshot?.manifest ?? join75(entry.materializedAt, "manifest.json");
90121
90153
  }
90122
90154
  function runtimeError3(message, detail) {
90123
90155
  return new ContextError(ExitCode.UserError, message, {
@@ -90190,7 +90222,7 @@ async function removeEmptySnapshotDirs(root, dir = root) {
90190
90222
  for (const entry of entries2) {
90191
90223
  if (!entry.isDirectory() || entry.name === ".tmp" || entry.name === ".cache")
90192
90224
  continue;
90193
- await removeEmptySnapshotDirs(root, join74(dir, entry.name));
90225
+ await removeEmptySnapshotDirs(root, join75(dir, entry.name));
90194
90226
  }
90195
90227
  if (dir === root)
90196
90228
  return;
@@ -90202,7 +90234,7 @@ async function removeEmptySnapshotDirs(root, dir = root) {
90202
90234
  async function cleanupStaleSnapshotFiles(input) {
90203
90235
  for (const path2 of input.previousPaths) {
90204
90236
  if (!input.currentPaths.has(path2)) {
90205
- await rm17(join74(input.materializedAtAbsPath, path2), { force: true });
90237
+ await rm17(join75(input.materializedAtAbsPath, path2), { force: true });
90206
90238
  }
90207
90239
  }
90208
90240
  await removeEmptySnapshotDirs(input.materializedAtAbsPath);
@@ -90385,9 +90417,9 @@ async function runCaptureFilePhaseUnlocked(input) {
90385
90417
  documentSnapshot
90386
90418
  });
90387
90419
  const manifestPath = sourceManifestPath(entry);
90388
- const manifestAbsPath = join74(input.projectRoot, manifestPath);
90420
+ const manifestAbsPath = join75(input.projectRoot, manifestPath);
90389
90421
  const materializedAt = entry.materializedAt;
90390
- const materializedAtAbsPath = join74(input.projectRoot, materializedAt);
90422
+ const materializedAtAbsPath = join75(input.projectRoot, materializedAt);
90391
90423
  const manifestInput = {
90392
90424
  sourceType: "file",
90393
90425
  sourceName: resolved.sourceName,
@@ -90437,13 +90469,13 @@ async function runCaptureFilePhaseUnlocked(input) {
90437
90469
  }));
90438
90470
  try {
90439
90471
  for (const file of snapshotFiles) {
90440
- await writeTextIfChanged(join74(materializedAtAbsPath, file.path), String(file.bytes));
90472
+ await writeTextIfChanged(join75(materializedAtAbsPath, file.path), String(file.bytes));
90441
90473
  }
90442
90474
  for (const file of files.metadata) {
90443
- await writeTextIfChanged(join74(materializedAtAbsPath, file.snapshotPath), routeMetadata.rawByPath.get(file.snapshotPath) ?? "");
90475
+ await writeTextIfChanged(join75(materializedAtAbsPath, file.snapshotPath), routeMetadata.rawByPath.get(file.snapshotPath) ?? "");
90444
90476
  }
90445
90477
  for (const asset of linkedAssets) {
90446
- await writeCaptureAssetIfChanged(join74(materializedAtAbsPath, asset.snapshotPath), asset.bytes);
90478
+ await writeCaptureAssetIfChanged(join75(materializedAtAbsPath, asset.snapshotPath), asset.bytes);
90447
90479
  }
90448
90480
  await writeTextIfChanged(manifestAbsPath, manifestContent);
90449
90481
  await cleanupStaleSnapshotFiles({
@@ -90621,7 +90653,7 @@ var init_larkCaptureReport = __esm(() => {
90621
90653
 
90622
90654
  // src/project/documentSnapshotFidelity.ts
90623
90655
  import { readFileSync as readFileSync7 } from "node:fs";
90624
- import { join as join75 } from "node:path";
90656
+ import { join as join76 } from "node:path";
90625
90657
  function readDocumentSnapshotCaptureReport(input) {
90626
90658
  const summary = input.manifest.metadata?.capture?.report;
90627
90659
  if (summary === undefined)
@@ -90630,7 +90662,7 @@ function readDocumentSnapshotCaptureReport(input) {
90630
90662
  if (asset === undefined || asset.role !== "audit" || asset.content_hash === undefined) {
90631
90663
  throw new TypeError(`snapshot capture report is not registered as a hashed audit asset: ${summary.path}`);
90632
90664
  }
90633
- const bytes = readFileSync7(join75(input.projectRoot, input.materializedAt, summary.path));
90665
+ const bytes = readFileSync7(join76(input.projectRoot, input.materializedAt, summary.path));
90634
90666
  if (computeDocumentContentHash(bytes) !== asset.content_hash) {
90635
90667
  throw new TypeError(`snapshot capture report hash does not match manifest: ${summary.path}`);
90636
90668
  }
@@ -90728,7 +90760,7 @@ function larkSnapshotIdentityDiagnostic(source2, manifest) {
90728
90760
  // src/project/repoSourceModules.ts
90729
90761
  import { existsSync as existsSync19 } from "node:fs";
90730
90762
  import { readFile as readFile64, readdir as readdir19 } from "node:fs/promises";
90731
- import { join as join76, resolve as resolve25 } from "node:path";
90763
+ import { join as join77, resolve as resolve25 } from "node:path";
90732
90764
  async function rootNames(root) {
90733
90765
  try {
90734
90766
  return (await readdir19(root)).sort();
@@ -90737,7 +90769,7 @@ async function rootNames(root) {
90737
90769
  }
90738
90770
  }
90739
90771
  async function packageEntries(root) {
90740
- const path2 = join76(root, "package.json");
90772
+ const path2 = join77(root, "package.json");
90741
90773
  if (!existsSync19(path2))
90742
90774
  return [];
90743
90775
  try {
@@ -90749,9 +90781,9 @@ async function packageEntries(root) {
90749
90781
  }
90750
90782
  }
90751
90783
  async function planningEvidence(inspectPath, module) {
90752
- const root = module.path === "." ? inspectPath : join76(inspectPath, module.path);
90784
+ const root = module.path === "." ? inspectPath : join77(inspectPath, module.path);
90753
90785
  const names = await rootNames(root);
90754
- const commonEntries = ["src/index.ts", "src/index.tsx", "src/main.ts", "src/main.tsx", "main.go"].filter((path2) => existsSync19(join76(root, path2)));
90786
+ const commonEntries = ["src/index.ts", "src/index.tsx", "src/main.ts", "src/main.tsx", "main.go"].filter((path2) => existsSync19(join77(root, path2)));
90755
90787
  const protocolNames = names.filter((name3) => /(?:openapi|swagger|schema|protocol|idl)/iu.test(name3) || /\.(?:proto|thrift)$/iu.test(name3));
90756
90788
  const lifecycleNames = names.filter((name3) => /(?:generated|vendor|mirror|legacy|sync)/iu.test(name3));
90757
90789
  return {
@@ -90789,7 +90821,7 @@ function suggestedModuleName(module) {
90789
90821
  return slug || "module";
90790
90822
  }
90791
90823
  async function inspectRepoSourceModules(input) {
90792
- const inspectPath = input.scopedAbs !== null && existsSync19(input.scopedAbs) ? input.scopedAbs : join76(input.projectRoot, input.status.materializedAt);
90824
+ const inspectPath = input.scopedAbs !== null && existsSync19(input.scopedAbs) ? input.scopedAbs : join77(input.projectRoot, input.status.materializedAt);
90793
90825
  const modules = existsSync19(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
90794
90826
  const recommended_sources = modules.filter((module) => module.path !== "." || modules.length === 1).map((module) => {
90795
90827
  const local = sourceModuleLocalForDisplay({ source: input.source, status: input.status, module });
@@ -90829,7 +90861,7 @@ var init_repoSourceModules = __esm(() => {
90829
90861
 
90830
90862
  // src/project/repoSourceRegistry.ts
90831
90863
  import { existsSync as existsSync20 } from "node:fs";
90832
- import { join as join77 } from "node:path";
90864
+ import { join as join78 } from "node:path";
90833
90865
  function assertRepoModuleName(name3) {
90834
90866
  if (!SOURCE_NAME_PATTERN2.test(name3)) {
90835
90867
  throw new ContextError(ExitCode.UserError, `repo source name must be a lowercase path-safe slug: ${name3}`, {
@@ -90880,7 +90912,7 @@ function registryEntryToRecord(entry) {
90880
90912
  };
90881
90913
  }
90882
90914
  function registryPath(projectRoot) {
90883
- return join77(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
90915
+ return join78(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
90884
90916
  }
90885
90917
  function defaultRepoMaterializedAt(source2) {
90886
90918
  return `sources/repo/${source2.namespace}/${source2.module}`;
@@ -90942,7 +90974,7 @@ import { existsSync as existsSync21 } from "node:fs";
90942
90974
  import { lstat as lstat9, mkdir as mkdir29, readFile as readFile65, readlink, realpath as realpath9, rm as rm18, symlink as symlink3 } from "node:fs/promises";
90943
90975
  import { execFile as execFile9 } from "node:child_process";
90944
90976
  import { promisify as promisify9 } from "node:util";
90945
- import { dirname as dirname35, isAbsolute as isAbsolute14, join as join78, relative as relative23, resolve as resolve26 } from "node:path";
90977
+ import { dirname as dirname35, isAbsolute as isAbsolute14, join as join79, relative as relative23, resolve as resolve26 } from "node:path";
90946
90978
  function nonEmpty(value) {
90947
90979
  if (value == null)
90948
90980
  return null;
@@ -90996,13 +91028,13 @@ async function gitOutput(cwd, args) {
90996
91028
  }
90997
91029
  }
90998
91030
  async function readGitOriginRemote(cwd) {
90999
- const directConfigPath = join78(cwd, ".git", "config");
91031
+ const directConfigPath = join79(cwd, ".git", "config");
91000
91032
  let config = await readFile65(directConfigPath, "utf8").catch(() => "");
91001
91033
  if (config.length === 0) {
91002
91034
  const gitDir = await resolveGitDir(cwd);
91003
91035
  if (gitDir === null)
91004
91036
  return null;
91005
- config = await readFile65(join78(gitDir, "config"), "utf8").catch(() => "");
91037
+ config = await readFile65(join79(gitDir, "config"), "utf8").catch(() => "");
91006
91038
  }
91007
91039
  let inOriginBlock = false;
91008
91040
  for (const line of config.split(/\r?\n/u)) {
@@ -91022,7 +91054,7 @@ async function readGitOriginRemote(cwd) {
91022
91054
  async function resolveGitRoot(cwd) {
91023
91055
  let current2 = resolve26(cwd);
91024
91056
  while (true) {
91025
- if (existsSync21(join78(current2, ".git")))
91057
+ if (existsSync21(join79(current2, ".git")))
91026
91058
  return current2;
91027
91059
  const parent = dirname35(current2);
91028
91060
  if (parent === current2)
@@ -91031,7 +91063,7 @@ async function resolveGitRoot(cwd) {
91031
91063
  }
91032
91064
  }
91033
91065
  async function resolveGitDir(cwd) {
91034
- const dotGit = join78(cwd, ".git");
91066
+ const dotGit = join79(cwd, ".git");
91035
91067
  if (!existsSync21(dotGit))
91036
91068
  return null;
91037
91069
  const stats = await lstat9(dotGit);
@@ -91049,17 +91081,17 @@ async function readGitHead(cwd) {
91049
91081
  const gitDir = await resolveGitDir(cwd);
91050
91082
  if (gitDir === null)
91051
91083
  return null;
91052
- const headRaw = (await readFile65(join78(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
91084
+ const headRaw = (await readFile65(join79(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
91053
91085
  if (/^[a-f0-9]{40}$/iu.test(headRaw))
91054
91086
  return headRaw.toLowerCase();
91055
91087
  const match = /^ref:\s*(.+)\s*$/iu.exec(headRaw);
91056
91088
  const refPath = match?.[1];
91057
91089
  if (refPath === undefined)
91058
91090
  return null;
91059
- const looseRef = (await readFile65(join78(gitDir, refPath), "utf8").catch(() => "")).trim();
91091
+ const looseRef = (await readFile65(join79(gitDir, refPath), "utf8").catch(() => "")).trim();
91060
91092
  if (/^[a-f0-9]{40}$/iu.test(looseRef))
91061
91093
  return looseRef.toLowerCase();
91062
- const packedRefs = await readFile65(join78(gitDir, "packed-refs"), "utf8").catch(() => "");
91094
+ const packedRefs = await readFile65(join79(gitDir, "packed-refs"), "utf8").catch(() => "");
91063
91095
  for (const line of packedRefs.split(/\r?\n/u)) {
91064
91096
  if (line.startsWith("#") || line.startsWith("^"))
91065
91097
  continue;
@@ -91070,7 +91102,7 @@ async function readGitHead(cwd) {
91070
91102
  return null;
91071
91103
  }
91072
91104
  async function ensureMaterializedSymlink(input) {
91073
- const linkPath = join78(input.projectRoot, input.materializedAt);
91105
+ const linkPath = join79(input.projectRoot, input.materializedAt);
91074
91106
  await mkdir29(dirname35(linkPath), { recursive: true });
91075
91107
  if (existsSync21(linkPath)) {
91076
91108
  const stats = await lstat9(linkPath);
@@ -91089,7 +91121,7 @@ async function ensureMaterializedSymlink(input) {
91089
91121
  return true;
91090
91122
  }
91091
91123
  async function diagnoseMaterializedSymlink(input) {
91092
- const linkPath = join78(input.projectRoot, input.materializedAt);
91124
+ const linkPath = join79(input.projectRoot, input.materializedAt);
91093
91125
  if (!existsSync21(linkPath)) {
91094
91126
  input.diagnostics.push(`materialized path is missing: ${input.materializedAt}`);
91095
91127
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to materialize the local source link.`);
@@ -91312,7 +91344,7 @@ async function inspectRepoSource(input) {
91312
91344
  const subpath = normalizeSubpath2(source2.subpath);
91313
91345
  const scopedAbs = localAbs === null ? null : scopedLocalPath(localAbs, subpath);
91314
91346
  const scopeExists = scopedAbs !== null && existsSync21(scopedAbs);
91315
- let materialized = existsSync21(join78(input.projectRoot, materializedAt));
91347
+ let materialized = existsSync21(join79(input.projectRoot, materializedAt));
91316
91348
  const checkout = await inspectRepoCheckout({
91317
91349
  source: source2,
91318
91350
  localAbs,
@@ -91498,7 +91530,7 @@ var init_entityId = __esm(() => {
91498
91530
  // src/project/reviewShared.ts
91499
91531
  import { createHash as createHash22 } from "node:crypto";
91500
91532
  import { mkdir as mkdir30, writeFile as writeFile24 } from "node:fs/promises";
91501
- import { dirname as dirname36, join as join79 } from "node:path";
91533
+ import { dirname as dirname36, join as join80 } from "node:path";
91502
91534
  function isRecord14(value) {
91503
91535
  return value !== null && typeof value === "object" && !Array.isArray(value);
91504
91536
  }
@@ -91541,7 +91573,7 @@ async function buildApprovedArticleIndex(projectRoot) {
91541
91573
  if (!isApprovedKnowledgeMarkdownPath(rel))
91542
91574
  continue;
91543
91575
  const { absPath, content: content3 } = file;
91544
- const relPath = join79("knowledge", collection, rel);
91576
+ const relPath = join80("knowledge", collection, rel);
91545
91577
  assetReferencesByRelPath.set(relPath, knowledgeAssetReferences({
91546
91578
  pageRelPath: relPath,
91547
91579
  content: content3
@@ -91554,7 +91586,7 @@ async function buildApprovedArticleIndex(projectRoot) {
91554
91586
  continue;
91555
91587
  const frontmatter2 = hydrateApprovedFrontmatter({
91556
91588
  frontmatter: parsed,
91557
- relPath: join79(collection, rel),
91589
+ relPath: join80(collection, rel),
91558
91590
  metadata
91559
91591
  });
91560
91592
  const article = articlesByPath.get(`${collection}/${rel}`);
@@ -91609,8 +91641,8 @@ ${yaml3}
91609
91641
  }
91610
91642
  async function writeReviewActionLog(input) {
91611
91643
  const stamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
91612
- const relPath = join79(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
91613
- const path2 = join79(input.projectRoot, relPath);
91644
+ const relPath = join80(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
91645
+ const path2 = join80(input.projectRoot, relPath);
91614
91646
  await mkdir30(dirname36(path2), { recursive: true });
91615
91647
  await writeFile24(path2, `${JSON.stringify({
91616
91648
  action: input.action,
@@ -91643,7 +91675,7 @@ var init_reviewShared = __esm(() => {
91643
91675
  init_knowledgeAssets();
91644
91676
  init_entityId();
91645
91677
  import_yaml38 = __toESM(require_dist(), 1);
91646
- REVIEW_ACTION_ROOT2 = join79(".tmp", "context-runtime", "review-actions");
91678
+ REVIEW_ACTION_ROOT2 = join80(".tmp", "context-runtime", "review-actions");
91647
91679
  });
91648
91680
 
91649
91681
  // src/project/managedDocumentStatus.ts
@@ -91719,7 +91751,7 @@ __export(exports_statusReaders, {
91719
91751
  countFiles: () => countFiles
91720
91752
  });
91721
91753
  import { existsSync as existsSync22, readFileSync as readFileSync8 } from "node:fs";
91722
- import { join as join80 } from "node:path";
91754
+ import { join as join81 } from "node:path";
91723
91755
  async function countFiles(root, predicate) {
91724
91756
  if (!existsSync22(root))
91725
91757
  return 0;
@@ -91728,7 +91760,7 @@ async function countFiles(root, predicate) {
91728
91760
  const entries2 = await readCommandDirectory(dir);
91729
91761
  for (const entry of entries2) {
91730
91762
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
91731
- const abs = join80(dir, entry.name);
91763
+ const abs = join81(dir, entry.name);
91732
91764
  if (entry.isDirectory())
91733
91765
  await visit3(abs, rel);
91734
91766
  else if (entry.isFile() && predicate(rel))
@@ -91919,7 +91951,7 @@ async function documentSourceSiteHint(input) {
91919
91951
  });
91920
91952
  }
91921
91953
  function documentSnapshotReadiness(input) {
91922
- const manifestPath = join80(input.projectRoot, input.manifest);
91954
+ const manifestPath = join81(input.projectRoot, input.manifest);
91923
91955
  if (!existsSync22(manifestPath)) {
91924
91956
  return {
91925
91957
  ready: false,
@@ -91989,7 +92021,7 @@ function documentSnapshotReadiness(input) {
91989
92021
  const missingFiles = [
91990
92022
  ...manifest.files.map((file) => file.path),
91991
92023
  ...(manifest.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
91992
- ].filter((path2) => !existsSync22(join80(input.projectRoot, input.materializedAt, path2)));
92024
+ ].filter((path2) => !existsSync22(join81(input.projectRoot, input.materializedAt, path2)));
91993
92025
  if (missingFiles.length > 0) {
91994
92026
  return {
91995
92027
  ready: false,
@@ -92780,7 +92812,7 @@ var init_workflowProvider = __esm(() => {
92780
92812
 
92781
92813
  // src/project/productionStageRefresh.ts
92782
92814
  import { readFile as readFile67 } from "node:fs/promises";
92783
- import { join as join82 } from "node:path";
92815
+ import { join as join83 } from "node:path";
92784
92816
  async function refreshProductionStageSources(projectRoot, stage) {
92785
92817
  const affected = new Set(stage.gaps.map((gap) => gap.scope));
92786
92818
  const unavailable = new Map;
@@ -92820,8 +92852,8 @@ Restore the authorized source and retry preparation.
92820
92852
  tasks: stage.tasks.map((task) => !["accepted", "excluded", "replaced"].includes(task.status) && task.sources.some((source2) => affected.has(source2.scope)) ? { ...task, status: "blocked", reason: "Source material refreshed; investigate and explicitly replace this unfinished task." } : task)
92821
92853
  });
92822
92854
  const directory = productionStageDirectory(stage.id);
92823
- const contents2 = new Map([...sourceMaterials].map(([scope2, content3]) => [join82(directory, productionSourceFile(scope2)), content3]));
92824
- contents2.set(join82(directory, "manifest.json"), `${JSON.stringify(updated)}
92855
+ const contents2 = new Map([...sourceMaterials].map(([scope2, content3]) => [join83(directory, productionSourceFile(scope2)), content3]));
92856
+ contents2.set(join83(directory, "manifest.json"), `${JSON.stringify(updated)}
92825
92857
  `);
92826
92858
  const targets = [];
92827
92859
  for (const [path2, content3] of contents2) {
@@ -92951,7 +92983,7 @@ var init_productionReport = __esm(() => {
92951
92983
  });
92952
92984
 
92953
92985
  // src/project/productionPlanningRoute.ts
92954
- import { join as join83 } from "node:path";
92986
+ import { join as join84 } from "node:path";
92955
92987
  async function productionPlanningRoute(input, stage) {
92956
92988
  const request = stage ? undefined : await productionPlanningRequest(input.projectRoot);
92957
92989
  const present = !!stage || !!request;
@@ -92989,7 +93021,7 @@ async function productionPlanningRoute(input, stage) {
92989
93021
  id: `production/${stage.id}/planning`,
92990
93022
  kind: "context-view",
92991
93023
  media_type: "text/markdown",
92992
- path: join83(input.projectRoot, productionStageDirectory(stage.id), "planning.md"),
93024
+ path: join84(input.projectRoot, productionStageDirectory(stage.id), "planning.md"),
92993
93025
  read_state: "read-required"
92994
93026
  }] : []
92995
93027
  ],
@@ -93008,7 +93040,7 @@ var init_productionPlanningRoute = __esm(() => {
93008
93040
 
93009
93041
  // src/project/productionWorkflowRoute.ts
93010
93042
  import { existsSync as existsSync24 } from "node:fs";
93011
- import { join as join84 } from "node:path";
93043
+ import { join as join85 } from "node:path";
93012
93044
  async function productionWorkflowRoute(input) {
93013
93045
  const stage = await readProductionStage(input.projectRoot);
93014
93046
  if (!stage || !stage.planning_complete)
@@ -93026,7 +93058,7 @@ async function productionWorkflowRoute(input) {
93026
93058
  const selected = new Set(dispatch.batches.flatMap((batch) => batch.tasks));
93027
93059
  const context = { workspace: input.projectRoot, authorities: [...input.authorities], facts: { production: {
93028
93060
  report_approved: stage.report_approved,
93029
- prepared: !dispatch.batches.length || existsSync24(join84(input.projectRoot, directory, "stage.md")) && stage.tasks.filter((task) => selected.has(task.id)).every((task) => task.status === "issued"),
93061
+ prepared: !dispatch.batches.length || existsSync24(join85(input.projectRoot, directory, "stage.md")) && stage.tasks.filter((task) => selected.has(task.id)).every((task) => task.status === "issued"),
93030
93062
  writing_complete: dispatch.batches.length === 0,
93031
93063
  complete: dispatch.state === "ended",
93032
93064
  review_clear: rejected.length === 0,
@@ -93043,7 +93075,7 @@ async function productionWorkflowRoute(input) {
93043
93075
  const resolved = await resolveRoute(provider, "indexer", "production", primary.routeId, context, evaluated.evaluation.revision);
93044
93076
  const report = resolved.node === "confirm-production-report";
93045
93077
  if (report)
93046
- await writeProductionProjection(input.projectRoot, join84(directory, "plan.md"), productionPlanMarkdown(stage));
93078
+ await writeProductionProjection(input.projectRoot, join85(directory, "plan.md"), productionPlanMarkdown(stage));
93047
93079
  const prepare = resolved.node === "prepare-production-stage";
93048
93080
  const writing = resolved.node === "work-production-stage";
93049
93081
  const repair = resolved.node === "repair-production-articles";
@@ -93058,7 +93090,7 @@ async function productionWorkflowRoute(input) {
93058
93090
  id: `production/${stage.id}/${report ? "plan" : "stage"}`,
93059
93091
  kind: "context-view",
93060
93092
  media_type: "text/markdown",
93061
- path: join84(input.projectRoot, directory, path3),
93093
+ path: join85(input.projectRoot, directory, path3),
93062
93094
  read_state: "read-required"
93063
93095
  });
93064
93096
  if (report || writing)
@@ -93069,18 +93101,18 @@ async function productionWorkflowRoute(input) {
93069
93101
  id: `production/${stage.id}/planning`,
93070
93102
  kind: "context-view",
93071
93103
  media_type: "text/markdown",
93072
- path: join84(input.projectRoot, directory, "planning.md"),
93104
+ path: join85(input.projectRoot, directory, "planning.md"),
93073
93105
  read_state: "read-required"
93074
93106
  });
93075
93107
  }
93076
93108
  if (repair) {
93077
- await writeProductionProjection(input.projectRoot, join84(directory, "repair.md"), [
93109
+ await writeProductionProjection(input.projectRoot, join85(directory, "repair.md"), [
93078
93110
  "# Revise rejected articles",
93079
93111
  "",
93080
93112
  ...rejected.map((candidate) => `- ${candidate.path}: ${candidate.review.title}`),
93081
93113
  "",
93082
93114
  "Use the user's Review feedback to add revision tasks for these article paths. Rejection does not cancel their planned responsibilities. Ask for missing feedback instead of guessing the reason.",
93083
- `Submit the plan amendment to ${path2} using ${join84(directory, "planning.schema.json")}. Keep accepted task identities unchanged; the CLI assigns the revision tasks and preserves article identities.`,
93115
+ `Submit the plan amendment to ${path2} using ${join85(directory, "planning.schema.json")}. Keep accepted task identities unchanged; the CLI assigns the revision tasks and preserves article identities.`,
93084
93116
  "Once issued, repair the affected sections through the existing edits submission. Unchanged sections and references do not need resubmission.",
93085
93117
  ""
93086
93118
  ].join(`
@@ -93089,7 +93121,7 @@ async function productionWorkflowRoute(input) {
93089
93121
  id: `production/${stage.id}/repair`,
93090
93122
  kind: "context-view",
93091
93123
  media_type: "text/markdown",
93092
- path: join84(input.projectRoot, directory, "repair.md"),
93124
+ path: join85(input.projectRoot, directory, "repair.md"),
93093
93125
  read_state: "read-required"
93094
93126
  });
93095
93127
  }
@@ -93106,7 +93138,7 @@ async function productionWorkflowRoute(input) {
93106
93138
  revision,
93107
93139
  reason_code: resolved.reasonCode,
93108
93140
  availability: resolved.availability,
93109
- summary: report ? `Present the report and wait. After approval, write {stage: ${stage.id}, decision: approved} to ${path2}.` : writing ? "Read the issued task directories. Coordinate them sequentially unless this caller supports independent Agents; only the coordinator submits shared state." : repair ? "Add revision tasks for rejected articles using the Review feedback; accepted production responsibilities remain unchanged." : investigate ? `Review pending configured scopes: ${stage.pending_scopes.filter((scope2) => !stage.gaps.some((gap2) => gap2.scope === scope2)).join(", ")}. Check their relevance to the current request and existing approved content before assigning investigation. Submit supported article tasks and remaining pending_scopes; do not infer missing articles from this list or repeat accepted work. If the requested articles are already accepted, context run --deliver --format json enters their Review while retaining unrelated pending scopes.` : resolved.node === "resolve-production-gap" ? `Source availability gaps: ${stage.gaps.map((gap2) => `${gap2.scope}: ${gap2.reason}`).join("; ")}. These failures do not establish missing knowledge or a new investigation assignment. Identify which sources the current task actually depends on; report unrelated configured-source failures separately. Preserve the configuration. To review completed articles independently, use context run --deliver --format json; this retains pending scopes and does not approve or publish content. If these sources are required, use context source recovery-plan --format json and context source restore with explicit local or clone decisions before preparation.` : "Prepare the current stage's eligible task directories.",
93141
+ summary: report ? `Present the report and apply context.gate.work_start_scope. After the applicable scope decision, write {stage: ${stage.id}, decision: approved} to ${path2}.` : writing ? "Read the issued task directories. Coordinate them sequentially unless this caller supports independent Agents; only the coordinator submits shared state." : repair ? "Add revision tasks for rejected articles using the Review feedback; accepted production responsibilities remain unchanged." : investigate ? `Review pending configured scopes: ${stage.pending_scopes.filter((scope2) => !stage.gaps.some((gap2) => gap2.scope === scope2)).join(", ")}. Check their relevance to the current request and existing approved content before assigning investigation. Submit supported article tasks and remaining pending_scopes; do not infer missing articles from this list or repeat accepted work. If the requested articles are already accepted, context run --deliver --format json enters their Review while retaining unrelated pending scopes.` : resolved.node === "resolve-production-gap" ? `Source availability gaps: ${stage.gaps.map((gap2) => `${gap2.scope}: ${gap2.reason}`).join("; ")}. These failures do not establish missing knowledge or a new investigation assignment. Identify which sources the current task actually depends on; report unrelated configured-source failures separately. Preserve the configuration. To review completed articles independently, use context run --deliver --format json; this retains pending scopes and does not approve or publish content. If these sources are required, use context source recovery-plan --format json and context source restore with explicit local or clone decisions before preparation.` : "Prepare the current stage's eligible task directories.",
93110
93142
  commands: report || prepare || writing || repair || investigate || gap ? [{
93111
93143
  command: command2,
93112
93144
  effect: "write",
@@ -97873,7 +97905,7 @@ var init_larkResourceCommand = __esm(() => {
97873
97905
  // src/lib/larkResourceMaterialization.ts
97874
97906
  import { createHash as createHash28 } from "node:crypto";
97875
97907
  import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as readdir21, rm as rm20 } from "node:fs/promises";
97876
- import { extname as extname13, join as join93 } from "node:path";
97908
+ import { extname as extname13, join as join94 } from "node:path";
97877
97909
  import { tmpdir } from "node:os";
97878
97910
  function countByKind(items, status) {
97879
97911
  const counts2 = new Map;
@@ -97981,7 +98013,7 @@ async function downloadedFile(input) {
97981
98013
  const bytes = await readFile74(input.localPath);
97982
98014
  return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes) };
97983
98015
  }
97984
- const tempRoot = await mkdtemp4(join93(tmpdir(), "context-lark-resource-"));
98016
+ const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-resource-"));
97985
98017
  try {
97986
98018
  await runLarkResourceCommand(input.runner, [
97987
98019
  "docs",
@@ -98002,7 +98034,7 @@ async function downloadedFile(input) {
98002
98034
  if (entries2.length !== 1)
98003
98035
  throw new Error(`media download produced ${entries2.length} files, expected exactly one`);
98004
98036
  const path3 = entries2[0]?.name ?? "resource.bin";
98005
- const bytes = await readFile74(join93(tempRoot, path3));
98037
+ const bytes = await readFile74(join94(tempRoot, path3));
98006
98038
  return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes) };
98007
98039
  } finally {
98008
98040
  await rm20(tempRoot, { recursive: true, force: true });
@@ -98093,9 +98125,9 @@ async function sheetMaterialization(resource, runner2, identity2) {
98093
98125
  const sheetId = resource.attributes["sheet-id"];
98094
98126
  if (token === undefined || sheetId === undefined)
98095
98127
  throw new Error("embedded Sheet requires token and sheet-id");
98096
- const tempRoot = await mkdtemp4(join93(tmpdir(), "context-lark-sheet-"));
98128
+ const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-sheet-"));
98097
98129
  try {
98098
- const outputPath = join93(tempRoot, "sheet.json");
98130
+ const outputPath = join94(tempRoot, "sheet.json");
98099
98131
  const stdout = await runLarkResourceCommand(runner2, [
98100
98132
  "sheets",
98101
98133
  "+csv-get",
@@ -98251,7 +98283,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
98251
98283
  if (token === undefined)
98252
98284
  throw new Error(`${resource.kind} has no whiteboard token`);
98253
98285
  const preview = await downloadedFile({ runner: runner2, identity: identity2, token, type: "whiteboard" });
98254
- const tempRoot = await mkdtemp4(join93(tmpdir(), "context-lark-whiteboard-"));
98286
+ const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-whiteboard-"));
98255
98287
  let rawPayload;
98256
98288
  try {
98257
98289
  await runLarkResourceCommand(runner2, [
@@ -98269,7 +98301,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
98269
98301
  "--format",
98270
98302
  "json"
98271
98303
  ], { cwd: tempRoot });
98272
- rawPayload = JSON.parse(await readFile74(join93(tempRoot, "raw.json"), "utf8"));
98304
+ rawPayload = JSON.parse(await readFile74(join94(tempRoot, "raw.json"), "utf8"));
98273
98305
  } finally {
98274
98306
  await rm20(tempRoot, { recursive: true, force: true });
98275
98307
  }
@@ -98631,7 +98663,7 @@ function resolveDocsFetchPlan(requested, runner2) {
98631
98663
  }
98632
98664
  return capabilitiesPromise.then((capabilities) => {
98633
98665
  if (!capabilities.supportsDocFormat) {
98634
- throw new LarkCliError(`${LARK_BIN} docs +fetch does not support --doc-format xml; upgrade @larksuite/cli before capturing Lark sources`, 0, "");
98666
+ throw new LarkCliError(`${LARK_BIN} docs +fetch does not support --doc-format xml; a compatible @larksuite/cli is required to capture Lark sources`, 0, "");
98635
98667
  }
98636
98668
  return { apiVersion: capabilities.apiVersion, docFormat: "xml" };
98637
98669
  });
@@ -98642,7 +98674,7 @@ function docsFetchFailureMessage(stderr, apiVersion) {
98642
98674
  const mentionsV2 = /api-version|--api-version|v2|deprecated|lark-cli update/iu.test(stderr);
98643
98675
  if (apiVersion === "v1" && mentionsV2) {
98644
98676
  return `${base}
98645
- Detected docs API v2 guidance from lark-cli. Upgrade @larksuite/cli and run \`lark-cli update\`; newer docs +fetch supports \`--api-version v2\`.`;
98677
+ Detected docs API v2 guidance from lark-cli; a compatible CLI with \`--api-version v2\` is required.`;
98646
98678
  }
98647
98679
  return base;
98648
98680
  }
@@ -98707,7 +98739,7 @@ function extractDocsFetchContent(payload, requestedFormat) {
98707
98739
  const withTitle = (result) => title2 === undefined ? result : { ...result, title: title2 };
98708
98740
  if (markdown !== undefined) {
98709
98741
  if (requestedFormat === "xml") {
98710
- throw new LarkCliError(`${LARK_BIN} docs +fetch returned Markdown despite --doc-format xml; capture stopped because the response cannot provide auditable rich-block fidelity. Upgrade lark-cli and retry.`, 0, "");
98742
+ throw new LarkCliError(`${LARK_BIN} docs +fetch returned Markdown despite --doc-format xml; capture stopped because the response cannot provide auditable rich-block fidelity. Use a compatible CLI and retry.`, 0, "");
98711
98743
  }
98712
98744
  return withTitle({ body: markdown, format: "markdown", recognizedShape: true });
98713
98745
  }
@@ -99038,7 +99070,7 @@ ${body2}`,
99038
99070
  };
99039
99071
  }
99040
99072
  var LARK_BIN = "lark-cli", MAX_FETCH_PAGES = 50, MAX_STRUCTURAL_FETCH_ATTEMPTS = 2, LarkCliNotInstalledError, LarkCliError, defaultRunner = (args, options) => new Promise((resolve8, reject) => {
99041
- const child = spawn4(LARK_BIN, args, {
99073
+ const child = spawn4(process.env.CONTEXT_LARK_CLI_BIN?.trim() || LARK_BIN, args, {
99042
99074
  ...options?.cwd === undefined ? {} : { cwd: options.cwd },
99043
99075
  stdio: ["ignore", "pipe", "pipe"]
99044
99076
  });
@@ -99119,7 +99151,7 @@ var init_sensitiveSourceLiteral = __esm(() => {
99119
99151
 
99120
99152
  // src/project/documentCaptureLark.ts
99121
99153
  import { readdir as readdir22, readFile as readFile75 } from "node:fs/promises";
99122
- import { basename as basename10, extname as extname14, join as join94 } from "node:path";
99154
+ import { basename as basename10, extname as extname14, join as join95 } from "node:path";
99123
99155
  function titleFromMarkdown2(markdown, fallbackPath) {
99124
99156
  const heading2 = markdown.split(`
99125
99157
  `).find((line) => /^#\s+\S/u.test(line));
@@ -99146,7 +99178,7 @@ async function fileContentMatches(path3, content3) {
99146
99178
  }
99147
99179
  }
99148
99180
  function sourceManifestPath2(entry) {
99149
- return entry.snapshot?.manifest ?? join94(entry.materializedAt, "manifest.json");
99181
+ return entry.snapshot?.manifest ?? join95(entry.materializedAt, "manifest.json");
99150
99182
  }
99151
99183
  function larkRuntimeError(message, detail) {
99152
99184
  return new ContextError(ExitCode.ExternalToolError, message, {
@@ -99193,6 +99225,7 @@ function larkTarget(entry) {
99193
99225
  }
99194
99226
  function larkErrorRecovery(error, sourceName) {
99195
99227
  const message = error instanceof Error ? error.message : String(error);
99228
+ const localCliRecovery = `Install @larksuite/cli in a private directory with \`npm install --prefix "$HOME/.cache/context/lark-cli" @larksuite/cli@latest\`, then rerun \`CONTEXT_LARK_CLI_BIN="$HOME/.cache/context/lark-cli/node_modules/.bin/lark-cli" context run capture:lark:${sourceName}\`. Keep this variable on subsequent Context commands that access Lark; do not replace the global lark-cli.`;
99196
99229
  const environmentIssue = detectExternalEnvironmentIssue(message);
99197
99230
  if (environmentIssue !== undefined) {
99198
99231
  return {
@@ -99207,13 +99240,13 @@ function larkErrorRecovery(error, sourceName) {
99207
99240
  if (error instanceof LarkCliNotInstalledError || /not installed|ENOENT/iu.test(message)) {
99208
99241
  return {
99209
99242
  reasonCode: "external.dependency-missing",
99210
- next: "Install lark-cli from https://github.com/larksuite/cli, then rerun capture"
99243
+ next: localCliRecovery
99211
99244
  };
99212
99245
  }
99213
99246
  if (/does not support --doc-format|api-version|deprecated|unsupported tool version|tool version unsupported/iu.test(message)) {
99214
99247
  return {
99215
99248
  reasonCode: "external.tool-version-unsupported",
99216
- next: "Run lark-cli update, confirm docs +fetch --help lists --doc-format, then rerun capture"
99249
+ next: localCliRecovery
99217
99250
  };
99218
99251
  }
99219
99252
  if (/empty|unsupported payload shape|not JSON|parse/iu.test(message)) {
@@ -99272,7 +99305,7 @@ function assetManifestEntry(asset, assetRoot) {
99272
99305
  };
99273
99306
  }
99274
99307
  async function listSnapshotAssetFiles(root2, assetRoot) {
99275
- const assetsRoot = join94(root2, assetRoot);
99308
+ const assetsRoot = join95(root2, assetRoot);
99276
99309
  const files = [];
99277
99310
  const visit4 = async (dir, prefix = assetRoot) => {
99278
99311
  let entries2;
@@ -99285,7 +99318,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
99285
99318
  }
99286
99319
  for (const entry of entries2) {
99287
99320
  const relPath = `${prefix}/${entry.name}`;
99288
- const absolutePath = join94(dir, entry.name);
99321
+ const absolutePath = join95(dir, entry.name);
99289
99322
  if (entry.isDirectory()) {
99290
99323
  await visit4(absolutePath, relPath);
99291
99324
  continue;
@@ -99300,7 +99333,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
99300
99333
  }
99301
99334
  async function staleSnapshotAssetPaths(input) {
99302
99335
  const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
99303
- return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join94(input.materializedAtAbsPath, path3));
99336
+ return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join95(input.materializedAtAbsPath, path3));
99304
99337
  }
99305
99338
  function normalizeLarkError(error, sourceName) {
99306
99339
  if (error instanceof ContextError)
@@ -99412,9 +99445,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
99412
99445
  locator
99413
99446
  }];
99414
99447
  const manifestPath = sourceManifestPath2(entry);
99415
- const manifestAbsPath = join94(input.projectRoot, manifestPath);
99448
+ const manifestAbsPath = join95(input.projectRoot, manifestPath);
99416
99449
  const materializedAt = entry.materializedAt;
99417
- const materializedAtAbsPath = join94(input.projectRoot, materializedAt);
99450
+ const materializedAtAbsPath = join95(input.projectRoot, materializedAt);
99418
99451
  const manifest = createDocumentSnapshotManifest({
99419
99452
  sourceType: "lark",
99420
99453
  sourceName: resolved.sourceName,
@@ -99448,13 +99481,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
99448
99481
  }));
99449
99482
  try {
99450
99483
  const requestedWrites = [{
99451
- path: join94(materializedAtAbsPath, documentPath),
99484
+ path: join95(materializedAtAbsPath, documentPath),
99452
99485
  bytes: normalized
99453
99486
  }];
99454
99487
  for (const asset of assets) {
99455
99488
  if (asset.bytes !== undefined) {
99456
99489
  requestedWrites.push({
99457
- path: join94(materializedAtAbsPath, asset.entry.path),
99490
+ path: join95(materializedAtAbsPath, asset.entry.path),
99458
99491
  bytes: asset.bytes
99459
99492
  });
99460
99493
  }
@@ -99471,7 +99504,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
99471
99504
  currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
99472
99505
  });
99473
99506
  await applyAtomicFileBatch({
99474
- transactionRoot: join94(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
99507
+ transactionRoot: join95(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
99475
99508
  writes,
99476
99509
  removals
99477
99510
  });
@@ -99901,7 +99934,7 @@ __export(exports_writeLockRecovery, {
99901
99934
  inspectWriterLock: () => inspectWriterLock
99902
99935
  });
99903
99936
  import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as readdir24, rename as rename8, rmdir as rmdir2 } from "node:fs/promises";
99904
- import { join as join99 } from "node:path";
99937
+ import { join as join100 } from "node:path";
99905
99938
  import { createHash as createHash30, randomUUID as randomUUID7 } from "node:crypto";
99906
99939
  async function inspectWriterLock(root2) {
99907
99940
  const path3 = await safeProjectTarget(root2, lockRelative);
@@ -99948,8 +99981,8 @@ async function recoverWriterLock(input) {
99948
99981
  };
99949
99982
  if (input.plan_digest !== before.digest)
99950
99983
  throw new Error("Writer lock changed; preview recovery again.");
99951
- const path3 = join99(input.projectRoot, lockRelative);
99952
- const guard = join99(path3, ".recovery");
99984
+ const path3 = join100(input.projectRoot, lockRelative);
99985
+ const guard = join100(path3, ".recovery");
99953
99986
  await mkdir34(guard);
99954
99987
  let archived = false;
99955
99988
  try {
@@ -99960,7 +99993,7 @@ async function recoverWriterLock(input) {
99960
99993
  if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
99961
99994
  throw new Error("Unexpected lock contents; preserve for diagnosis.");
99962
99995
  const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
99963
- await rename8(path3, join99(input.projectRoot, archive));
99996
+ await rename8(path3, join100(input.projectRoot, archive));
99964
99997
  archived = true;
99965
99998
  return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
99966
99999
  } finally {
@@ -99984,7 +100017,7 @@ __export(exports_taskRecovery, {
99984
100017
  RECOVERY_COMMAND: () => RECOVERY_COMMAND
99985
100018
  });
99986
100019
  import { existsSync as existsSync26 } from "node:fs";
99987
- import { dirname as dirname41, join as join100 } from "node:path";
100020
+ import { dirname as dirname41, join as join101 } from "node:path";
99988
100021
  import { lstat as lstat11, readdir as readdir25, readFile as readFile83 } from "node:fs/promises";
99989
100022
  async function recoveryText(root2, path3) {
99990
100023
  const target = await safeProjectTarget(root2, path3);
@@ -100002,7 +100035,7 @@ async function recoveryJournals(root2) {
100002
100035
  await safeProjectTarget(root2, path3);
100003
100036
  let stat10;
100004
100037
  try {
100005
- stat10 = await lstat11(join100(root2, path3));
100038
+ stat10 = await lstat11(join101(root2, path3));
100006
100039
  } catch (error) {
100007
100040
  if (error.code === "ENOENT")
100008
100041
  return;
@@ -100013,7 +100046,7 @@ async function recoveryJournals(root2) {
100013
100046
  if (stat10.isDirectory()) {
100014
100047
  if (depth > 3)
100015
100048
  throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
100016
- for (const name3 of (await readdir25(join100(root2, path3))).sort())
100049
+ for (const name3 of (await readdir25(join101(root2, path3))).sort())
100017
100050
  await visit4(`${path3}/${name3}`, depth + 1);
100018
100051
  } else if (stat10.isFile())
100019
100052
  entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
@@ -100025,8 +100058,8 @@ function recoveryResources() {
100025
100058
  try {
100026
100059
  const root2 = dirname41(contextWorkflowProviderPath());
100027
100060
  const resources = {
100028
- skill: join100(root2, "skills/recover-workspace/SKILL.md"),
100029
- issue_template: join100(root2, "resources/templates/recovery-issue.md")
100061
+ skill: join101(root2, "skills/recover-workspace/SKILL.md"),
100062
+ issue_template: join101(root2, "resources/templates/recovery-issue.md")
100030
100063
  };
100031
100064
  if (!Object.values(resources).every((path3) => existsSync26(path3)))
100032
100065
  throw new Error("Recovery resources are absent from this Provider.");
@@ -100112,7 +100145,7 @@ __export(exports_taskLocalSourceAdjustment, {
100112
100145
  adjustLocalRevisionSources: () => adjustLocalRevisionSources
100113
100146
  });
100114
100147
  import { readFile as readFile84 } from "node:fs/promises";
100115
- import { join as join101 } from "node:path";
100148
+ import { join as join102 } from "node:path";
100116
100149
  async function adjustLocalRevisionSources(root2, input) {
100117
100150
  const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
100118
100151
  if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
@@ -100155,7 +100188,7 @@ async function adjustLocalRevisionSources(root2, input) {
100155
100188
  if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
100156
100189
  throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
100157
100190
  }
100158
- const raw = await readFile84(join101(root2, await revisionStoragePath(root2)), "utf8");
100191
+ const raw = await readFile84(join102(root2, await revisionStoragePath(root2)), "utf8");
100159
100192
  let next2;
100160
100193
  const discardIds = new Set;
100161
100194
  if (!input.refresh) {
@@ -100258,7 +100291,7 @@ ${input.instruction}` : revision.instruction
100258
100291
  content: content3
100259
100292
  }];
100260
100293
  if (discardIds.size > 0) {
100261
- const ledger = await readFile84(join101(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
100294
+ const ledger = await readFile84(join102(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
100262
100295
  if (error.code === "ENOENT")
100263
100296
  return;
100264
100297
  throw error;
@@ -100515,7 +100548,7 @@ __export(exports_managedDocumentRename, {
100515
100548
  renameManagedDocument: () => renameManagedDocument
100516
100549
  });
100517
100550
  import { readFile as readFile92 } from "node:fs/promises";
100518
- import { join as join109, posix as posix11 } from "node:path";
100551
+ import { join as join110, posix as posix11 } from "node:path";
100519
100552
  async function optionalText2(path3) {
100520
100553
  try {
100521
100554
  return await readFile92(path3, "utf8");
@@ -100602,7 +100635,7 @@ async function renameManagedDocument(input) {
100602
100635
  if (path3.split("/").includes("..") || path3.startsWith("/"))
100603
100636
  throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
100604
100637
  await safeProjectTarget(input.projectRoot, path3);
100605
- const before = await optionalText2(join109(input.projectRoot, path3));
100638
+ const before = await optionalText2(join110(input.projectRoot, path3));
100606
100639
  if (before === undefined)
100607
100640
  continue;
100608
100641
  let after;
@@ -100691,7 +100724,7 @@ var init_managedDocumentRename = __esm(() => {
100691
100724
 
100692
100725
  // src/cli.ts
100693
100726
  import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
100694
- import { dirname as dirname50, join as join115 } from "node:path";
100727
+ import { dirname as dirname49, join as join116 } from "node:path";
100695
100728
  import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL3 } from "node:url";
100696
100729
 
100697
100730
  // ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
@@ -100746,7 +100779,7 @@ init_dist();
100746
100779
  init_cliFeedback();
100747
100780
  init_errors3();
100748
100781
  init_exitCode();
100749
- import { join as join91 } from "node:path";
100782
+ import { join as join92 } from "node:path";
100750
100783
 
100751
100784
  // src/project/documentCaptureAvailability.ts
100752
100785
  init_atomicFileBatch();
@@ -100755,11 +100788,11 @@ init_documentRun();
100755
100788
  init_writeLock();
100756
100789
  import { createHash as createHash23 } from "node:crypto";
100757
100790
  import { readFile as readFile66, rm as rm19 } from "node:fs/promises";
100758
- import { join as join81 } from "node:path";
100791
+ import { join as join82 } from "node:path";
100759
100792
  import { isDeepStrictEqual } from "node:util";
100760
100793
  function receiptPath(root, phaseId) {
100761
100794
  const key = createHash23("sha256").update(phaseId).digest("hex");
100762
- return join81(root, ".tmp/context-runtime/document-acquisition", `${key}.json`);
100795
+ return join82(root, ".tmp/context-runtime/document-acquisition", `${key}.json`);
100763
100796
  }
100764
100797
  async function identity(root, phase) {
100765
100798
  const resolved = await resolveDocumentPhaseSource({ projectRoot: root, phase });
@@ -100791,7 +100824,7 @@ async function runDocumentCaptureWithAvailability(root, phase, capture2) {
100791
100824
  retry_command: `context run ${phase.id}`,
100792
100825
  message: source2.snapshotReady ? "Document refresh unavailable. Retain the validated registered snapshot; it is not confirmed current upstream." : "Document acquisition unavailable. Keep this source registered as a pending evidence gap; do not cite it or invent content. Unrelated work may continue."
100793
100826
  };
100794
- await applyAtomicFileBatch({ transactionRoot: join81(root, ".tmp/context-runtime/transactions"), writes: [{ path: path2, bytes: `${JSON.stringify({ configuration, warning }, null, 2)}
100827
+ await applyAtomicFileBatch({ transactionRoot: join82(root, ".tmp/context-runtime/transactions"), writes: [{ path: path2, bytes: `${JSON.stringify({ configuration, warning }, null, 2)}
100795
100828
  ` }] });
100796
100829
  return {
100797
100830
  kind: "document.capture.warning",
@@ -100834,7 +100867,7 @@ init_revisionDelivery();
100834
100867
  init_workspacePreparation();
100835
100868
  init_src2();
100836
100869
  init_statusReaders();
100837
- import { join as join85 } from "node:path";
100870
+ import { join as join86 } from "node:path";
100838
100871
 
100839
100872
  // src/project/statusEvidence.ts
100840
100873
  function evidenceWarningState(issues) {
@@ -101274,7 +101307,7 @@ async function collectProjectStatusSnapshotInternal(projectRoot, options = {}) {
101274
101307
  const authoring = production && !production.delivery && (dispatchProductionStage(production, productionCapabilitiesSchema.parse({})).state !== "ended" || draftStatus.count > 0 && draftStatus.diagnostics.length === 0);
101275
101308
  const deferDeliveryChecks = !maintenance && !localRevision && !localUpdate && !localRollback && (taskPreparation === "cleared" && !production || !!authoring);
101276
101309
  const collectionsWithPages = new Set;
101277
- const approvedPages = await countFiles(join85(projectRoot, "knowledge"), (rel) => {
101310
+ const approvedPages = await countFiles(join86(projectRoot, "knowledge"), (rel) => {
101278
101311
  if (!isApprovedKnowledgeMarkdownPath(rel) || rel.startsWith("assets/"))
101279
101312
  return false;
101280
101313
  collectionsWithPages.add(rel.split("/")[0]);
@@ -101282,7 +101315,7 @@ async function collectProjectStatusSnapshotInternal(projectRoot, options = {}) {
101282
101315
  });
101283
101316
  const approvedCollections = KNOWLEDGE_COLLECTIONS.filter((collection) => collectionsWithPages.has(collection));
101284
101317
  const closeStatus = deferDeliveryChecks ? { state: "not-checked", diagnostics: [] } : await readCloseStatus(projectRoot);
101285
- const distFiles = await countFiles(join85(projectRoot, "dist"), () => true);
101318
+ const distFiles = await countFiles(join86(projectRoot, "dist"), () => true);
101286
101319
  const verifyStatus = !deferDeliveryChecks && draftStatus.diagnostics.length === 0 ? await readVerifyStatus(projectRoot) : { issues: [], diagnostics: [] };
101287
101320
  const revisionDocuments = localRevision ? documentSources.filter((source2) => localRevision.target.source_refs.some((ref2) => [source2.name, source2.id].filter(Boolean).some((name3) => ref2 === `${source2.type}:${name3}` || ref2 === `docs:${name3}` || ref2.startsWith(`${source2.type}:${name3}#`) || ref2.startsWith(`${source2.type}:${name3}/`)))) : documentSources;
101288
101321
  const pendingCapture = pendingDocumentCaptureCommands({
@@ -101653,14 +101686,14 @@ function bindWorkflowExecutionContext(result, context) {
101653
101686
  // src/project/workflow/workflowRouteOutput.ts
101654
101687
  init_atomicWrite();
101655
101688
  import { createHash as createHash24 } from "node:crypto";
101656
- import { join as join86 } from "node:path";
101689
+ import { join as join87 } from "node:path";
101657
101690
  async function workflowRouteOutput(projectRoot, route) {
101658
101691
  if (!route)
101659
101692
  return null;
101660
101693
  const body = `${JSON.stringify(route, null, 2)}
101661
101694
  `;
101662
101695
  const digest6 = createHash24("sha256").update(body).digest("hex");
101663
- const file = join86(projectRoot, ".tmp/context-runtime/routes", `${digest6}.json`);
101696
+ const file = join87(projectRoot, ".tmp/context-runtime/routes", `${digest6}.json`);
101664
101697
  await atomicWriteFile(file, body);
101665
101698
  return {
101666
101699
  file,
@@ -101676,7 +101709,7 @@ async function workflowRunResultFile(projectRoot, result) {
101676
101709
  const body = `${JSON.stringify(result, null, 2)}
101677
101710
  `;
101678
101711
  const digest6 = createHash24("sha256").update(body).digest("hex");
101679
- const file = join86(projectRoot, ".tmp/context-runtime/action-results", `${digest6}.run.json`);
101712
+ const file = join87(projectRoot, ".tmp/context-runtime/action-results", `${digest6}.run.json`);
101680
101713
  await atomicWriteFile(file, body);
101681
101714
  return file;
101682
101715
  }
@@ -101820,7 +101853,7 @@ init_candidateLedger();
101820
101853
  init_reviewShared();
101821
101854
  import { mkdir as mkdir31, readFile as readFile71, writeFile as writeFile25 } from "node:fs/promises";
101822
101855
  import { fileURLToPath as fileURLToPath6 } from "node:url";
101823
- import { dirname as dirname38, isAbsolute as isAbsolute15, join as join89, resolve as resolve28 } from "node:path";
101856
+ import { dirname as dirname38, isAbsolute as isAbsolute15, join as join90, resolve as resolve28 } from "node:path";
101824
101857
 
101825
101858
  // src/project/reviewSiteModel.ts
101826
101859
  init_siteTheme2();
@@ -101829,7 +101862,7 @@ init_unified();
101829
101862
  init_remark_parse();
101830
101863
  var import_yaml40 = __toESM(require_dist(), 1);
101831
101864
  import { readFile as readFile70 } from "node:fs/promises";
101832
- import { join as join88 } from "node:path";
101865
+ import { join as join89 } from "node:path";
101833
101866
  import { execFile as execFile10 } from "node:child_process";
101834
101867
  import { promisify as promisify10 } from "node:util";
101835
101868
  import { createHash as createHash25 } from "node:crypto";
@@ -104795,9 +104828,9 @@ init_workspace();
104795
104828
 
104796
104829
  // src/project/reviewFeedback.ts
104797
104830
  import { readdir as readdir20, readFile as readFile69 } from "node:fs/promises";
104798
- import { join as join87 } from "node:path";
104831
+ import { join as join88 } from "node:path";
104799
104832
  async function readPendingReviewFeedback(root2, candidates) {
104800
- const directory = join87(root2, ".tmp/context-runtime/review-feedback");
104833
+ const directory = join88(root2, ".tmp/context-runtime/review-feedback");
104801
104834
  let files;
104802
104835
  try {
104803
104836
  files = await readdir20(directory);
@@ -104810,7 +104843,7 @@ async function readPendingReviewFeedback(root2, candidates) {
104810
104843
  const results = new Map;
104811
104844
  const receipts = [];
104812
104845
  for (const file of files.filter((f) => /^[a-f0-9]+\.json$/u.test(f)).sort()) {
104813
- const receipt2 = JSON.parse(await readFile69(join87(directory, file), "utf8"));
104846
+ const receipt2 = JSON.parse(await readFile69(join88(directory, file), "utf8"));
104814
104847
  receipts.push(receipt2);
104815
104848
  }
104816
104849
  for (const receipt2 of receipts.sort((a, b) => a.created_at.localeCompare(b.created_at))) {
@@ -104930,7 +104963,7 @@ async function optional2(path3) {
104930
104963
  async function reviewSiteBaselineHash(root2, reviewedPaths) {
104931
104964
  const files = await readApprovedMarkdownFiles(root2);
104932
104965
  return hash3(JSON.stringify([
104933
- await optional2(join88(root2, "src/knowledge-map.yaml")) ?? null,
104966
+ await optional2(join89(root2, "src/knowledge-map.yaml")) ?? null,
104934
104967
  files.map((f) => [f.relPath, reviewedPaths.includes(f.relPath) ? hash3(f.content) : title(f.content, f.relPath)]).sort((a, b) => a[0].localeCompare(b[0]))
104935
104968
  ]));
104936
104969
  }
@@ -105043,9 +105076,9 @@ async function collectReviewSiteModel(root2, candidates) {
105043
105076
  for (const [i2, p] of unplaced.entries())
105044
105077
  nodes.push({ key: `review-page-${p.id}`, parent: "review-unplaced", title: p.title, order: i2, page: p.id, change: p.change });
105045
105078
  }
105046
- const pkgText = await optional2(join88(root2, "package.json"));
105079
+ const pkgText = await optional2(join89(root2, "package.json"));
105047
105080
  const pkg = pkgText ? JSON.parse(pkgText) : {};
105048
- const project = await optional2(join88(root2, "src/index.ts")) === undefined ? undefined : await loadContextProjectModule(root2);
105081
+ const project = await optional2(join89(root2, "src/index.ts")) === undefined ? undefined : await loadContextProjectModule(root2);
105049
105082
  const siteTitle = project?.project.packages.flatMap((p) => p.kind === "package.kb" && p.site?.title ? [p.site.title] : [])[0];
105050
105083
  const sitePackages = project?.project.packages.flatMap((p) => p.kind === "package.kb" && p.site ? [p.site] : []) ?? [];
105051
105084
  const themeCss = siteThemeVariables(await resolveSiteTheme(root2, sitePackages.length === 1 ? sitePackages[0]?.theme : undefined));
@@ -105214,7 +105247,7 @@ article.review-new-page .context-diagram-shell,article .changed .context-diagram
105214
105247
  `;
105215
105248
 
105216
105249
  // src/project/reviewHtml.ts
105217
- var REVIEW_HTML_ROOT = join89(".tmp", "context-runtime", "review");
105250
+ var REVIEW_HTML_ROOT = join90(".tmp", "context-runtime", "review");
105218
105251
  async function collectReviewCandidates(projectRoot, collection) {
105219
105252
  const rows = await readCandidateRecords(projectRoot);
105220
105253
  const draftRows = rows.filter((row) => row.collection === collection && row.status === "draft");
@@ -105247,7 +105280,7 @@ ${diagramScript ? `<script>${diagramScript}</script>` : ""}<script>const DATA=${
105247
105280
  }
105248
105281
  function resolveOutputPath(projectRoot, outPath, reviewScope) {
105249
105282
  if (outPath === undefined)
105250
- return join89(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
105283
+ return join90(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
105251
105284
  return isAbsolute15(outPath) ? outPath : resolve28(projectRoot, outPath);
105252
105285
  }
105253
105286
  async function writeReviewHtml(input) {
@@ -105263,7 +105296,7 @@ async function writeReviewHtml(input) {
105263
105296
  if (model.pages.some((page) => page.html.includes('class="language-mermaid"'))) {
105264
105297
  const here = dirname38(fileURLToPath6(import.meta.url));
105265
105298
  try {
105266
- diagramScript = await readFile71(join89(here, "browser/diagrams.js"), "utf8");
105299
+ diagramScript = await readFile71(join90(here, "browser/diagrams.js"), "utf8");
105267
105300
  } catch (error) {
105268
105301
  if (error.code !== "ENOENT")
105269
105302
  throw error;
@@ -105285,7 +105318,7 @@ init_dist();
105285
105318
  init_atomicWrite();
105286
105319
  init_reviewShared();
105287
105320
  import { mkdir as mkdir32, readFile as readFile72 } from "node:fs/promises";
105288
- import { join as join90 } from "node:path";
105321
+ import { join as join91 } from "node:path";
105289
105322
  var REVIEW_BATCH_MAX_CANDIDATES = 6;
105290
105323
  var REVIEW_BATCH_MAX_BYTES = 512 * 1024;
105291
105324
  async function readerPurposes(projectRoot, sources) {
@@ -105365,11 +105398,11 @@ async function materializeCurrentReviewBatchSet(input) {
105365
105398
  const batches = buildCurrentReviewBatchDocuments(input.candidates);
105366
105399
  const setDigest = digestText(batches.map((batch) => `${batch.task_key}:${batch.digest}`).join(`
105367
105400
  `));
105368
- const root2 = join90(input.projectRoot, ".tmp", "context-runtime", "review", `current-${setDigest.slice("sha256:".length)}`);
105401
+ const root2 = join91(input.projectRoot, ".tmp", "context-runtime", "review", `current-${setDigest.slice("sha256:".length)}`);
105369
105402
  await mkdir32(root2, { recursive: true });
105370
105403
  const entries2 = [];
105371
105404
  for (const batch of batches) {
105372
- const path4 = join90(input.projectRoot, ".tmp", "context-runtime", "review", `${batch.task_key}-${batch.digest.slice("sha256:".length)}.md`);
105405
+ const path4 = join91(input.projectRoot, ".tmp", "context-runtime", "review", `${batch.task_key}-${batch.digest.slice("sha256:".length)}.md`);
105373
105406
  const existing = await readFile72(path4, "utf8").catch((error) => {
105374
105407
  if (error.code === "ENOENT")
105375
105408
  return;
@@ -105423,7 +105456,7 @@ async function materializeCurrentReviewBatchSet(input) {
105423
105456
  ].join(`
105424
105457
  `);
105425
105458
  const digest6 = digestText(content3);
105426
- const path3 = join90(root2, "index.md");
105459
+ const path3 = join91(root2, "index.md");
105427
105460
  await atomicWriteFile(path3, `${content3}
105428
105461
  `);
105429
105462
  return {
@@ -105456,11 +105489,11 @@ function shellQuote6(value) {
105456
105489
  }
105457
105490
  function receiptSetPath(receipts) {
105458
105491
  const token = digestText(JSON.stringify(receipts)).slice("sha256:".length);
105459
- return join91(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
105492
+ return join92(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
105460
105493
  }
105461
105494
  async function writeReceiptContinuation(input) {
105462
105495
  const path3 = receiptSetPath(input.receipts);
105463
- const absolutePath = join91(input.projectRoot, path3);
105496
+ const absolutePath = join92(input.projectRoot, path3);
105464
105497
  await writeJsonAtomic(absolutePath, input.receipts);
105465
105498
  const contextCommand = input.managed ? [
105466
105499
  "context",
@@ -105555,7 +105588,7 @@ async function materializeContextWorkflowResource(input) {
105555
105588
  const resourceId = workflowResourceId(input.resourceId);
105556
105589
  const content3 = renderContextWorkflowResource(resourceId, status);
105557
105590
  const location = await materializeResource(await loadContextWorkflowProvider(), resourceId, {
105558
- cache: join91(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
105591
+ cache: join92(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
105559
105592
  workspace: found.projectRoot,
105560
105593
  revision: input.revision,
105561
105594
  input: {
@@ -105587,7 +105620,7 @@ async function materializeContextWorkflowResource(input) {
105587
105620
  receipts: afterReadReceipts
105588
105621
  });
105589
105622
  const directResources = (status.workflow.current?.resources.required ?? []).filter((resource) => resource.read_state === "read-required" && resource.path !== undefined && resource.digest !== undefined);
105590
- const afterReadCommand = directResources.length === 0 ? continuation.command : `context resource acknowledge-current --revision ${shellQuote6(input.revision)}${authorityCommandOptions(authorities, "resource")} --resource-receipts ${shellQuote6(`@${join91(found.projectRoot, continuation.path)}`)} --format json`;
105623
+ const afterReadCommand = directResources.length === 0 ? continuation.command : `context resource acknowledge-current --revision ${shellQuote6(input.revision)}${authorityCommandOptions(authorities, "resource")} --resource-receipts ${shellQuote6(`@${join92(found.projectRoot, continuation.path)}`)} --format json`;
105591
105624
  return {
105592
105625
  protocol: "context.workflow.resource.v1",
105593
105626
  id: resourceId,
@@ -105648,14 +105681,14 @@ async function acknowledgeCurrentWorkflowResources(input) {
105648
105681
  const reevaluated = await reevaluateProjectStatusWorkflow({
105649
105682
  snapshot,
105650
105683
  resourceReceipts: normalizedReceipts,
105651
- resourceReceiptsReference: `@${join91(found.projectRoot, continuation.path)}`
105684
+ resourceReceiptsReference: `@${join92(found.projectRoot, continuation.path)}`
105652
105685
  });
105653
105686
  return {
105654
105687
  ...reevaluated,
105655
105688
  resourceAcknowledgement: {
105656
105689
  protocol: "context.workflow.resource-receipts.v1",
105657
105690
  acknowledged: directResources.length,
105658
- receiptReference: `@${join91(found.projectRoot, continuation.path)}`
105691
+ receiptReference: `@${join92(found.projectRoot, continuation.path)}`
105659
105692
  }
105660
105693
  };
105661
105694
  }
@@ -105702,8 +105735,8 @@ init_errors3();
105702
105735
  init_exitCode();
105703
105736
  init_workspace();
105704
105737
  import { readFile as readFile73 } from "node:fs/promises";
105705
- import { isAbsolute as isAbsolute16, join as join92, sep as sep6, resolve as resolve29 } from "node:path";
105706
- var RECEIPT_DIRECTORY = join92(".tmp", "context-runtime", "workflow", "read-receipts");
105738
+ import { isAbsolute as isAbsolute16, join as join93, sep as sep6, resolve as resolve29 } from "node:path";
105739
+ var RECEIPT_DIRECTORY = join93(".tmp", "context-runtime", "workflow", "read-receipts");
105707
105740
  function workflowResourceReceiptCwd(value, cwd) {
105708
105741
  if (value === undefined || !value.startsWith("@"))
105709
105742
  return cwd;
@@ -105974,14 +106007,14 @@ function compactJsonResult(result, verbose) {
105974
106007
  // src/project/runLog.ts
105975
106008
  import { randomUUID as randomUUID5 } from "node:crypto";
105976
106009
  import { mkdir as mkdir33, writeFile as writeFile26 } from "node:fs/promises";
105977
- import { dirname as dirname39, join as join95 } from "node:path";
106010
+ import { dirname as dirname39, join as join96 } from "node:path";
105978
106011
  var createPhaseRunId = () => {
105979
106012
  const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
105980
106013
  return `run_${timestamp}_${randomUUID5().slice(0, 8)}`;
105981
106014
  };
105982
106015
  async function writePhaseRunLog(input) {
105983
- const relPath = join95(".tmp", "context-runtime", "runs", `${input.runId}.json`);
105984
- const absPath = join95(input.projectRoot, relPath);
106016
+ const relPath = join96(".tmp", "context-runtime", "runs", `${input.runId}.json`);
106017
+ const absPath = join96(input.projectRoot, relPath);
105985
106018
  await mkdir33(dirname39(absPath), { recursive: true });
105986
106019
  await writeFile26(absPath, `${JSON.stringify({
105987
106020
  run_id: input.runId,
@@ -107081,7 +107114,7 @@ init_reviewApplyIndexer();
107081
107114
  init_approvedKnowledgeSnapshots();
107082
107115
  import { existsSync as existsSync25 } from "node:fs";
107083
107116
  import { readFile as readFile76 } from "node:fs/promises";
107084
- import { join as join96 } from "node:path";
107117
+ import { join as join97 } from "node:path";
107085
107118
 
107086
107119
  // src/project/reviewCandidateAuthority.ts
107087
107120
  init_src2();
@@ -107144,7 +107177,7 @@ async function prepareApprovedPage(input) {
107144
107177
  next: "Refresh the current production or article revision, then reopen Review before approval."
107145
107178
  });
107146
107179
  }
107147
- const relPath = join96("knowledge", input.record.path);
107180
+ const relPath = join97("knowledge", input.record.path);
107148
107181
  const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
107149
107182
  const previousPath = input.record.approved_revision?.previous_path;
107150
107183
  if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
@@ -107159,13 +107192,13 @@ async function prepareApprovedPage(input) {
107159
107192
  next: "Resolve the approved page path migration explicitly before approving this candidate."
107160
107193
  });
107161
107194
  }
107162
- const absPath = join96(input.projectRoot, relPath);
107195
+ const absPath = join97(input.projectRoot, relPath);
107163
107196
  const existing = existsSync25(absPath) ? await readFile76(absPath, "utf8") : undefined;
107164
107197
  let previous3;
107165
107198
  if (previousPath !== undefined) {
107166
107199
  if (existing !== undefined || existingView?.relPath !== `knowledge/${previousPath}`)
107167
107200
  throw new TypeError("Page move destination or original identity changed; refresh its revision.");
107168
- previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join96(input.projectRoot, "knowledge", previousPath), "utf8") };
107201
+ previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join97(input.projectRoot, "knowledge", previousPath), "utf8") };
107169
107202
  }
107170
107203
  if (input.record.approved_revision !== undefined) {
107171
107204
  const base = previous3?.content ?? existing;
@@ -107212,7 +107245,7 @@ async function prepareApprovedPage(input) {
107212
107245
  }
107213
107246
  async function readProjectFileMaybe(projectRoot, relPath) {
107214
107247
  try {
107215
- return await readFile76(join96(projectRoot, relPath), "utf8");
107248
+ return await readFile76(join97(projectRoot, relPath), "utf8");
107216
107249
  } catch (error) {
107217
107250
  if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
107218
107251
  return;
@@ -107435,7 +107468,7 @@ async function applyReviewDecisions(input) {
107435
107468
  });
107436
107469
  }
107437
107470
  seenApprovedIds.set(approvedRef, row.candidate_id);
107438
- const approvedPath = join96("knowledge", row.path);
107471
+ const approvedPath = join97("knowledge", row.path);
107439
107472
  const previousPathCandidate = seenApprovedPaths.get(knowledgeTargetPathKey(approvedPath));
107440
107473
  if (previousPathCandidate !== undefined) {
107441
107474
  throw new ContextError(ExitCode.UserError, `multiple approved review decisions target the same knowledge path: ${approvedPath}`, {
@@ -107485,7 +107518,7 @@ async function applyReviewDecisions(input) {
107485
107518
  for (const path3 of approvedPageIndex.byRelPath.keys()) {
107486
107519
  if (pagesToWrite.some((page) => page.relPath === path3 || page.previous?.path === path3))
107487
107520
  continue;
107488
- const before = await readFile76(join96(input.projectRoot, path3), "utf8");
107521
+ const before = await readFile76(join97(input.projectRoot, path3), "utf8");
107489
107522
  const local = path3.replace(/^knowledge\//u, "");
107490
107523
  const after = moveKnowledgeLinkTargets2(before, local, local, moved);
107491
107524
  navigationTargets.push(reviewFileTarget({ path: path3, baseContent: before, targetContent: after }));
@@ -107569,12 +107602,12 @@ init_candidateLedger();
107569
107602
 
107570
107603
  // src/project/localHtmlReport.ts
107571
107604
  import { execFile as execFile11 } from "node:child_process";
107572
- import { isAbsolute as isAbsolute17, join as join97 } from "node:path";
107605
+ import { isAbsolute as isAbsolute17, join as join98 } from "node:path";
107573
107606
  import { pathToFileURL as pathToFileURL2 } from "node:url";
107574
107607
  import { promisify as promisify11 } from "node:util";
107575
107608
  var execFileAsync5 = promisify11(execFile11);
107576
107609
  function htmlReportReference(input) {
107577
- const absolutePath = isAbsolute17(input.path) ? input.path : join97(input.projectRoot, input.path);
107610
+ const absolutePath = isAbsolute17(input.path) ? input.path : join98(input.projectRoot, input.path);
107578
107611
  return {
107579
107612
  format: "html",
107580
107613
  path: input.path,
@@ -108598,7 +108631,7 @@ init_maintenanceStorage();
108598
108631
  init_productionFeedback();
108599
108632
  import { randomUUID as randomUUID6 } from "node:crypto";
108600
108633
  import { readFile as readFile79 } from "node:fs/promises";
108601
- import { join as join98 } from "node:path";
108634
+ import { join as join99 } from "node:path";
108602
108635
  async function beginProductionRevision(input) {
108603
108636
  return withProductionFeedback({ operation: "revision" }, () => withProjectWriteLock(input.projectRoot, "production-revision", async () => {
108604
108637
  await recoverDurableMultiFileTransactions(input.projectRoot);
@@ -108637,7 +108670,7 @@ async function beginProductionRevision(input) {
108637
108670
  const formal = approved.byPath.get(path3);
108638
108671
  if (!prior && !formal)
108639
108672
  throw invalid2("Write the current task first; there is no article draft to revise yet.");
108640
- const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join98("knowledge", path3)), "utf8");
108673
+ const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join99("knowledge", path3)), "utf8");
108641
108674
  const sections = prior?.indexer_candidate.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
108642
108675
  const sources = [];
108643
108676
  for (const source2 of owner.sources) {
@@ -109277,7 +109310,7 @@ init_atomicWrite();
109277
109310
  var import_yaml44 = __toESM(require_dist(), 1);
109278
109311
  import { Buffer as Buffer4 } from "node:buffer";
109279
109312
  import { createHash as createHash31 } from "node:crypto";
109280
- import { join as join102 } from "node:path";
109313
+ import { join as join103 } from "node:path";
109281
109314
  var INLINE_LIMIT = 16 * 1024;
109282
109315
  function record4(value) {
109283
109316
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
@@ -109303,8 +109336,8 @@ async function prepareActionCompletionOutput(input) {
109303
109336
  if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
109304
109337
  return input.result;
109305
109338
  const digest6 = createHash31("sha256").update(full).digest("hex");
109306
- const root2 = join102(input.projectRoot, ".tmp/context-runtime/action-results");
109307
- const resultFile = join102(root2, `${digest6}.json`);
109339
+ const root2 = join103(input.projectRoot, ".tmp/context-runtime/action-results");
109340
+ const resultFile = join103(root2, `${digest6}.json`);
109308
109341
  await atomicWriteFile(resultFile, full);
109309
109342
  if (production)
109310
109343
  return {
@@ -109315,7 +109348,7 @@ async function prepareActionCompletionOutput(input) {
109315
109348
  ...pick(result, ["next", "next_preparation"])
109316
109349
  };
109317
109350
  const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
109318
- const nextFile = next2 === undefined ? undefined : join102(root2, `${digest6}.next.json`);
109351
+ const nextFile = next2 === undefined ? undefined : join103(root2, `${digest6}.next.json`);
109319
109352
  if (nextFile !== undefined)
109320
109353
  await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
109321
109354
  const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
@@ -109722,7 +109755,7 @@ init_cliFeedback();
109722
109755
  import { existsSync as existsSync27 } from "node:fs";
109723
109756
  import { readdir as readdir26, rm as rm21 } from "node:fs/promises";
109724
109757
  import { homedir } from "node:os";
109725
- import { join as join103 } from "node:path";
109758
+ import { join as join104 } from "node:path";
109726
109759
  var ORPHAN_MARKER = ".orphaned_at";
109727
109760
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
109728
109761
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -109739,19 +109772,19 @@ async function cleanClaudePluginCache(opts = {}) {
109739
109772
  for (const mp of marketplaces) {
109740
109773
  if (!mp.isDirectory())
109741
109774
  continue;
109742
- const mpDir = join103(cacheRoot, mp.name);
109775
+ const mpDir = join104(cacheRoot, mp.name);
109743
109776
  const plugins = await readdir26(mpDir, { withFileTypes: true });
109744
109777
  for (const pl of plugins) {
109745
109778
  if (!pl.isDirectory())
109746
109779
  continue;
109747
- const plDir = join103(mpDir, pl.name);
109780
+ const plDir = join104(mpDir, pl.name);
109748
109781
  const versions = await readdir26(plDir, { withFileTypes: true });
109749
109782
  for (const ver of versions) {
109750
109783
  if (!ver.isDirectory())
109751
109784
  continue;
109752
109785
  scanned += 1;
109753
- const verDir = join103(plDir, ver.name);
109754
- const markerPath = join103(verDir, ORPHAN_MARKER);
109786
+ const verDir = join104(plDir, ver.name);
109787
+ const markerPath = join104(verDir, ORPHAN_MARKER);
109755
109788
  if (!existsSync27(markerPath))
109756
109789
  continue;
109757
109790
  const label2 = `${mp.name}/${pl.name}/${ver.name}`;
@@ -109783,7 +109816,7 @@ function resolveClaudePluginCacheRoot(opts) {
109783
109816
  if (explicitRoot)
109784
109817
  return explicitRoot;
109785
109818
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
109786
- return join103(home, ".claude", "plugins", "cache");
109819
+ return join104(home, ".claude", "plugins", "cache");
109787
109820
  }
109788
109821
  async function isEmptyDir(dir) {
109789
109822
  try {
@@ -109815,13 +109848,13 @@ init_exitCode();
109815
109848
 
109816
109849
  // src/lib/packageVersion.ts
109817
109850
  import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
109818
- import { dirname as dirname42, join as join104 } from "node:path";
109851
+ import { dirname as dirname42, join as join105 } from "node:path";
109819
109852
  import { fileURLToPath as fileURLToPath8 } from "node:url";
109820
109853
  function readPackageVersion() {
109821
109854
  try {
109822
109855
  let dir = dirname42(fileURLToPath8(import.meta.url));
109823
109856
  for (let depth = 0;depth < 8; depth += 1) {
109824
- const packagePath = join104(dir, "package.json");
109857
+ const packagePath = join105(dir, "package.json");
109825
109858
  if (existsSync28(packagePath)) {
109826
109859
  const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
109827
109860
  if (typeof parsed.version === "string" && parsed.version.length > 0) {
@@ -110208,14 +110241,14 @@ init_src2();
110208
110241
  init_documentCapture();
110209
110242
  import { existsSync as existsSync30 } from "node:fs";
110210
110243
  import { readFile as readFile86 } from "node:fs/promises";
110211
- import { join as join106 } from "node:path";
110244
+ import { join as join107 } from "node:path";
110212
110245
 
110213
110246
  // src/project/sourceCommandViews.ts
110214
110247
  init_documentSiteDetection();
110215
110248
  init_workspace();
110216
110249
  init_documentBatchManifest();
110217
110250
  import { readFile as readFile85 } from "node:fs/promises";
110218
- import { join as join105 } from "node:path";
110251
+ import { join as join106 } from "node:path";
110219
110252
  function repoSourceAgentView(source2) {
110220
110253
  return {
110221
110254
  id: source2.id ?? source2.name,
@@ -110276,7 +110309,7 @@ async function fileSourceAgentViewWithNextAction(input) {
110276
110309
  };
110277
110310
  }
110278
110311
  function documentSourceManifestPath(source2) {
110279
- return source2.snapshot?.manifest ?? join105(source2.materializedAt, "manifest.json");
110312
+ return source2.snapshot?.manifest ?? join106(source2.materializedAt, "manifest.json");
110280
110313
  }
110281
110314
  async function fileSourceDocumentSiteHint(input) {
110282
110315
  const detection = await detectDocumentSiteFiles({
@@ -110286,7 +110319,7 @@ async function fileSourceDocumentSiteHint(input) {
110286
110319
  let snapshotConfigured = false;
110287
110320
  const manifest = documentSourceManifestPath(input.source);
110288
110321
  try {
110289
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join105(input.projectRoot, manifest), "utf8")), input.source.name);
110322
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join106(input.projectRoot, manifest), "utf8")), input.source.name);
110290
110323
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
110291
110324
  } catch {
110292
110325
  snapshotConfigured = false;
@@ -110319,11 +110352,11 @@ async function larkSourceAgentViewWithNextAction(input) {
110319
110352
  init_documentBatchManifest();
110320
110353
  init_documentSnapshotFidelity();
110321
110354
  function documentSourceManifestPath2(source2) {
110322
- return source2.snapshot?.manifest ?? join106(source2.materializedAt, "manifest.json");
110355
+ return source2.snapshot?.manifest ?? join107(source2.materializedAt, "manifest.json");
110323
110356
  }
110324
110357
  async function documentSnapshotState(input) {
110325
110358
  const manifest = documentSourceManifestPath2(input.source);
110326
- const manifestPath = join106(input.projectRoot, manifest);
110359
+ const manifestPath = join107(input.projectRoot, manifest);
110327
110360
  if (!existsSync30(manifestPath)) {
110328
110361
  return {
110329
110362
  snapshotReady: false,
@@ -110402,7 +110435,7 @@ async function documentSnapshotState(input) {
110402
110435
  const missing = [
110403
110436
  ...parsed.files.map((file) => file.path),
110404
110437
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
110405
- ].find((path3) => !existsSync30(join106(input.projectRoot, input.source.materializedAt, path3)));
110438
+ ].find((path3) => !existsSync30(join107(input.projectRoot, input.source.materializedAt, path3)));
110406
110439
  if (missing !== undefined) {
110407
110440
  return {
110408
110441
  snapshotReady: false,
@@ -110504,7 +110537,7 @@ init_exitCode();
110504
110537
  var import_yaml47 = __toESM(require_dist(), 1);
110505
110538
  import { createHash as createHash32 } from "node:crypto";
110506
110539
  import { readFile as readFile87, realpath as realpath11 } from "node:fs/promises";
110507
- import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join107, relative as relative27, resolve as resolve35 } from "node:path";
110540
+ import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join108, relative as relative27, resolve as resolve35 } from "node:path";
110508
110541
  init_writeLock();
110509
110542
  var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
110510
110543
  function isDateSourceNamespace(value) {
@@ -110600,7 +110633,7 @@ function assertSafeFileInclude(value) {
110600
110633
  }
110601
110634
  async function readRegistryDocument(projectRoot, registryPath2) {
110602
110635
  try {
110603
- const content3 = await readFile87(join107(projectRoot, registryPath2), "utf8");
110636
+ const content3 = await readFile87(join108(projectRoot, registryPath2), "utf8");
110604
110637
  return content3.trim().length === 0 ? { sources: [] } : import_yaml47.default.parse(content3);
110605
110638
  } catch (error) {
110606
110639
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -110718,7 +110751,7 @@ async function addFileSourceUnlocked(input) {
110718
110751
  const record6 = entry2;
110719
110752
  return record6.name !== input.name && record6.id !== input.name;
110720
110753
  }), nextEntry];
110721
- await atomicWriteFile(join107(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110754
+ await atomicWriteFile(join108(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110722
110755
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
110723
110756
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
110724
110757
  if (entry === undefined) {
@@ -110774,7 +110807,7 @@ async function addLarkSourceUnlocked(input) {
110774
110807
  const record6 = entry2;
110775
110808
  return record6.name !== input.name && record6.id !== input.name;
110776
110809
  }), nextEntry];
110777
- await atomicWriteFile(join107(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110810
+ await atomicWriteFile(join108(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
110778
110811
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
110779
110812
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
110780
110813
  if (entry === undefined) {
@@ -110979,7 +111012,7 @@ var import_yaml48 = __toESM(require_dist(), 1);
110979
111012
  import { existsSync as existsSync31 } from "node:fs";
110980
111013
  import { createHash as createHash33 } from "node:crypto";
110981
111014
  import { readFile as readFile88, readdir as readdir27, rm as rm23 } from "node:fs/promises";
110982
- import { isAbsolute as isAbsolute21, join as join108, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
111015
+ import { isAbsolute as isAbsolute21, join as join109, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
110983
111016
  function sourceIdentity(source2) {
110984
111017
  if (source2.kind === "source.collection")
110985
111018
  return;
@@ -111011,7 +111044,7 @@ function collectStrings(value, output) {
111011
111044
  }
111012
111045
  }
111013
111046
  async function yamlReferences(input) {
111014
- const absolutePath = join108(input.projectRoot, input.path);
111047
+ const absolutePath = join109(input.projectRoot, input.path);
111015
111048
  if (!existsSync31(absolutePath))
111016
111049
  return false;
111017
111050
  const parsed = import_yaml48.default.parse(await readFile88(absolutePath, "utf8"));
@@ -111140,7 +111173,7 @@ async function registryRemovalWrite(projectRoot, source2) {
111140
111173
  const path3 = registryPath2(source2.type);
111141
111174
  if (path3 === null)
111142
111175
  return;
111143
- const absolutePath = join108(projectRoot, path3);
111176
+ const absolutePath = join109(projectRoot, path3);
111144
111177
  const document4 = existsSync31(absolutePath) ? import_yaml48.default.parse(await readFile88(absolutePath, "utf8")) : { sources: [] };
111145
111178
  return {
111146
111179
  path: absolutePath,
@@ -111159,7 +111192,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
111159
111192
  return absolute;
111160
111193
  }
111161
111194
  function safeManagedManifestPath(projectRoot, source2) {
111162
- const manifest = source2.manifest ?? join108(source2.materializedAt, "manifest.json");
111195
+ const manifest = source2.manifest ?? join109(source2.materializedAt, "manifest.json");
111163
111196
  if (isAbsolute21(manifest))
111164
111197
  throw unsafeOwnership(source2, manifest);
111165
111198
  const absolute = resolve36(projectRoot, manifest);
@@ -111321,7 +111354,7 @@ function publicRemovalResult(plan, action) {
111321
111354
  };
111322
111355
  }
111323
111356
  async function pruneExtractRuntime(projectRoot, source2) {
111324
- const fingerprintPath = join108(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
111357
+ const fingerprintPath = join109(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
111325
111358
  const removedPhaseIds = new Set;
111326
111359
  if (existsSync31(fingerprintPath)) {
111327
111360
  const parsed = JSON.parse(await readFile88(fingerprintPath, "utf8"));
@@ -111338,14 +111371,14 @@ async function pruneExtractRuntime(projectRoot, source2) {
111338
111371
  await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
111339
111372
  `);
111340
111373
  }
111341
- const phaseOwnershipPath = join108(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
111374
+ const phaseOwnershipPath = join109(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
111342
111375
  if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
111343
111376
  const parsed = JSON.parse(await readFile88(phaseOwnershipPath, "utf8"));
111344
111377
  const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
111345
111378
  await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
111346
111379
  `);
111347
111380
  }
111348
- const symbolPath = join108(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
111381
+ const symbolPath = join109(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
111349
111382
  if (existsSync31(symbolPath)) {
111350
111383
  const parsed = JSON.parse(await readFile88(symbolPath, "utf8"));
111351
111384
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
@@ -111353,12 +111386,12 @@ async function pruneExtractRuntime(projectRoot, source2) {
111353
111386
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
111354
111387
  `);
111355
111388
  }
111356
- const snapshotRoot = join108(projectRoot, ".tmp/context-runtime/extract/candidates");
111389
+ const snapshotRoot = join109(projectRoot, ".tmp/context-runtime/extract/candidates");
111357
111390
  const visit4 = async (directory) => {
111358
111391
  if (!existsSync31(directory))
111359
111392
  return;
111360
111393
  for (const entry of await readdir27(directory, { withFileTypes: true })) {
111361
- const path3 = join108(directory, entry.name);
111394
+ const path3 = join109(directory, entry.name);
111362
111395
  if (entry.isDirectory()) {
111363
111396
  await visit4(path3);
111364
111397
  continue;
@@ -111408,7 +111441,7 @@ async function removeProjectSource(input) {
111408
111441
  });
111409
111442
  }
111410
111443
  await applyAtomicFileBatch({
111411
- transactionRoot: join108(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
111444
+ transactionRoot: join109(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
111412
111445
  writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
111413
111446
  removals: plan.absoluteRemovals
111414
111447
  });
@@ -112051,7 +112084,7 @@ init_exitCode();
112051
112084
  var import_yaml51 = __toESM(require_dist(), 1);
112052
112085
  import { constants as constants6, existsSync as existsSync32 } from "node:fs";
112053
112086
  import { lstat as lstat13, open as open5, readdir as readdir28 } from "node:fs/promises";
112054
- import { dirname as dirname44, join as join110, resolve as resolve38 } from "node:path";
112087
+ import { dirname as dirname44, join as join111, resolve as resolve38 } from "node:path";
112055
112088
  import { fileURLToPath as fileURLToPath9 } from "node:url";
112056
112089
  function bundledSkillRoot() {
112057
112090
  const directory = dirname44(fileURLToPath9(import.meta.url));
@@ -112081,7 +112114,7 @@ async function readProductionSkills(root2) {
112081
112114
  const entries2 = (await readdir28(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
112082
112115
  const skills = [];
112083
112116
  for (const directory of entries2) {
112084
- const entry = join110(root2, directory.name, "SKILL.md");
112117
+ const entry = join111(root2, directory.name, "SKILL.md");
112085
112118
  if (!(await lstat13(entry)).isFile())
112086
112119
  throw new TypeError(`Skill entry must be a regular file: ${entry}`);
112087
112120
  const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
@@ -112490,7 +112523,7 @@ init_errors3();
112490
112523
  init_exitCode();
112491
112524
  import { createHash as createHash34 } from "node:crypto";
112492
112525
  import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as readdir29, rename as rename9, rm as rm24, writeFile as writeFile28 } from "node:fs/promises";
112493
- import { dirname as dirname46, join as join111, resolve as resolve40 } from "node:path";
112526
+ import { dirname as dirname46, join as join112, resolve as resolve40 } from "node:path";
112494
112527
  var MARKER = ".context-skill-install.json";
112495
112528
  function conflict(path3) {
112496
112529
  throw new ContextError(ExitCode.UserError, `Local skill install conflict: ${path3}`, {
@@ -112521,7 +112554,7 @@ async function digest7(root2) {
112521
112554
  for (const name3 of (await readdir29(dir)).sort()) {
112522
112555
  if (!prefix && name3 === MARKER)
112523
112556
  continue;
112524
- const path3 = join111(dir, name3);
112557
+ const path3 = join112(dir, name3);
112525
112558
  const entry = await lstat14(path3);
112526
112559
  if (entry.isSymbolicLink())
112527
112560
  conflict(path3);
@@ -112541,31 +112574,31 @@ async function installLocalSkills(root2, path3, dryRun, agent) {
112541
112574
  if (!path3.trim())
112542
112575
  conflict("--local requires a non-empty path");
112543
112576
  const targetRoot = resolve40(path3);
112544
- const skillsRoot = join111(targetRoot, "skills");
112577
+ const skillsRoot = join112(targetRoot, "skills");
112545
112578
  await checkParents(skillsRoot);
112546
- const sourceRoot2 = join111(root2, "skills");
112579
+ const sourceRoot2 = join112(root2, "skills");
112547
112580
  const commandPlans = [];
112548
112581
  const commandEntries = new Set;
112549
112582
  if (agent === "claude" || agent === "cursor") {
112550
- for (const name3 of await readdir29(join111(root2, "claude", "commands"))) {
112583
+ for (const name3 of await readdir29(join112(root2, "claude", "commands"))) {
112551
112584
  if (name3.endsWith(".md"))
112552
112585
  commandEntries.add(name3.slice(0, -3));
112553
112586
  }
112554
- const commandsRoot = join111(targetRoot, "commands");
112587
+ const commandsRoot = join112(targetRoot, "commands");
112555
112588
  await checkParents(commandsRoot);
112556
- for (const entry of await readdir29(join111(root2, agent, "commands"), { withFileTypes: true })) {
112589
+ for (const entry of await readdir29(join112(root2, agent, "commands"), { withFileTypes: true })) {
112557
112590
  if (!entry.isFile() || !entry.name.endsWith(".md"))
112558
112591
  continue;
112559
- let content3 = await readFile94(join111(root2, agent, "commands", entry.name), "utf8");
112592
+ let content3 = await readFile94(join112(root2, agent, "commands", entry.name), "utf8");
112560
112593
  if (agent === "claude") {
112561
112594
  const frontmatter2 = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
112562
112595
  if (!frontmatter2)
112563
- conflict(join111(root2, agent, "commands", entry.name));
112596
+ conflict(join112(root2, agent, "commands", entry.name));
112564
112597
  content3 = `${frontmatter2[1]}disable-model-invocation: true
112565
112598
  ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmatter2[3]}${content3.slice(frontmatter2[0].length)}`;
112566
112599
  }
112567
- const target = join111(commandsRoot, entry.name);
112568
- const marker = join111(commandsRoot, `.context-${entry.name}.json`);
112600
+ const target = join112(commandsRoot, entry.name);
112601
+ const marker = join112(commandsRoot, `.context-${entry.name}.json`);
112569
112602
  for (const file of [target, marker]) {
112570
112603
  const existing = await stat10(file);
112571
112604
  if (existing && (!existing.isFile() || existing.isSymbolicLink()))
@@ -112586,14 +112619,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112586
112619
  commandPlans.push({ name: entry.name, target, marker, content: content3, hash: createHash34("sha256").update(content3).digest("hex") });
112587
112620
  }
112588
112621
  if (!commandPlans.length)
112589
- conflict(join111(root2, agent, "commands"));
112622
+ conflict(join112(root2, agent, "commands"));
112590
112623
  }
112591
112624
  const plans = [];
112592
112625
  for (const entry of (await readdir29(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
112593
- if (!entry.isDirectory() || !await stat10(join111(sourceRoot2, entry.name, "SKILL.md")))
112626
+ if (!entry.isDirectory() || !await stat10(join112(sourceRoot2, entry.name, "SKILL.md")))
112594
112627
  continue;
112595
- const source2 = join111(sourceRoot2, entry.name);
112596
- const target = join111(skillsRoot, entry.name);
112628
+ const source2 = join112(sourceRoot2, entry.name);
112629
+ const target = join112(skillsRoot, entry.name);
112597
112630
  if (commandEntries.has(entry.name)) {
112598
112631
  if (await stat10(target))
112599
112632
  conflict(`${target} (use a fresh host directory to avoid duplicate command/skill entries)`);
@@ -112603,7 +112636,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112603
112636
  if (existing) {
112604
112637
  if (!existing.isDirectory() || existing.isSymbolicLink())
112605
112638
  conflict(target);
112606
- const markerPath = join111(target, MARKER);
112639
+ const markerPath = join112(target, MARKER);
112607
112640
  if (!(await stat10(markerPath))?.isFile())
112608
112641
  conflict(target);
112609
112642
  let marker;
@@ -112622,14 +112655,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112622
112655
  if (!dryRun) {
112623
112656
  await mkdir36(skillsRoot, { recursive: true });
112624
112657
  for (const plan of plans) {
112625
- const staging = await mkdtemp5(join111(skillsRoot, ".context-install-"));
112626
- const candidate = join111(staging, "candidate");
112627
- const previous3 = join111(staging, "previous");
112658
+ const staging = await mkdtemp5(join112(skillsRoot, ".context-install-"));
112659
+ const candidate = join112(staging, "candidate");
112660
+ const previous3 = join112(staging, "previous");
112628
112661
  let moved = false;
112629
112662
  try {
112630
112663
  await cp2(plan.source, candidate, { recursive: true });
112631
112664
  if (agent === "claude") {
112632
- const skillFile = join111(candidate, "SKILL.md");
112665
+ const skillFile = join112(candidate, "SKILL.md");
112633
112666
  const content3 = await readFile94(skillFile, "utf8");
112634
112667
  const parts = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
112635
112668
  if (parts && /^\s*context-public-entry:\s*["']?false["']?\s*$/mu.test(parts[2])) {
@@ -112638,7 +112671,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
112638
112671
  ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
112639
112672
  }
112640
112673
  }
112641
- await writeFile28(join111(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
112674
+ await writeFile28(join112(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
112642
112675
  `);
112643
112676
  if (plan.exists) {
112644
112677
  await rename9(plan.target, previous3);
@@ -112662,12 +112695,12 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
112662
112695
  }
112663
112696
  for (const command3 of commandPlans) {
112664
112697
  await mkdir36(dirname46(command3.target), { recursive: true });
112665
- const staging = await mkdtemp5(join111(dirname46(command3.target), ".context-install-"));
112666
- await writeFile28(join111(staging, "command"), command3.content);
112667
- await writeFile28(join111(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
112698
+ const staging = await mkdtemp5(join112(dirname46(command3.target), ".context-install-"));
112699
+ await writeFile28(join112(staging, "command"), command3.content);
112700
+ await writeFile28(join112(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
112668
112701
  `);
112669
- await rename9(join111(staging, "command"), command3.target);
112670
- await rename9(join111(staging, "marker"), command3.marker);
112702
+ await rename9(join112(staging, "command"), command3.target);
112703
+ await rename9(join112(staging, "marker"), command3.marker);
112671
112704
  await rm24(staging, { recursive: true, force: true });
112672
112705
  }
112673
112706
  }
@@ -112690,66 +112723,49 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
112690
112723
  init_cliFeedback();
112691
112724
  init_errors3();
112692
112725
  init_exitCode();
112693
- import { access as access6, stat as stat11 } from "node:fs/promises";
112694
- import { constants as constants7 } from "node:fs";
112695
- import { homedir as homedir2 } from "node:os";
112696
- import { basename as basename13, delimiter, dirname as dirname47, join as join112, resolve as resolve41 } from "node:path";
112726
+ import { lstat as lstat15 } from "node:fs/promises";
112727
+ import { join as join113, resolve as resolve41 } from "node:path";
112697
112728
  var HOST_DIRS = { claude: ".claude", cursor: ".cursor", codex: ".agents" };
112698
- async function detectLocalAgent(agent) {
112699
- const commands = agent === "cursor" ? ["cursor", "cursor-agent"] : [agent];
112700
- for (const directory of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
112701
- for (const command3 of commands) {
112702
- for (const suffix of process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""]) {
112703
- const file = join112(directory, command3 + suffix);
112704
- try {
112705
- if (!(await stat11(file)).isFile())
112706
- continue;
112707
- await access6(file, constants7.X_OK);
112708
- return true;
112709
- } catch {}
112710
- }
112711
- }
112712
- }
112713
- if (process.platform === "darwin") {
112714
- const app = { claude: "Claude.app", cursor: "Cursor.app", codex: "Codex.app" }[agent];
112715
- if (agent !== "claude") {
112716
- for (const directory of ["/Applications", join112(homedir2(), "Applications")]) {
112717
- try {
112718
- if ((await stat11(join112(directory, app))).isDirectory())
112719
- return true;
112720
- } catch {}
112721
- }
112729
+ async function detectLocalAgent(agent, repo) {
112730
+ const path3 = join113(repo, HOST_DIRS[agent]);
112731
+ try {
112732
+ const entry = await lstat15(path3);
112733
+ if (!entry.isDirectory() || entry.isSymbolicLink()) {
112734
+ throw new ContextError(ExitCode.UserError, `Local host directory is not a regular directory: ${path3}`);
112722
112735
  }
112736
+ return true;
112737
+ } catch (error) {
112738
+ if (error.code === "ENOENT")
112739
+ return false;
112740
+ throw error;
112723
112741
  }
112724
- return false;
112725
112742
  }
112726
- async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocalAgent) {
112743
+ async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocalAgent, selectedAgent) {
112727
112744
  if (!path3.trim())
112728
112745
  throw new ContextError(ExitCode.UserError, "--local requires a non-empty repository path", {
112729
112746
  category: ErrorCategory.UserInputInvalid,
112730
- next: "Run context plugin install --local /path/to/repository."
112747
+ next: "Run context plugin install --local /path/to/repository --agent auto-detect."
112731
112748
  });
112732
- const requested = resolve41(path3);
112733
- const repo = Object.values(HOST_DIRS).some((name3) => name3 === basename13(requested)) ? dirname47(requested) : requested;
112749
+ const repo = resolve41(path3);
112734
112750
  const agents = [];
112735
112751
  for (const agent of ["claude", "cursor", "codex"]) {
112736
- if (await detect(agent))
112752
+ if (selectedAgent ? selectedAgent === "all" || agent === selectedAgent : await detect(agent, repo))
112737
112753
  agents.push(agent);
112738
112754
  }
112739
- const targets = agents.length ? agents.map((agent) => ({ agent, path: join112(repo, HOST_DIRS[agent]) })) : [{ path: join112(repo, ".agents") }];
112755
+ const targets = agents.length ? agents.map((agent) => ({ agent, path: join113(repo, HOST_DIRS[agent]) })) : [{ path: join113(repo, ".agents") }];
112740
112756
  const previews = [];
112741
112757
  for (const target of targets)
112742
112758
  previews.push(await installLocalSkills(root2, target.path, true, target.agent));
112743
112759
  const header = formatFeedback({
112744
112760
  symbol: agents.length ? "✓" : "⚠",
112745
- action: "detected",
112761
+ action: selectedAgent ? "selected" : "detected",
112746
112762
  subject: "local agent targets",
112747
- headline: agents.length ? agents.join(", ") : "No supported agent detected",
112763
+ headline: agents.length ? agents.join(", ") : "No supported host directory found",
112748
112764
  body: [
112749
112765
  `repository: ${repo}`,
112750
112766
  ...targets.map((target) => `${target.agent ?? "standalone"}: ${target.path}`),
112751
- ...!agents.length ? ["Installing only .agents/skills. Configure a supported host to read this directory, or rerun with an explicit --agent and its target path."] : [],
112752
- "Host discovery does not verify runtime skill loading; refresh the host after installation."
112767
+ ...!agents.length ? ["Installing only .agents/skills. Configure a supported host to read this directory, or select an explicit --agent with the same repository root."] : [],
112768
+ "Repository directory discovery does not verify runtime skill loading; refresh the host after installation."
112753
112769
  ]
112754
112770
  });
112755
112771
  if (dryRun)
@@ -112769,7 +112785,7 @@ init_cliFeedback();
112769
112785
  init_errors3();
112770
112786
  init_exitCode();
112771
112787
  import { existsSync as existsSync35 } from "node:fs";
112772
- import { dirname as dirname49, join as join114, resolve as resolve42 } from "node:path";
112788
+ import { dirname as dirname48, join as join115, resolve as resolve42 } from "node:path";
112773
112789
  import { fileURLToPath as fileURLToPath10 } from "node:url";
112774
112790
 
112775
112791
  // src/project/pluginInstallTargets.ts
@@ -112779,8 +112795,8 @@ init_exitCode();
112779
112795
  import { execFile as execFile13 } from "node:child_process";
112780
112796
  import { existsSync as existsSync34 } from "node:fs";
112781
112797
  import { cp as cp3, mkdir as mkdir37, readdir as readdir30, readFile as readFile95, rename as rename10, rm as rm25, writeFile as writeFile29 } from "node:fs/promises";
112782
- import { homedir as homedir3 } from "node:os";
112783
- import { dirname as dirname48, join as join113 } from "node:path";
112798
+ import { homedir as homedir2 } from "node:os";
112799
+ import { dirname as dirname47, join as join114 } from "node:path";
112784
112800
  import { promisify as promisify13 } from "node:util";
112785
112801
  var execFileAsync7 = promisify13(execFile13);
112786
112802
  var MARKETPLACE_NAME = "c4a";
@@ -112834,23 +112850,23 @@ async function claudePluginInstalled(pluginId) {
112834
112850
  }
112835
112851
  }
112836
112852
  function codexHome() {
112837
- return process.env.CODEX_HOME?.trim() || join113(homedir3(), ".codex");
112853
+ return process.env.CODEX_HOME?.trim() || join114(homedir2(), ".codex");
112838
112854
  }
112839
112855
  function claudePluginCacheRoot() {
112840
112856
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
112841
112857
  if (explicitRoot)
112842
112858
  return explicitRoot;
112843
- const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir3();
112844
- return join113(home, ".claude", "plugins", "cache");
112859
+ const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
112860
+ return join114(home, ".claude", "plugins", "cache");
112845
112861
  }
112846
112862
  function sharedSkillsRoot() {
112847
- return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join113(homedir3(), ".agents", "skills");
112863
+ return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join114(homedir2(), ".agents", "skills");
112848
112864
  }
112849
112865
  function claudeSkillsRoot() {
112850
- return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join113(homedir3(), ".claude", "skills");
112866
+ return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join114(homedir2(), ".claude", "skills");
112851
112867
  }
112852
112868
  function cursorPluginRoot() {
112853
- return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join113(homedir3(), ".cursor", "plugins", "local", PLUGIN_NAME);
112869
+ return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join114(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
112854
112870
  }
112855
112871
  function blockHeader(line) {
112856
112872
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -112901,7 +112917,7 @@ function pruneLegacyCodexConfigContent(content3) {
112901
112917
  `), removed };
112902
112918
  }
112903
112919
  async function pruneLegacyCodexConfig(dryRun, steps) {
112904
- const configPath = join113(codexHome(), "config.toml");
112920
+ const configPath = join114(codexHome(), "config.toml");
112905
112921
  const current2 = await readFile95(configPath, "utf8").catch(() => "");
112906
112922
  if (!current2)
112907
112923
  return;
@@ -112918,7 +112934,7 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
112918
112934
  }
112919
112935
  }
112920
112936
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
112921
- const cacheRoot = join113(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
112937
+ const cacheRoot = join114(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
112922
112938
  if (!existsSync34(cacheRoot))
112923
112939
  return;
112924
112940
  const versions = (await readdir30(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
@@ -112930,7 +112946,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
112930
112946
  status: dryRun ? "planned" : "ran"
112931
112947
  });
112932
112948
  if (!dryRun)
112933
- await Promise.all(versions.map((version3) => rm25(join113(cacheRoot, version3), { recursive: true, force: true })));
112949
+ await Promise.all(versions.map((version3) => rm25(join114(cacheRoot, version3), { recursive: true, force: true })));
112934
112950
  }
112935
112951
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
112936
112952
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -112954,15 +112970,15 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
112954
112970
  for (const marketplace of marketplaces) {
112955
112971
  if (!marketplace.isDirectory())
112956
112972
  continue;
112957
- const pluginDir = join113(cacheRoot, marketplace.name, PLUGIN_NAME);
112973
+ const pluginDir = join114(cacheRoot, marketplace.name, PLUGIN_NAME);
112958
112974
  if (!existsSync34(pluginDir))
112959
112975
  continue;
112960
112976
  const versions = await readdir30(pluginDir, { withFileTypes: true }).catch(() => []);
112961
112977
  for (const version3 of versions) {
112962
112978
  if (!version3.isDirectory())
112963
112979
  continue;
112964
- const versionDir = join113(pluginDir, version3.name);
112965
- if (!existsSync34(join113(versionDir, ORPHAN_MARKER2)))
112980
+ const versionDir = join114(pluginDir, version3.name);
112981
+ if (!existsSync34(join114(versionDir, ORPHAN_MARKER2)))
112966
112982
  continue;
112967
112983
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
112968
112984
  if (!dryRun) {
@@ -112972,7 +112988,7 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
112972
112988
  if (!dryRun && await isEmptyDir2(pluginDir)) {
112973
112989
  await rm25(pluginDir, { recursive: true, force: true });
112974
112990
  }
112975
- const marketplaceDir = join113(cacheRoot, marketplace.name);
112991
+ const marketplaceDir = join114(cacheRoot, marketplace.name);
112976
112992
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
112977
112993
  await rm25(marketplaceDir, { recursive: true, force: true });
112978
112994
  }
@@ -112993,7 +113009,7 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
112993
113009
  return;
112994
113010
  const removed = [];
112995
113011
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
112996
- const pluginDir = join113(cacheRoot, MARKETPLACE_NAME, pluginName);
113012
+ const pluginDir = join114(cacheRoot, MARKETPLACE_NAME, pluginName);
112997
113013
  if (!existsSync34(pluginDir))
112998
113014
  continue;
112999
113015
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
@@ -113010,11 +113026,11 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
113010
113026
  }
113011
113027
  }
113012
113028
  async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
113013
- const manifest = await readFile95(join113(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
113029
+ const manifest = await readFile95(join114(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
113014
113030
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
113015
113031
  if (!currentVersion)
113016
113032
  return;
113017
- const pluginDir = join113(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
113033
+ const pluginDir = join114(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
113018
113034
  const staleVersions = (await readdir30(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
113019
113035
  if (staleVersions.length === 0)
113020
113036
  return;
@@ -113024,7 +113040,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
113024
113040
  status: dryRun ? "planned" : "ran"
113025
113041
  });
113026
113042
  if (!dryRun) {
113027
- await Promise.all(staleVersions.map((version3) => rm25(join113(pluginDir, version3), { recursive: true, force: true })));
113043
+ await Promise.all(staleVersions.map((version3) => rm25(join114(pluginDir, version3), { recursive: true, force: true })));
113028
113044
  }
113029
113045
  }
113030
113046
  function enableCodexPluginConfig(content3) {
@@ -113088,8 +113104,8 @@ source = ${JSON.stringify(root2)}
113088
113104
  `;
113089
113105
  }
113090
113106
  async function ensureCodexPluginEnabled() {
113091
- const configPath = join113(codexHome(), "config.toml");
113092
- await mkdir37(dirname48(configPath), { recursive: true });
113107
+ const configPath = join114(codexHome(), "config.toml");
113108
+ await mkdir37(dirname47(configPath), { recursive: true });
113093
113109
  const current2 = await readFile95(configPath, "utf8").catch(() => "");
113094
113110
  const next2 = enableCodexPluginConfig(current2);
113095
113111
  if (next2 !== current2) {
@@ -113097,8 +113113,8 @@ async function ensureCodexPluginEnabled() {
113097
113113
  }
113098
113114
  }
113099
113115
  async function ensureCodexLocalMarketplace(root2) {
113100
- const configPath = join113(codexHome(), "config.toml");
113101
- await mkdir37(dirname48(configPath), { recursive: true });
113116
+ const configPath = join114(codexHome(), "config.toml");
113117
+ await mkdir37(dirname47(configPath), { recursive: true });
113102
113118
  const current2 = await readFile95(configPath, "utf8").catch(() => "");
113103
113119
  const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
113104
113120
  if (next2 !== current2) {
@@ -113106,7 +113122,7 @@ async function ensureCodexLocalMarketplace(root2) {
113106
113122
  }
113107
113123
  }
113108
113124
  async function codexPluginVersion(root2) {
113109
- const manifestPath = join113(root2, "codex", ".codex-plugin", "plugin.json");
113125
+ const manifestPath = join114(root2, "codex", ".codex-plugin", "plugin.json");
113110
113126
  const manifest = JSON.parse(await readFile95(manifestPath, "utf8"));
113111
113127
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
113112
113128
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
@@ -113114,10 +113130,10 @@ async function codexPluginVersion(root2) {
113114
113130
  return manifest.version;
113115
113131
  }
113116
113132
  function codexPluginCacheDir(version3) {
113117
- return join113(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
113133
+ return join114(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
113118
113134
  }
113119
113135
  async function replaceDirectoryFromSource(source2, target) {
113120
- await mkdir37(dirname48(target), { recursive: true });
113136
+ await mkdir37(dirname47(target), { recursive: true });
113121
113137
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
113122
113138
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
113123
113139
  await rm25(temporary, { recursive: true, force: true });
@@ -113137,7 +113153,7 @@ async function replaceDirectoryFromSource(source2, target) {
113137
113153
  }
113138
113154
  }
113139
113155
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
113140
- const source2 = join113(root2, "codex");
113156
+ const source2 = join114(root2, "codex");
113141
113157
  const target = codexPluginCacheDir(version3);
113142
113158
  steps.push({
113143
113159
  agent: "codex",
@@ -113149,13 +113165,13 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
113149
113165
  await replaceDirectoryFromSource(source2, target);
113150
113166
  }
113151
113167
  async function bundledProviderSkillNames(root2) {
113152
- const skillsRoot = join113(root2, "skills");
113168
+ const skillsRoot = join114(root2, "skills");
113153
113169
  const entries2 = await readdir30(skillsRoot, { withFileTypes: true });
113154
113170
  const names = [];
113155
113171
  for (const entry of entries2) {
113156
113172
  if (!entry.isDirectory() || entry.name === "context")
113157
113173
  continue;
113158
- const skillPath = join113(skillsRoot, entry.name, "SKILL.md");
113174
+ const skillPath = join114(skillsRoot, entry.name, "SKILL.md");
113159
113175
  if (!existsSync34(skillPath))
113160
113176
  continue;
113161
113177
  const skill = await readFile95(skillPath, "utf8");
@@ -113170,10 +113186,10 @@ async function bundledProviderSkillNames(root2) {
113170
113186
  return names;
113171
113187
  }
113172
113188
  async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
113173
- const sourceRoot2 = join113(root2, "skills");
113189
+ const sourceRoot2 = join114(root2, "skills");
113174
113190
  for (const name3 of await bundledProviderSkillNames(root2)) {
113175
- const source2 = join113(sourceRoot2, name3);
113176
- const target = join113(targetRoot, name3);
113191
+ const source2 = join114(sourceRoot2, name3);
113192
+ const target = join114(targetRoot, name3);
113177
113193
  steps.push({
113178
113194
  agent,
113179
113195
  command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
@@ -113184,7 +113200,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
113184
113200
  }
113185
113201
  }
113186
113202
  async function installCursor(root2, dryRun, steps) {
113187
- const source2 = join113(root2, "cursor");
113203
+ const source2 = join114(root2, "cursor");
113188
113204
  const target = cursorPluginRoot();
113189
113205
  steps.push({
113190
113206
  agent: "cursor",
@@ -113239,12 +113255,12 @@ async function installCodex(root2, dryRun, steps) {
113239
113255
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
113240
113256
  steps.push({
113241
113257
  agent: "codex",
113242
- command: `ensure ${shellQuote8(join113(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
113258
+ command: `ensure ${shellQuote8(join114(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
113243
113259
  status: dryRun ? "planned" : "ran"
113244
113260
  });
113245
113261
  steps.push({
113246
113262
  agent: "codex",
113247
- command: `ensure ${shellQuote8(join113(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
113263
+ command: `ensure ${shellQuote8(join114(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
113248
113264
  status: dryRun ? "planned" : "ran"
113249
113265
  });
113250
113266
  if (dryRun) {
@@ -113283,10 +113299,10 @@ function pluginAgentOption(value) {
113283
113299
  }
113284
113300
  function packageCandidateDirs() {
113285
113301
  const dirs = [];
113286
- let dir = dirname49(fileURLToPath10(import.meta.url));
113302
+ let dir = dirname48(fileURLToPath10(import.meta.url));
113287
113303
  for (let index2 = 0;index2 < 8; index2++) {
113288
113304
  dirs.push(dir);
113289
- const parent = dirname49(dir);
113305
+ const parent = dirname48(dir);
113290
113306
  if (parent === dir)
113291
113307
  break;
113292
113308
  dir = parent;
@@ -113299,13 +113315,13 @@ function pluginRootCandidates() {
113299
113315
  return [resolve42(envRoot)];
113300
113316
  const candidates = [];
113301
113317
  for (const dir of packageCandidateDirs()) {
113302
- candidates.push(join114(dir, "plugins"));
113303
- candidates.push(join114(dir, "dist", "plugins"));
113318
+ candidates.push(join115(dir, "plugins"));
113319
+ candidates.push(join115(dir, "dist", "plugins"));
113304
113320
  }
113305
113321
  return [...new Set(candidates)];
113306
113322
  }
113307
113323
  function isInstallablePluginRoot(root2) {
113308
- return existsSync35(join114(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join114(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join114(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join114(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join114(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join114(root2, "skills"));
113324
+ return existsSync35(join115(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join115(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join115(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join115(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join115(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join115(root2, "skills"));
113309
113325
  }
113310
113326
  function resolveBundledPluginsRoot() {
113311
113327
  const candidates = pluginRootCandidates();
@@ -113455,14 +113471,14 @@ function registerPluginCommands(program2) {
113455
113471
  const agent = pluginAgentOption(options.agent);
113456
113472
  process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
113457
113473
  });
113458
- plugin.command("install").description("Install globally by default, or copy standalone skills with --local <path>").option("--agent <agent>", "agent target: claude | codex | cursor | all", "all").option("--local <path>", "Auto-detect hosts under a repository; with --agent, use the exact host directory").option("--dry-run", "Preview installation without writing files or configuration").action(async (options, command3) => {
113474
+ plugin.command("install").description("Install globally by default, or copy standalone skills with --local <path>").option("--agent <agent>", "agent target: claude | codex | cursor | all; local only: auto-detect | standalone", "all").option("--local <path>", "Repository root; install selected or detected hosts into their corresponding subdirectories").option("--dry-run", "Preview installation without writing files or configuration").action(async (options, command3) => {
113459
113475
  if (options.local !== undefined) {
113460
- const agent2 = command3.getOptionValueSource("agent") === "cli" ? pluginAgentOption(options.agent) : undefined;
113461
- if (agent2 === "all") {
113462
- throw new ContextError(ExitCode.UserError, "--local requires one --agent (claude, cursor or codex), or omit --agent for automatic detection.");
113476
+ if (command3.getOptionValueSource("agent") !== "cli") {
113477
+ throw new ContextError(ExitCode.UserError, "--local requires explicit --agent: claude, cursor, codex, all, auto-detect or standalone.");
113463
113478
  }
113479
+ const agent2 = options.agent === "auto-detect" || options.agent === "standalone" ? options.agent : pluginAgentOption(options.agent);
113464
113480
  const { pluginsRoot } = await runPluginPathCommand();
113465
- process.stdout.write(agent2 ? await installLocalSkills(pluginsRoot, String(options.local), options.dryRun === true, agent2) : await installAutoLocalSkills(pluginsRoot, String(options.local), options.dryRun === true));
113481
+ process.stdout.write(agent2 === "standalone" ? await installLocalSkills(pluginsRoot, String(options.local), options.dryRun === true) : await installAutoLocalSkills(pluginsRoot, String(options.local), options.dryRun === true, undefined, agent2 === "auto-detect" ? undefined : agent2));
113466
113482
  return;
113467
113483
  }
113468
113484
  const agent = pluginAgentOption(options.agent);
@@ -113550,21 +113566,21 @@ function inferErrorCategory(message) {
113550
113566
  }
113551
113567
  function readQuickstartPath() {
113552
113568
  try {
113553
- let dir = dirname50(fileURLToPath11(import.meta.url));
113569
+ let dir = dirname49(fileURLToPath11(import.meta.url));
113554
113570
  for (let i2 = 0;i2 < 8; i2++) {
113555
- const candidate = join115(dir, "docs", "quickstart.md");
113571
+ const candidate = join116(dir, "docs", "quickstart.md");
113556
113572
  if (existsSync36(candidate))
113557
113573
  return candidate;
113558
- const pkg = join115(dir, "package.json");
113574
+ const pkg = join116(dir, "package.json");
113559
113575
  if (existsSync36(pkg))
113560
113576
  return candidate;
113561
- const parent = dirname50(dir);
113577
+ const parent = dirname49(dir);
113562
113578
  if (parent === dir)
113563
113579
  break;
113564
113580
  dir = parent;
113565
113581
  }
113566
113582
  } catch {}
113567
- return join115(dirname50(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
113583
+ return join116(dirname49(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
113568
113584
  }
113569
113585
  var GREEN = "\x1B[32m";
113570
113586
  var RESET = "\x1B[0m";