@c4a/context-cli 0.6.5 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -17720,17 +17720,17 @@ var init_writeLock = __esm(() => {
17720
17720
 
17721
17721
  // src/project/packageTemplateReview.ts
17722
17722
  import { createHash as createHash12 } from "node:crypto";
17723
- import { existsSync as existsSync14 } from "node:fs";
17723
+ import { existsSync as existsSync15 } from "node:fs";
17724
17724
  import { mkdir as mkdir13, readFile as readFile20, readdir as readdir8, writeFile as writeFile9 } from "node:fs/promises";
17725
- import { dirname as dirname17, join as join24, relative as relative10, resolve as resolve14 } from "node:path";
17725
+ import { dirname as dirname18, join as join25, relative as relative10, resolve as resolve14 } from "node:path";
17726
17726
  async function templateFiles(root) {
17727
- if (!existsSync14(root))
17727
+ if (!existsSync15(root))
17728
17728
  return [];
17729
17729
  const files = [];
17730
17730
  const visit2 = async (dir) => {
17731
17731
  const entries = await readdir8(dir, { withFileTypes: true });
17732
17732
  for (const entry of entries) {
17733
- const absolutePath = join24(dir, entry.name);
17733
+ const absolutePath = join25(dir, entry.name);
17734
17734
  if (entry.isDirectory()) {
17735
17735
  await visit2(absolutePath);
17736
17736
  continue;
@@ -17757,8 +17757,8 @@ function isMarker(value) {
17757
17757
  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");
17758
17758
  }
17759
17759
  async function readMarker(templateRoot) {
17760
- const markerPath = join24(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17761
- if (!existsSync14(markerPath))
17760
+ const markerPath = join25(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17761
+ if (!existsSync15(markerPath))
17762
17762
  return null;
17763
17763
  try {
17764
17764
  const parsed = JSON.parse(await readFile20(markerPath, "utf8"));
@@ -17768,15 +17768,15 @@ async function readMarker(templateRoot) {
17768
17768
  }
17769
17769
  }
17770
17770
  async function writeStarterTemplateReviewMarker(templateRoot) {
17771
- const markerPath = join24(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17772
- if (existsSync14(markerPath))
17771
+ const markerPath = join25(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17772
+ if (existsSync15(markerPath))
17773
17773
  return false;
17774
17774
  const marker = {
17775
17775
  schema: PACKAGE_TEMPLATE_REVIEW_SCHEMA,
17776
17776
  starter_digest: await templateDigest(templateRoot),
17777
17777
  disposition: "review-required"
17778
17778
  };
17779
- await mkdir13(dirname17(markerPath), { recursive: true });
17779
+ await mkdir13(dirname18(markerPath), { recursive: true });
17780
17780
  await writeFile9(markerPath, `${JSON.stringify(marker, null, 2)}
17781
17781
  `, "utf8");
17782
17782
  return true;
@@ -17796,7 +17796,7 @@ async function inspectPackageTemplateReview(projectRoot, pkg) {
17796
17796
  packageName: pkg.name,
17797
17797
  templatePath: pkg.template.path,
17798
17798
  state: "invalid",
17799
- diagnostic: `${join24(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
17799
+ diagnostic: `${join25(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
17800
17800
  };
17801
17801
  }
17802
17802
  const currentDigest = await templateDigest(templateRoot);
@@ -17837,8 +17837,8 @@ async function acceptStarterPackageTemplates(input) {
17837
17837
  alreadyResolved.push(pkg.name);
17838
17838
  continue;
17839
17839
  }
17840
- const markerPath = join24(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
17841
- const marker = await readMarker(join24(input.projectRoot, pkg.template.path));
17840
+ const markerPath = join25(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
17841
+ const marker = await readMarker(join25(input.projectRoot, pkg.template.path));
17842
17842
  if (marker === null || marker === "invalid") {
17843
17843
  throw new ContextError(ExitCode.WorkspaceStateError, "package template review marker changed before acceptance", {
17844
17844
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -17866,6 +17866,7 @@ var init_packageTemplateReview = __esm(() => {
17866
17866
  // src/project/workspace.ts
17867
17867
  var exports_workspace = {};
17868
17868
  __export(exports_workspace, {
17869
+ resolveContextProjectInitTarget: () => resolveContextProjectInitTarget,
17869
17870
  projectLanguage: () => projectLanguage,
17870
17871
  loadContextProjectModule: () => loadContextProjectModule,
17871
17872
  isContextProjectRoot: () => isContextProjectRoot,
@@ -17876,30 +17877,30 @@ __export(exports_workspace, {
17876
17877
  assertContextStatusWorkspaceAllowed: () => assertContextStatusWorkspaceAllowed,
17877
17878
  PROJECT_LANGUAGES: () => PROJECT_LANGUAGES
17878
17879
  });
17879
- import { existsSync as existsSync15, readFileSync as readFileSync5 } from "node:fs";
17880
+ import { existsSync as existsSync16, readFileSync as readFileSync6 } from "node:fs";
17880
17881
  import { mkdir as mkdir14, readFile as readFile21, readdir as readdir9, writeFile as writeFile10 } from "node:fs/promises";
17881
17882
  import { createRequire as createRequire3 } from "node:module";
17882
- import { basename as basename5, dirname as dirname18, isAbsolute as isAbsolute6, join as join25, parse as parse6, relative as relative11, resolve as resolve15 } from "node:path";
17883
- import { fileURLToPath as fileURLToPath5 } from "node:url";
17883
+ import { basename as basename5, dirname as dirname19, isAbsolute as isAbsolute6, join as join26, parse as parse6, relative as relative11, resolve as resolve15 } from "node:path";
17884
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
17884
17885
  import { createJiti } from "jiti";
17885
- function isRecord12(value) {
17886
+ function isRecord13(value) {
17886
17887
  return value !== null && typeof value === "object" && !Array.isArray(value);
17887
17888
  }
17888
17889
  function readPackageJson(root) {
17889
- const packagePath = join25(root, "package.json");
17890
- if (!existsSync15(packagePath))
17890
+ const packagePath = join26(root, "package.json");
17891
+ if (!existsSync16(packagePath))
17891
17892
  return null;
17892
17893
  try {
17893
- const parsed = JSON.parse(readFileSync5(packagePath, "utf8"));
17894
- return isRecord12(parsed) ? parsed : null;
17894
+ const parsed = JSON.parse(readFileSync6(packagePath, "utf8"));
17895
+ return isRecord13(parsed) ? parsed : null;
17895
17896
  } catch {
17896
17897
  return null;
17897
17898
  }
17898
17899
  }
17899
17900
  function readPackageJsonFile(packageJsonPath) {
17900
17901
  try {
17901
- const parsed = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
17902
- return isRecord12(parsed) ? parsed : null;
17902
+ const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
17903
+ return isRecord13(parsed) ? parsed : null;
17903
17904
  } catch {
17904
17905
  return null;
17905
17906
  }
@@ -17910,22 +17911,22 @@ function resolveExportImportTarget(packageJsonPath) {
17910
17911
  return null;
17911
17912
  const exportsField = parsed.exports;
17912
17913
  if (typeof exportsField === "string") {
17913
- return join25(dirname18(packageJsonPath), exportsField);
17914
+ return join26(dirname19(packageJsonPath), exportsField);
17914
17915
  }
17915
- if (isRecord12(exportsField)) {
17916
+ if (isRecord13(exportsField)) {
17916
17917
  const rootExport = exportsField["."];
17917
17918
  if (typeof rootExport === "string") {
17918
- return join25(dirname18(packageJsonPath), rootExport);
17919
+ return join26(dirname19(packageJsonPath), rootExport);
17919
17920
  }
17920
- if (isRecord12(rootExport) && typeof rootExport.import === "string") {
17921
- return join25(dirname18(packageJsonPath), rootExport.import);
17921
+ if (isRecord13(rootExport) && typeof rootExport.import === "string") {
17922
+ return join26(dirname19(packageJsonPath), rootExport.import);
17922
17923
  }
17923
17924
  }
17924
17925
  if (typeof parsed.module === "string") {
17925
- return join25(dirname18(packageJsonPath), parsed.module);
17926
+ return join26(dirname19(packageJsonPath), parsed.module);
17926
17927
  }
17927
17928
  if (typeof parsed.main === "string") {
17928
- return join25(dirname18(packageJsonPath), parsed.main);
17929
+ return join26(dirname19(packageJsonPath), parsed.main);
17929
17930
  }
17930
17931
  return null;
17931
17932
  }
@@ -17941,16 +17942,16 @@ function resolveContextSdkImportAlias(entryPath) {
17941
17942
  return "@c4a/context";
17942
17943
  }
17943
17944
  function readCurrentPackageVersion() {
17944
- let dir = dirname18(fileURLToPath5(import.meta.url));
17945
+ let dir = dirname19(fileURLToPath6(import.meta.url));
17945
17946
  for (let index2 = 0;index2 < 8; index2++) {
17946
- const packagePath = join25(dir, "package.json");
17947
- if (existsSync15(packagePath)) {
17947
+ const packagePath = join26(dir, "package.json");
17948
+ if (existsSync16(packagePath)) {
17948
17949
  const parsed = readPackageJson(dir);
17949
17950
  if (typeof parsed?.version === "string" && parsed.version.trim().length > 0) {
17950
17951
  return parsed.version;
17951
17952
  }
17952
17953
  }
17953
- const parent = dirname18(dir);
17954
+ const parent = dirname19(dir);
17954
17955
  if (parent === dir)
17955
17956
  break;
17956
17957
  dir = parent;
@@ -17959,7 +17960,7 @@ function readCurrentPackageVersion() {
17959
17960
  }
17960
17961
  function readContextProjectPackage(root) {
17961
17962
  const parsed = readPackageJson(root);
17962
- const context = isRecord12(parsed?.context) ? parsed.context : null;
17963
+ const context = isRecord13(parsed?.context) ? parsed.context : null;
17963
17964
  if (context?.project !== true || typeof context.entry !== "string" || context.entry.trim().length === 0) {
17964
17965
  return null;
17965
17966
  }
@@ -17970,7 +17971,7 @@ function readContextProjectPackage(root) {
17970
17971
  }
17971
17972
  function readContextWorkspaceDir(root) {
17972
17973
  const parsed = readPackageJson(root);
17973
- const context = isRecord12(parsed?.context) ? parsed.context : null;
17974
+ const context = isRecord13(parsed?.context) ? parsed.context : null;
17974
17975
  const workspaceDir = context?.workspaceDir;
17975
17976
  if (typeof workspaceDir !== "string" || workspaceDir.trim().length === 0)
17976
17977
  return null;
@@ -17978,7 +17979,7 @@ function readContextWorkspaceDir(root) {
17978
17979
  }
17979
17980
  function readContextProjectLanguage(root) {
17980
17981
  const parsed = readPackageJson(root);
17981
- const context = isRecord12(parsed?.context) ? parsed.context : null;
17982
+ const context = isRecord13(parsed?.context) ? parsed.context : null;
17982
17983
  return context?.language === "en" || context?.language === "zh-CN" ? context.language : undefined;
17983
17984
  }
17984
17985
  function isSameOrChildPath(path3, parent) {
@@ -17999,13 +18000,13 @@ function findContextWorkspaceExpectation(startDir = process.cwd()) {
17999
18000
  workspaceDir,
18000
18001
  workspaceRoot,
18001
18002
  cwd,
18002
- exists: existsSync15(workspaceRoot)
18003
+ exists: existsSync16(workspaceRoot)
18003
18004
  };
18004
18005
  }
18005
18006
  }
18006
18007
  if (dir === root)
18007
18008
  return null;
18008
- const parent = dirname18(dir);
18009
+ const parent = dirname19(dir);
18009
18010
  if (parent === dir)
18010
18011
  return null;
18011
18012
  dir = parent;
@@ -18039,7 +18040,7 @@ function findContextProjectRoot(startDir = process.cwd()) {
18039
18040
  return { projectRoot: dir };
18040
18041
  if (dir === root)
18041
18042
  return null;
18042
- const parent = dirname18(dir);
18043
+ const parent = dirname19(dir);
18043
18044
  if (parent === dir)
18044
18045
  return null;
18045
18046
  dir = parent;
@@ -18049,6 +18050,9 @@ function normalizeProjectDir(cwd, projectDir) {
18049
18050
  const raw = projectDir?.trim() || DEFAULT_PROJECT_DIR;
18050
18051
  return raw === "." ? resolve15(cwd) : resolve15(cwd, raw);
18051
18052
  }
18053
+ function resolveContextProjectInitTarget(cwd, projectDir) {
18054
+ return normalizeProjectDir(cwd, projectDir);
18055
+ }
18052
18056
  function slugifyName(value) {
18053
18057
  const slug = value.trim().toLowerCase().replace(/[^a-z0-9._-]+/gu, "-").replace(/^-+|-+$/gu, "");
18054
18058
  return slug.length > 0 ? slug : "context";
@@ -18078,7 +18082,7 @@ function initCommand(input, allowNonempty) {
18078
18082
  return args.map(shellQuote3).join(" ");
18079
18083
  }
18080
18084
  async function assertInitTargetAllowed(input, projectRoot) {
18081
- if (!existsSync15(projectRoot) || isContextProjectRoot(projectRoot) || input.allowNonempty === true)
18085
+ if (!existsSync16(projectRoot) || isContextProjectRoot(projectRoot) || input.allowNonempty === true)
18082
18086
  return;
18083
18087
  const entries = (await readdir9(projectRoot)).sort();
18084
18088
  if (entries.length === 0)
@@ -18102,11 +18106,11 @@ async function assertInitTargetAllowed(input, projectRoot) {
18102
18106
  });
18103
18107
  }
18104
18108
  async function writeIfMissing(path3, content3, result) {
18105
- if (existsSync15(path3)) {
18109
+ if (existsSync16(path3)) {
18106
18110
  result.kept.push(path3);
18107
18111
  return;
18108
18112
  }
18109
- await mkdir14(dirname18(path3), { recursive: true });
18113
+ await mkdir14(dirname19(path3), { recursive: true });
18110
18114
  await writeFile10(path3, content3, "utf8");
18111
18115
  result.created.push(path3);
18112
18116
  }
@@ -18114,7 +18118,7 @@ async function listStaticTemplateFiles(root, dir = root) {
18114
18118
  const entries = await readdir9(dir, { withFileTypes: true });
18115
18119
  const files = [];
18116
18120
  for (const entry of entries) {
18117
- const absolutePath = join25(dir, entry.name);
18121
+ const absolutePath = join26(dir, entry.name);
18118
18122
  if (entry.isDirectory()) {
18119
18123
  files.push(...await listStaticTemplateFiles(root, absolutePath));
18120
18124
  continue;
@@ -18131,8 +18135,8 @@ async function listStaticTemplateFiles(root, dir = root) {
18131
18135
  function resolveContextPackageTemplatesRoot() {
18132
18136
  try {
18133
18137
  const packageJsonPath = createRequire3(import.meta.url).resolve("@c4a/context/package.json");
18134
- const templateRoot = join25(dirname18(packageJsonPath), "templates", "package-templates");
18135
- if (existsSync15(templateRoot))
18138
+ const templateRoot = join26(dirname19(packageJsonPath), "templates", "package-templates");
18139
+ if (existsSync16(templateRoot))
18136
18140
  return templateRoot;
18137
18141
  } catch {}
18138
18142
  throw new ContextError(ExitCode.WorkspaceStateError, "missing @c4a/context package templates", {
@@ -18143,8 +18147,8 @@ function resolveContextPackageTemplatesRoot() {
18143
18147
  }
18144
18148
  async function writeDefaultPackageTemplates(projectRoot, result, language) {
18145
18149
  const defaultRoot = resolveContextPackageTemplatesRoot();
18146
- const templateRoot = language === "zh-CN" ? join25(dirname18(defaultRoot), "package-templates.zh-CN") : defaultRoot;
18147
- if (!existsSync15(templateRoot)) {
18150
+ const templateRoot = language === "zh-CN" ? join26(dirname19(defaultRoot), "package-templates.zh-CN") : defaultRoot;
18151
+ if (!existsSync16(templateRoot)) {
18148
18152
  throw new ContextError(ExitCode.WorkspaceStateError, `missing ${language} @c4a/context package templates`, {
18149
18153
  category: ErrorCategory.WorkspaceStateInvalid,
18150
18154
  path: templateRoot,
@@ -18153,21 +18157,21 @@ async function writeDefaultPackageTemplates(projectRoot, result, language) {
18153
18157
  }
18154
18158
  const files = await listStaticTemplateFiles(templateRoot);
18155
18159
  for (const file of files) {
18156
- await writeIfMissing(join25(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile21(file.absolutePath, "utf8"), result);
18160
+ await writeIfMissing(join26(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile21(file.absolutePath, "utf8"), result);
18157
18161
  }
18158
18162
  const templateKinds = [...new Set(files.map((file) => file.relativePath.split("/")[0]).filter((value) => value !== undefined && value.length > 0))];
18159
18163
  for (const templateKind of templateKinds) {
18160
- const root = join25(projectRoot, "src", "package-templates", templateKind);
18164
+ const root = join26(projectRoot, "src", "package-templates", templateKind);
18161
18165
  if (await writeStarterTemplateReviewMarker(root)) {
18162
- result.created.push(join25(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18166
+ result.created.push(join26(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18163
18167
  } else {
18164
- result.kept.push(join25(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18168
+ result.kept.push(join26(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18165
18169
  }
18166
18170
  }
18167
18171
  }
18168
18172
  function resolveLocalSdkDependency() {
18169
18173
  const packageJsonPath = createRequire3(import.meta.url).resolve("@c4a/context/package.json");
18170
- return `file:${dirname18(packageJsonPath)}`;
18174
+ return `file:${dirname19(packageJsonPath)}`;
18171
18175
  }
18172
18176
  function resolveSdkDependency(dev, version3) {
18173
18177
  return dev === true ? resolveLocalSdkDependency() : version3;
@@ -18465,20 +18469,20 @@ async function initContextProject(input) {
18465
18469
  kept: []
18466
18470
  };
18467
18471
  for (const dir of PROJECT_DIRS) {
18468
- await mkdir14(join25(projectRoot, dir), { recursive: true });
18472
+ await mkdir14(join26(projectRoot, dir), { recursive: true });
18469
18473
  }
18470
- await mkdir14(join25(projectRoot, "sources", "repo"), { recursive: true });
18471
- await mkdir14(join25(projectRoot, "sources", "file"), { recursive: true });
18472
- await mkdir14(join25(projectRoot, "sources", "lark"), { recursive: true });
18473
- await writeIfMissing(join25(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
18474
- await writeIfMissing(join25(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
18474
+ await mkdir14(join26(projectRoot, "sources", "repo"), { recursive: true });
18475
+ await mkdir14(join26(projectRoot, "sources", "file"), { recursive: true });
18476
+ await mkdir14(join26(projectRoot, "sources", "lark"), { recursive: true });
18477
+ await writeIfMissing(join26(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
18478
+ await writeIfMissing(join26(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
18475
18479
  await writeDefaultPackageTemplates(projectRoot, result, language);
18476
- await writeIfMissing(join25(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
18477
- await writeIfMissing(join25(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
18478
- await writeIfMissing(join25(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
18479
- await writeIfMissing(join25(projectRoot, ".gitignore"), renderGitignore(), result);
18480
- await writeIfMissing(join25(projectRoot, "README.md"), renderReadme(projectName, language), result);
18481
- await writeIfMissing(join25(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
18480
+ await writeIfMissing(join26(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
18481
+ await writeIfMissing(join26(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
18482
+ await writeIfMissing(join26(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
18483
+ await writeIfMissing(join26(projectRoot, ".gitignore"), renderGitignore(), result);
18484
+ await writeIfMissing(join26(projectRoot, "README.md"), renderReadme(projectName, language), result);
18485
+ await writeIfMissing(join26(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
18482
18486
  if (input.debug === true)
18483
18487
  await enableContextDebug(projectRoot, "init");
18484
18488
  return result;
@@ -18492,7 +18496,7 @@ async function loadContextProjectModule(root) {
18492
18496
  next: "Ensure package.json declares context.project=true and context.entry points to src/index.ts, then rerun the command."
18493
18497
  });
18494
18498
  }
18495
- const entryPath = join25(root, projectConfig.entry);
18499
+ const entryPath = join26(root, projectConfig.entry);
18496
18500
  const jiti = createJiti(entryPath, {
18497
18501
  alias: {
18498
18502
  "@c4a/context": resolveContextSdkImportAlias(entryPath)
@@ -18502,7 +18506,7 @@ async function loadContextProjectModule(root) {
18502
18506
  moduleCache: false
18503
18507
  });
18504
18508
  const loadedProject = await jiti.import(entryPath, { default: true });
18505
- if (!isRecord12(loadedProject) || loadedProject.kind !== "context.project") {
18509
+ if (!isRecord13(loadedProject) || loadedProject.kind !== "context.project") {
18506
18510
  throw new ContextError(ExitCode.WorkspaceStateError, "src/index.ts default export must be a @c4a/context project module", {
18507
18511
  category: ErrorCategory.SchemaInvalid,
18508
18512
  path: projectConfig.entry,
@@ -21518,7 +21522,7 @@ var require_util2 = __commonJS((exports) => {
21518
21522
  return path4;
21519
21523
  }
21520
21524
  exports.normalize = normalize;
21521
- function join46(aRoot, aPath) {
21525
+ function join47(aRoot, aPath) {
21522
21526
  if (aRoot === "") {
21523
21527
  aRoot = ".";
21524
21528
  }
@@ -21550,7 +21554,7 @@ var require_util2 = __commonJS((exports) => {
21550
21554
  }
21551
21555
  return joined;
21552
21556
  }
21553
- exports.join = join46;
21557
+ exports.join = join47;
21554
21558
  exports.isAbsolute = function(aPath) {
21555
21559
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
21556
21560
  };
@@ -21723,7 +21727,7 @@ var require_util2 = __commonJS((exports) => {
21723
21727
  parsed.path = parsed.path.substring(0, index2 + 1);
21724
21728
  }
21725
21729
  }
21726
- sourceURL = join46(urlGenerate(parsed), sourceURL);
21730
+ sourceURL = join47(urlGenerate(parsed), sourceURL);
21727
21731
  }
21728
21732
  return normalize(sourceURL);
21729
21733
  }
@@ -24123,9 +24127,9 @@ var require_lib = __commonJS((exports, module) => {
24123
24127
  });
24124
24128
 
24125
24129
  // src/cli.ts
24126
- import { existsSync as existsSync46, readFileSync as readFileSync9, realpathSync } from "node:fs";
24127
- import { dirname as dirname42, join as join73 } from "node:path";
24128
- import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL4 } from "node:url";
24130
+ import { existsSync as existsSync47, readFileSync as readFileSync10, realpathSync } from "node:fs";
24131
+ import { dirname as dirname43, join as join74 } from "node:path";
24132
+ import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL4 } from "node:url";
24129
24133
 
24130
24134
  // ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
24131
24135
  var import__ = __toESM(require_commander(), 1);
@@ -24189,7 +24193,7 @@ function mergedWorkflowAuthorities(...values) {
24189
24193
  }
24190
24194
 
24191
24195
  // src/project/workflow/workflowResource.ts
24192
- import { join as join55 } from "node:path";
24196
+ import { join as join56 } from "node:path";
24193
24197
 
24194
24198
  // ../../node_modules/.bun/@c4a+agent-graph@0.2.5/node_modules/@c4a/agent-graph/dist/index.js
24195
24199
  import { createRequire as createRequire2 } from "node:module";
@@ -40402,7 +40406,7 @@ init_errors();
40402
40406
  init_exitCode();
40403
40407
 
40404
40408
  // src/project/status.ts
40405
- import { join as join54 } from "node:path";
40409
+ import { join as join55 } from "node:path";
40406
40410
 
40407
40411
  // ../context/src/contracts.ts
40408
40412
  var DEFAULT_PACKAGE_NAVIGATION = {
@@ -45289,9 +45293,9 @@ function resolveStructureCompileRoute(input) {
45289
45293
  // src/project/statusReaders.ts
45290
45294
  init_errors();
45291
45295
  var import_yaml29 = __toESM(require_dist3(), 1);
45292
- import { existsSync as existsSync35, readFileSync as readFileSync7 } from "node:fs";
45296
+ import { existsSync as existsSync36, readFileSync as readFileSync8 } from "node:fs";
45293
45297
  import { readdir as readdir16 } from "node:fs/promises";
45294
- import { join as join52 } from "node:path";
45298
+ import { join as join53 } from "node:path";
45295
45299
 
45296
45300
  // src/project/documentCapture.ts
45297
45301
  import { createHash as createHash4 } from "node:crypto";
@@ -68944,20 +68948,156 @@ async function readApprovedCodegraphPages(input) {
68944
68948
  // src/project/close.ts
68945
68949
  init_cliFeedback();
68946
68950
  init_errors();
68947
- init_exitCode();
68948
68951
  var import_yaml14 = __toESM(require_dist3(), 1);
68949
- import { existsSync as existsSync21 } from "node:fs";
68952
+ import { existsSync as existsSync22 } from "node:fs";
68950
68953
  import { mkdir as mkdir17, readdir as readdir11, readFile as readFile27, writeFile as writeFile13 } from "node:fs/promises";
68951
- import { dirname as dirname21, join as join32, relative as relative13 } from "node:path";
68954
+ import { dirname as dirname22, join as join33, relative as relative13 } from "node:path";
68955
+
68956
+ // src/runtimeEvents.ts
68957
+ import { randomUUID as randomUUID2 } from "node:crypto";
68958
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
68959
+ import { spawn as spawn2 } from "node:child_process";
68960
+ import { dirname as dirname15, join as join17 } from "node:path";
68961
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
68962
+ var CONTEXT_RUNTIME_EVENT_BATCH_SCHEMA = "context.runtime-event-batch.v1";
68963
+ var CONTEXT_RUNTIME_EVENT_SINK_SCHEMA = "context.runtime-event-sink.v1";
68964
+ var activeScope;
68965
+ function isRecord8(value) {
68966
+ return value !== null && typeof value === "object" && !Array.isArray(value);
68967
+ }
68968
+ function parseContextRuntimeEventSink(value) {
68969
+ if (!isRecord8(value))
68970
+ return null;
68971
+ if (value.schema !== CONTEXT_RUNTIME_EVENT_SINK_SCHEMA || value.transport !== "command")
68972
+ return null;
68973
+ if (typeof value.command !== "string" || value.command.trim().length === 0)
68974
+ return null;
68975
+ if (!Array.isArray(value.args) || !value.args.every((arg) => typeof arg === "string"))
68976
+ return null;
68977
+ return {
68978
+ schema: CONTEXT_RUNTIME_EVENT_SINK_SCHEMA,
68979
+ transport: "command",
68980
+ command: value.command,
68981
+ args: [...value.args]
68982
+ };
68983
+ }
68984
+ function readRuntimePackageMetadata() {
68985
+ try {
68986
+ let dir = dirname15(fileURLToPath4(import.meta.url));
68987
+ for (let index2 = 0;index2 < 8; index2++) {
68988
+ const packagePath = join17(dir, "package.json");
68989
+ if (existsSync8(packagePath)) {
68990
+ const parsed = JSON.parse(readFileSync4(packagePath, "utf8"));
68991
+ if (isRecord8(parsed)) {
68992
+ return {
68993
+ contextVersion: typeof parsed.version === "string" ? parsed.version : "unknown",
68994
+ sink: parseContextRuntimeEventSink(parsed.contextRuntimeEventSink)
68995
+ };
68996
+ }
68997
+ }
68998
+ const parent = dirname15(dir);
68999
+ if (parent === dir)
69000
+ break;
69001
+ dir = parent;
69002
+ }
69003
+ } catch {}
69004
+ return { contextVersion: "unknown", sink: null };
69005
+ }
69006
+ function dispatchCommand(sink, batch, cwd) {
69007
+ return new Promise((resolve8) => {
69008
+ let settled = false;
69009
+ let timer;
69010
+ const finish = () => {
69011
+ if (settled)
69012
+ return;
69013
+ settled = true;
69014
+ if (timer !== undefined)
69015
+ clearTimeout(timer);
69016
+ resolve8();
69017
+ };
69018
+ try {
69019
+ const child = spawn2(sink.command, sink.args, {
69020
+ cwd,
69021
+ detached: true,
69022
+ env: process.env,
69023
+ shell: false,
69024
+ stdio: ["pipe", "ignore", "ignore"]
69025
+ });
69026
+ child.once("error", finish);
69027
+ child.stdin.once("error", finish);
69028
+ child.stdin.end(JSON.stringify(batch), finish);
69029
+ child.unref();
69030
+ timer = setTimeout(finish, 250);
69031
+ timer.unref();
69032
+ } catch {
69033
+ finish();
69034
+ }
69035
+ });
69036
+ }
69037
+ async function flushRuntimeEvents(scope) {
69038
+ const grouped = new Map;
69039
+ for (const queued of scope.events) {
69040
+ const events = grouped.get(queued.cwd) ?? [];
69041
+ events.push(queued.event);
69042
+ grouped.set(queued.cwd, events);
69043
+ }
69044
+ await Promise.all([...grouped.entries()].map(async ([cwd, events]) => {
69045
+ try {
69046
+ await scope.dispatch(scope.sink, {
69047
+ schema: CONTEXT_RUNTIME_EVENT_BATCH_SCHEMA,
69048
+ context_version: scope.contextVersion,
69049
+ events
69050
+ }, cwd);
69051
+ } catch {}
69052
+ }));
69053
+ }
69054
+ function queueContextRuntimeEvent(input) {
69055
+ if (activeScope === undefined)
69056
+ return;
69057
+ activeScope.events.push({
69058
+ cwd: input.cwd,
69059
+ event: {
69060
+ event_id: randomUUID2(),
69061
+ event_time: Date.now(),
69062
+ kind: input.kind,
69063
+ properties: input.properties ?? {}
69064
+ }
69065
+ });
69066
+ }
69067
+ async function withContextRuntimeEventDelivery(work, options = {}) {
69068
+ if (activeScope !== undefined || process.env.CONTEXT_RUNTIME_EVENTS_DISABLED === "1") {
69069
+ return work();
69070
+ }
69071
+ const metadata = readRuntimePackageMetadata();
69072
+ const sink = options.sink === undefined ? metadata.sink : options.sink;
69073
+ if (sink === null)
69074
+ return work();
69075
+ const scope = {
69076
+ contextVersion: options.contextVersion ?? metadata.contextVersion,
69077
+ dispatch: options.dispatch ?? dispatchCommand,
69078
+ events: [],
69079
+ sink
69080
+ };
69081
+ activeScope = scope;
69082
+ try {
69083
+ return await work();
69084
+ } finally {
69085
+ activeScope = undefined;
69086
+ await flushRuntimeEvents(scope);
69087
+ }
69088
+ }
69089
+
69090
+ // src/project/close.ts
69091
+ init_exitCode();
68952
69092
 
68953
69093
  // src/project/approvedStructureEdges.ts
68954
69094
  init_cliFeedback();
68955
69095
  init_errors();
68956
69096
  init_exitCode();
68957
69097
  var import_yaml10 = __toESM(require_dist3(), 1);
68958
- import { existsSync as existsSync10 } from "node:fs";
69098
+ import { existsSync as existsSync11 } from "node:fs";
68959
69099
  import { readFile as readFile17 } from "node:fs/promises";
68960
- import { join as join19 } from "node:path";
69100
+ import { join as join20 } from "node:path";
68961
69101
 
68962
69102
  // src/project/proseAlignTypes.ts
68963
69103
  import { createHash as createHash9 } from "node:crypto";
@@ -69014,21 +69154,21 @@ function slugify2(input, maxLen = 60) {
69014
69154
  // src/project/semanticRules.ts
69015
69155
  var import_yaml8 = __toESM(require_dist3(), 1);
69016
69156
  import { createHash as createHash8 } from "node:crypto";
69017
- import { existsSync as existsSync8, readFileSync as readFileSync4, readdirSync } from "node:fs";
69018
- import { basename as basename4, dirname as dirname15, join as join17 } from "node:path";
69019
- import { fileURLToPath as fileURLToPath4 } from "node:url";
69157
+ import { existsSync as existsSync9, readFileSync as readFileSync5, readdirSync } from "node:fs";
69158
+ import { basename as basename4, dirname as dirname16, join as join18 } from "node:path";
69159
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
69020
69160
  function sha256(value) {
69021
69161
  return `sha256:${createHash8("sha256").update(value).digest("hex")}`;
69022
69162
  }
69023
69163
  function workflowRootCandidates() {
69024
- const runtimeDir = dirname15(fileURLToPath4(import.meta.url));
69164
+ const runtimeDir = dirname16(fileURLToPath5(import.meta.url));
69025
69165
  return [
69026
- join17(runtimeDir, "providers", "context"),
69027
- join17(runtimeDir, "..", "..", "context-workflow")
69166
+ join18(runtimeDir, "providers", "context"),
69167
+ join18(runtimeDir, "..", "..", "context-workflow")
69028
69168
  ];
69029
69169
  }
69030
69170
  function semanticRuleMetadata(scope, filePath) {
69031
- const content3 = readFileSync4(filePath, "utf8").replaceAll(`\r
69171
+ const content3 = readFileSync5(filePath, "utf8").replaceAll(`\r
69032
69172
  `, `
69033
69173
  `);
69034
69174
  const end = content3.indexOf(`
@@ -69059,19 +69199,19 @@ function semanticRuleMetadata(scope, filePath) {
69059
69199
  }
69060
69200
  function semanticRuleDescriptors(scope) {
69061
69201
  for (const root of workflowRootCandidates()) {
69062
- const directory = join17(root, "resources", "semantic", scope);
69063
- if (!existsSync8(directory))
69202
+ const directory = join18(root, "resources", "semantic", scope);
69203
+ if (!existsSync9(directory))
69064
69204
  continue;
69065
- return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).sort((left, right) => left.name.localeCompare(right.name)).map((entry) => semanticRuleMetadata(scope, join17(directory, entry.name)));
69205
+ return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).sort((left, right) => left.name.localeCompare(right.name)).map((entry) => semanticRuleMetadata(scope, join18(directory, entry.name)));
69066
69206
  }
69067
69207
  throw new Error(`Context ${scope} semantic workflow resources are missing. Rebuild or reinstall @c4a/context-cli.`);
69068
69208
  }
69069
69209
  function ruleContent(rulePath) {
69070
69210
  for (const root of workflowRootCandidates()) {
69071
- const absolute = join17(root, rulePath);
69072
- if (existsSync8(absolute)) {
69211
+ const absolute = join18(root, rulePath);
69212
+ if (existsSync9(absolute)) {
69073
69213
  return {
69074
- content: readFileSync4(absolute, "utf8"),
69214
+ content: readFileSync5(absolute, "utf8"),
69075
69215
  available: true,
69076
69216
  filePath: absolute
69077
69217
  };
@@ -69484,15 +69624,15 @@ init_cliFeedback();
69484
69624
  init_errors();
69485
69625
  init_exitCode();
69486
69626
  var import_yaml9 = __toESM(require_dist3(), 1);
69487
- import { existsSync as existsSync9 } from "node:fs";
69627
+ import { existsSync as existsSync10 } from "node:fs";
69488
69628
  import { mkdir as mkdir12, readFile as readFile16, writeFile as writeFile8 } from "node:fs/promises";
69489
- import { dirname as dirname16, join as join18 } from "node:path";
69629
+ import { dirname as dirname17, join as join19 } from "node:path";
69490
69630
 
69491
69631
  // src/project/proseAlignPayloadParse.ts
69492
69632
  import { createHash as createHash10 } from "node:crypto";
69493
69633
 
69494
69634
  // src/project/proseAlignSchemaUtils.ts
69495
- function isRecord8(value) {
69635
+ function isRecord9(value) {
69496
69636
  return value !== null && typeof value === "object" && !Array.isArray(value);
69497
69637
  }
69498
69638
  function stringValue2(record, field) {
@@ -69559,7 +69699,7 @@ function parsePreferredNodes(value, diagnostics) {
69559
69699
  }
69560
69700
  const nodes = [];
69561
69701
  for (const [index2, rawNode] of value.entries()) {
69562
- if (!isRecord8(rawNode)) {
69702
+ if (!isRecord9(rawNode)) {
69563
69703
  diagnostics.push(diagnostic("error", "schema.preferred_node_object", "schema", "preferred_nodes item must be an object.", `user_or_agent_hints.preferred_nodes[${index2}]`));
69564
69704
  continue;
69565
69705
  }
@@ -69584,7 +69724,7 @@ function parsePreferredNodes(value, diagnostics) {
69584
69724
  function parseUserOrAgentHints(value, diagnostics) {
69585
69725
  if (value === undefined)
69586
69726
  return;
69587
- if (!isRecord8(value)) {
69727
+ if (!isRecord9(value)) {
69588
69728
  diagnostics.push(diagnostic("error", "schema.user_or_agent_hints_object", "schema", "user_or_agent_hints must be an object.", "user_or_agent_hints"));
69589
69729
  return;
69590
69730
  }
@@ -69787,7 +69927,7 @@ function parseNodes(value, diagnostics) {
69787
69927
  diagnostics.push(diagnostic("error", "schema.nodes_missing", "schema", "Payload must include at least one node.", "nodes"));
69788
69928
  const nodes = [];
69789
69929
  for (const [index2, rawNode] of value.entries()) {
69790
- if (!isRecord8(rawNode)) {
69930
+ if (!isRecord9(rawNode)) {
69791
69931
  diagnostics.push(diagnostic("error", "schema.node_object", "schema", `Node ${index2 + 1} must be an object.`, `nodes[${index2}]`));
69792
69932
  continue;
69793
69933
  }
@@ -69824,7 +69964,7 @@ function parseSections(input) {
69824
69964
  const sectionIds = new Set;
69825
69965
  for (const [sectionIndex, rawSection] of input.value.entries()) {
69826
69966
  const field = `views[${input.viewIndex}].sections[${sectionIndex}]`;
69827
- if (!isRecord8(rawSection)) {
69967
+ if (!isRecord9(rawSection)) {
69828
69968
  input.diagnostics.push(diagnostic("error", "schema.section_object", "schema", "Section must be an object.", field));
69829
69969
  continue;
69830
69970
  }
@@ -69926,7 +70066,7 @@ function parseViews(value, nodes, diagnostics) {
69926
70066
  const nodeByRef = new Map(nodes.map((node3) => [node3.node_ref, node3]));
69927
70067
  const views = [];
69928
70068
  for (const [index2, rawView] of value.entries()) {
69929
- if (!isRecord8(rawView)) {
70069
+ if (!isRecord9(rawView)) {
69930
70070
  diagnostics.push(diagnostic("error", "schema.view_object", "schema", `View ${index2 + 1} must be an object.`, `views[${index2}]`));
69931
70071
  continue;
69932
70072
  }
@@ -69945,7 +70085,7 @@ function parseEdges(value, diagnostics) {
69945
70085
  }
69946
70086
  const edges = [];
69947
70087
  for (const [index2, rawEdge] of value.entries()) {
69948
- if (!isRecord8(rawEdge)) {
70088
+ if (!isRecord9(rawEdge)) {
69949
70089
  diagnostics.push(diagnostic("error", "schema.edge_object", "schema", `Edge ${index2 + 1} must be an object.`, `edges[${index2}]`));
69950
70090
  continue;
69951
70091
  }
@@ -69992,7 +70132,7 @@ function parseUnresolved(value, diagnostics) {
69992
70132
  }
69993
70133
  const unresolved = [];
69994
70134
  for (const [index2, rawIssue] of value.entries()) {
69995
- if (!isRecord8(rawIssue)) {
70135
+ if (!isRecord9(rawIssue)) {
69996
70136
  diagnostics.push(diagnostic("error", "schema.unresolved_object", "schema", `Unresolved issue ${index2 + 1} must be an object.`, `unresolved[${index2}]`));
69997
70137
  continue;
69998
70138
  }
@@ -70015,7 +70155,7 @@ function parseUnresolved(value, diagnostics) {
70015
70155
  function parseLifecycle(value, diagnostics) {
70016
70156
  if (value === undefined)
70017
70157
  return { state: "draft" };
70018
- if (!isRecord8(value)) {
70158
+ if (!isRecord9(value)) {
70019
70159
  diagnostics.push(diagnostic("error", "schema.lifecycle_object", "schema", "Payload lifecycle must be an object.", "lifecycle"));
70020
70160
  return { state: "draft" };
70021
70161
  }
@@ -70073,7 +70213,7 @@ function structureBody(input) {
70073
70213
  }
70074
70214
  function parseAlignPayload(value) {
70075
70215
  const diagnostics = [];
70076
- if (!isRecord8(value)) {
70216
+ if (!isRecord9(value)) {
70077
70217
  return {
70078
70218
  diagnostics: [diagnostic("error", "schema.payload_object", "schema", "Payload must be a YAML/JSON object.", "schema")]
70079
70219
  };
@@ -70158,7 +70298,7 @@ function snapshotPath(projectRoot, structureDigest) {
70158
70298
  structure_digest: structureDigest
70159
70299
  });
70160
70300
  }
70161
- return join18(projectRoot, STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70301
+ return join19(projectRoot, STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70162
70302
  }
70163
70303
  function normalizedSnapshot(payload) {
70164
70304
  const { user_or_agent_hints: _hints, ...body } = payload;
@@ -70174,8 +70314,8 @@ function normalizedSnapshot(payload) {
70174
70314
  });
70175
70315
  }
70176
70316
  async function readSlots(projectRoot) {
70177
- const path3 = join18(projectRoot, STRUCTURE_SLOT_FILE);
70178
- if (!existsSync9(path3))
70317
+ const path3 = join19(projectRoot, STRUCTURE_SLOT_FILE);
70318
+ if (!existsSync10(path3))
70179
70319
  return [];
70180
70320
  const parsed = import_yaml9.default.parse(await readFile16(path3, "utf8"));
70181
70321
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -70223,8 +70363,8 @@ async function updateSlots(projectRoot, payload) {
70223
70363
  ...current2.filter((slot) => !replacements.has(`${slot.source}\x00${slot.collection}`)),
70224
70364
  ...replacements.values()
70225
70365
  ].sort((left, right) => left.source.localeCompare(right.source) || left.collection.localeCompare(right.collection));
70226
- const path3 = join18(projectRoot, STRUCTURE_SLOT_FILE);
70227
- await mkdir12(dirname16(path3), { recursive: true });
70366
+ const path3 = join19(projectRoot, STRUCTURE_SLOT_FILE);
70367
+ await mkdir12(dirname17(path3), { recursive: true });
70228
70368
  await writeFile8(path3, import_yaml9.default.stringify({ schema_version: STRUCTURE_SLOT_SCHEMA_VERSION, slots }), "utf8");
70229
70369
  }
70230
70370
  async function writeStructureSnapshot(projectRoot, payload) {
@@ -70239,7 +70379,7 @@ async function writeStructureSnapshot(projectRoot, payload) {
70239
70379
  });
70240
70380
  }
70241
70381
  const content3 = import_yaml9.default.stringify(normalized);
70242
- if (existsSync9(path3)) {
70382
+ if (existsSync10(path3)) {
70243
70383
  const current2 = await readFile16(path3, "utf8");
70244
70384
  const existing = parseAlignPayload(import_yaml9.default.parse(current2)).payload;
70245
70385
  if (existing?.structure_digest !== payload.structure_digest) {
@@ -70255,14 +70395,14 @@ async function writeStructureSnapshot(projectRoot, payload) {
70255
70395
  await updateSlots(projectRoot, payload);
70256
70396
  return path3;
70257
70397
  }
70258
- await mkdir12(dirname16(path3), { recursive: true });
70398
+ await mkdir12(dirname17(path3), { recursive: true });
70259
70399
  await writeFile8(path3, content3, "utf8");
70260
70400
  await updateSlots(projectRoot, payload);
70261
70401
  return path3;
70262
70402
  }
70263
70403
  async function readStructureSnapshot(projectRoot, structureDigest) {
70264
70404
  const path3 = snapshotPath(projectRoot, structureDigest);
70265
- if (!existsSync9(path3))
70405
+ if (!existsSync10(path3))
70266
70406
  return null;
70267
70407
  try {
70268
70408
  return import_yaml9.default.parse(await readFile16(path3, "utf8"));
@@ -70290,8 +70430,8 @@ async function readStructureSnapshotPayload(projectRoot, structureDigest) {
70290
70430
  return { ...record, structure_digest: structureDigest };
70291
70431
  }
70292
70432
  async function archiveActiveStructure(projectRoot) {
70293
- const path3 = join18(projectRoot, LIFECYCLE_STRUCTURE_FILE);
70294
- if (!existsSync9(path3))
70433
+ const path3 = join19(projectRoot, LIFECYCLE_STRUCTURE_FILE);
70434
+ if (!existsSync10(path3))
70295
70435
  return null;
70296
70436
  let parsed;
70297
70437
  try {
@@ -70319,7 +70459,7 @@ function structureSnapshotRelativePath(structureDigest) {
70319
70459
  const match = STRUCTURE_DIGEST_PATTERN.exec(structureDigest);
70320
70460
  if (match?.[1] === undefined)
70321
70461
  return STRUCTURE_SNAPSHOT_ROOT;
70322
- return join18(STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70462
+ return join19(STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70323
70463
  }
70324
70464
  async function currentStructureSlotDigest(projectRoot, source2, collection) {
70325
70465
  return (await readSlots(projectRoot)).find((slot) => slot.source === source2 && slot.collection === collection)?.structure_digest;
@@ -70334,9 +70474,9 @@ async function activeStructureSlots(projectRoot, collection) {
70334
70474
 
70335
70475
  // src/project/approvedStructureEdges.ts
70336
70476
  var KNOWLEDGE_ROOT = "knowledge";
70337
- var APPROVED_STRUCTURE_PATH = join19(KNOWLEDGE_ROOT, "structure.yaml");
70477
+ var APPROVED_STRUCTURE_PATH = join20(KNOWLEDGE_ROOT, "structure.yaml");
70338
70478
  var STRUCTURE_EDGE_CONFIDENCE_SET = new Set(STRUCTURE_EDGE_CONFIDENCES);
70339
- function isRecord9(value) {
70479
+ function isRecord10(value) {
70340
70480
  return value !== null && typeof value === "object" && !Array.isArray(value);
70341
70481
  }
70342
70482
  function readEdgeArray(structure) {
@@ -70346,7 +70486,7 @@ function normalizeApprovedEdges(input) {
70346
70486
  const allowed = new Set(STRUCTURE_EDGE_TYPES);
70347
70487
  const edges = [];
70348
70488
  for (const [index2, rawEdge] of input.rawEdges.entries()) {
70349
- if (!isRecord9(rawEdge)) {
70489
+ if (!isRecord10(rawEdge)) {
70350
70490
  throw new ContextError(ExitCode.WorkspaceStateError, "structure edge must be an object", {
70351
70491
  category: ErrorCategory.WorkspaceStateInvalid,
70352
70492
  path: input.path,
@@ -70437,20 +70577,20 @@ function structureEndpointRefs(structure) {
70437
70577
  const refs = [];
70438
70578
  if (Array.isArray(structure.nodes)) {
70439
70579
  for (const node3 of structure.nodes) {
70440
- if (isRecord9(node3) && typeof node3.node_ref === "string")
70580
+ if (isRecord10(node3) && typeof node3.node_ref === "string")
70441
70581
  refs.push(node3.node_ref);
70442
70582
  }
70443
70583
  }
70444
70584
  if (Array.isArray(structure.views)) {
70445
70585
  for (const view of structure.views) {
70446
- if (!isRecord9(view))
70586
+ if (!isRecord10(view))
70447
70587
  continue;
70448
70588
  if (typeof view.view_ref === "string")
70449
70589
  refs.push(view.view_ref);
70450
70590
  if (!Array.isArray(view.sections))
70451
70591
  continue;
70452
70592
  for (const section of view.sections) {
70453
- if (isRecord9(section) && typeof section.section_ref === "string")
70593
+ if (isRecord10(section) && typeof section.section_ref === "string")
70454
70594
  refs.push(section.section_ref);
70455
70595
  }
70456
70596
  }
@@ -70458,12 +70598,12 @@ function structureEndpointRefs(structure) {
70458
70598
  return refs;
70459
70599
  }
70460
70600
  async function readYamlRecord(projectRoot, relPath) {
70461
- const absPath = join19(projectRoot, relPath);
70462
- if (!existsSync10(absPath))
70601
+ const absPath = join20(projectRoot, relPath);
70602
+ if (!existsSync11(absPath))
70463
70603
  return null;
70464
70604
  try {
70465
70605
  const parsed = import_yaml10.default.parse(await readFile17(absPath, "utf8"));
70466
- return isRecord9(parsed) ? parsed : null;
70606
+ return isRecord10(parsed) ? parsed : null;
70467
70607
  } catch (error) {
70468
70608
  throw new ContextError(ExitCode.WorkspaceStateError, `${relPath} is invalid YAML`, {
70469
70609
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -70502,7 +70642,7 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70502
70642
  const snapshotEdges = [];
70503
70643
  for (const structureDigest of [...new Set(slots.map((slot) => slot.structureDigest))].sort()) {
70504
70644
  const structure2 = await readStructureSnapshot(projectRoot, structureDigest);
70505
- if (!isRecord9(structure2)) {
70645
+ if (!isRecord10(structure2)) {
70506
70646
  throw new ContextError(ExitCode.WorkspaceStateError, "active structure snapshot is missing", {
70507
70647
  category: ErrorCategory.WorkspaceStateInvalid,
70508
70648
  structure_digest: structureDigest,
@@ -70543,7 +70683,7 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70543
70683
  }
70544
70684
  if (structure === null)
70545
70685
  return null;
70546
- const lifecycle = isRecord9(structure.lifecycle) ? structure.lifecycle : {};
70686
+ const lifecycle = isRecord10(structure.lifecycle) ? structure.lifecycle : {};
70547
70687
  if (lifecycle.state !== "confirmed" && lifecycle.state !== "frozen")
70548
70688
  return null;
70549
70689
  return normalizeApprovedEdges({
@@ -70559,15 +70699,15 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70559
70699
  init_cliFeedback();
70560
70700
  init_errors();
70561
70701
  init_exitCode();
70562
- import { existsSync as existsSync17 } from "node:fs";
70702
+ import { existsSync as existsSync18 } from "node:fs";
70563
70703
  import { readFile as readFile23 } from "node:fs/promises";
70564
- import { join as join27 } from "node:path";
70704
+ import { join as join28 } from "node:path";
70565
70705
 
70566
70706
  // src/project/verifyApprovedStructure.ts
70567
70707
  var import_yaml12 = __toESM(require_dist3(), 1);
70568
- import { existsSync as existsSync13 } from "node:fs";
70708
+ import { existsSync as existsSync14 } from "node:fs";
70569
70709
  import { readFile as readFile19 } from "node:fs/promises";
70570
- import { join as join23 } from "node:path";
70710
+ import { join as join24 } from "node:path";
70571
70711
 
70572
70712
  // src/project/approvedStructureInputHash.ts
70573
70713
  import { createHash as createHash11 } from "node:crypto";
@@ -70608,11 +70748,11 @@ function approvedStructureInputHash(input) {
70608
70748
  }
70609
70749
 
70610
70750
  // src/project/verifyApprovedStructureEdges.ts
70611
- import { join as join21 } from "node:path";
70751
+ import { join as join22 } from "node:path";
70612
70752
 
70613
70753
  // src/project/verifyCanonicalSourceRefs.ts
70614
- import { existsSync as existsSync11 } from "node:fs";
70615
- import { join as join20 } from "node:path";
70754
+ import { existsSync as existsSync12 } from "node:fs";
70755
+ import { join as join21 } from "node:path";
70616
70756
  var CANONICAL_SOURCE_REF = /^repo:([^#]+)#symbol:(.+):([^:@]+):([^:@]+)@([a-f0-9]+)$/iu;
70617
70757
  function validateCanonicalSourceRef(input) {
70618
70758
  const path3 = input.path ?? ".tmp/context-runtime/lifecycle/candidates.jsonl";
@@ -70668,7 +70808,7 @@ async function validateCanonicalEvidenceSourceRef(input) {
70668
70808
  const registryEntry = input.sourceRegistry.loaded ? registeredDocumentSource(input.sourceRegistry, locator.sourceType, locator.sourceName) : undefined;
70669
70809
  const materializedAt = registryEntry?.materializedAt ?? defaultDocumentMaterializedAt(locator.sourceType, locator.sourceName);
70670
70810
  const manifestPath = registryEntry?.snapshot?.manifest ?? defaultDocumentManifest(materializedAt);
70671
- if (!existsSync11(join20(input.projectRoot, manifestPath)) && !snapshotRootExists(input.projectRoot, materializedAt)) {
70811
+ if (!existsSync12(join21(input.projectRoot, manifestPath)) && !snapshotRootExists(input.projectRoot, materializedAt)) {
70672
70812
  input.issues.push({
70673
70813
  severity: unresolvedSeverity,
70674
70814
  code: "approved-evidence-unavailable",
@@ -70741,7 +70881,7 @@ async function validateCanonicalEvidenceSourceRef(input) {
70741
70881
  }
70742
70882
 
70743
70883
  // src/project/verifyApprovedStructureEdges.ts
70744
- var APPROVED_STRUCTURE_PATH2 = join21("knowledge", "structure.yaml");
70884
+ var APPROVED_STRUCTURE_PATH2 = join22("knowledge", "structure.yaml");
70745
70885
  function approvedStructureEdgeRecords(parsed, issues) {
70746
70886
  if (parsed.edges === undefined)
70747
70887
  return [];
@@ -70874,7 +71014,7 @@ async function validateApprovedStructureEdgeRecords(input) {
70874
71014
  init_cliFeedback();
70875
71015
  init_errors();
70876
71016
  init_exitCode();
70877
- function isRecord10(value) {
71017
+ function isRecord11(value) {
70878
71018
  return value !== null && typeof value === "object" && !Array.isArray(value);
70879
71019
  }
70880
71020
  function codegraphEdgesFromFrontmatter(frontmatter, path3) {
@@ -70887,7 +71027,7 @@ function codegraphEdgesFromFrontmatter(frontmatter, path3) {
70887
71027
  });
70888
71028
  }
70889
71029
  return frontmatter.code_edges.map((rawEdge, index2) => {
70890
- if (!isRecord10(rawEdge)) {
71030
+ if (!isRecord11(rawEdge)) {
70891
71031
  throw new ContextError(ExitCode.WorkspaceStateError, "approved code edge must be an object", {
70892
71032
  category: ErrorCategory.WorkspaceStateInvalid,
70893
71033
  path: path3,
@@ -70947,17 +71087,17 @@ function codegraphRelationshipCoverage(input) {
70947
71087
  }
70948
71088
 
70949
71089
  // src/project/approvedStructureInputs.ts
70950
- import { existsSync as existsSync12 } from "node:fs";
71090
+ import { existsSync as existsSync13 } from "node:fs";
70951
71091
  import { readFile as readFile18 } from "node:fs/promises";
70952
- import { join as join22 } from "node:path";
71092
+ import { join as join23 } from "node:path";
70953
71093
  init_cliFeedback();
70954
71094
  init_errors();
70955
71095
  init_exitCode();
70956
71096
  var import_yaml11 = __toESM(require_dist3(), 1);
70957
- var APPROVED_STRUCTURE_FILE = join22("knowledge", "structure.yaml");
71097
+ var APPROVED_STRUCTURE_FILE = join23("knowledge", "structure.yaml");
70958
71098
  var COLLECTIONS = new Set(KNOWLEDGE_COLLECTIONS);
70959
71099
  var SNAPSHOT_HASH_PATTERN = /^sha256:[a-f0-9]{64}$/u;
70960
- function isRecord11(value) {
71100
+ function isRecord12(value) {
70961
71101
  return value !== null && typeof value === "object" && !Array.isArray(value);
70962
71102
  }
70963
71103
  function invalidSourceInputs(reason) {
@@ -70976,14 +71116,14 @@ function sortedSourceInputs(values2) {
70976
71116
  function parseApprovedStructureSourceInputs(structure) {
70977
71117
  if (structure.source_inputs === undefined)
70978
71118
  return [];
70979
- if (!isRecord11(structure.source_inputs)) {
71119
+ if (!isRecord12(structure.source_inputs)) {
70980
71120
  throw invalidSourceInputs("source_inputs must be an object when present");
70981
71121
  }
70982
71122
  const inputs = new Map;
70983
71123
  for (const [source2, collections] of Object.entries(structure.source_inputs)) {
70984
71124
  if (source2.trim().length === 0)
70985
71125
  throw invalidSourceInputs("source_inputs source key must not be empty");
70986
- if (!isRecord11(collections)) {
71126
+ if (!isRecord12(collections)) {
70987
71127
  throw invalidSourceInputs(`source_inputs.${source2} must be an object`);
70988
71128
  }
70989
71129
  for (const [collection, snapshotHash] of Object.entries(collections)) {
@@ -71008,8 +71148,8 @@ function approvedStructureSourceInputsRecord(inputs) {
71008
71148
  return result;
71009
71149
  }
71010
71150
  async function readApprovedStructureSourceInputs(projectRoot) {
71011
- const path3 = join22(projectRoot, APPROVED_STRUCTURE_FILE);
71012
- if (!existsSync12(path3))
71151
+ const path3 = join23(projectRoot, APPROVED_STRUCTURE_FILE);
71152
+ if (!existsSync13(path3))
71013
71153
  return [];
71014
71154
  let parsed;
71015
71155
  try {
@@ -71017,7 +71157,7 @@ async function readApprovedStructureSourceInputs(projectRoot) {
71017
71157
  } catch {
71018
71158
  return [];
71019
71159
  }
71020
- if (!isRecord11(parsed))
71160
+ if (!isRecord12(parsed))
71021
71161
  return [];
71022
71162
  return parseApprovedStructureSourceInputs(parsed);
71023
71163
  }
@@ -71046,14 +71186,14 @@ function approvedStructureSourceInputKey(input) {
71046
71186
  }
71047
71187
 
71048
71188
  // src/project/verifyApprovedStructure.ts
71049
- var APPROVED_STRUCTURE_PATH3 = join23("knowledge", "structure.yaml");
71189
+ var APPROVED_STRUCTURE_PATH3 = join24("knowledge", "structure.yaml");
71050
71190
  var APPROVED_STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
71051
71191
  var LOCAL_REF = /^src-(\d+)(#(?:span|symbol):.+)$/u;
71052
71192
  async function readApprovedStructureForVerify(input) {
71053
71193
  if (input.structureOverride !== undefined)
71054
71194
  return input.structureOverride;
71055
- const structurePath = join23(input.projectRoot, APPROVED_STRUCTURE_PATH3);
71056
- if (!existsSync13(structurePath))
71195
+ const structurePath = join24(input.projectRoot, APPROVED_STRUCTURE_PATH3);
71196
+ if (!existsSync14(structurePath))
71057
71197
  return;
71058
71198
  let rawParsed;
71059
71199
  try {
@@ -71278,7 +71418,7 @@ async function approvedStructureProjection(projectRoot) {
71278
71418
  const views = [];
71279
71419
  const parentIndexes = [];
71280
71420
  const codeEdges = [];
71281
- for (const file of await walkMarkdown(join23(projectRoot, "knowledge"))) {
71421
+ for (const file of await walkMarkdown(join24(projectRoot, "knowledge"))) {
71282
71422
  if (isKnowledgeAssetPath(file.relPath))
71283
71423
  continue;
71284
71424
  const content3 = await readFile19(file.absPath, "utf8");
@@ -71692,13 +71832,13 @@ async function validateApprovedStructureEdges(input) {
71692
71832
  init_workspace();
71693
71833
 
71694
71834
  // src/project/reviewDecisions.ts
71695
- import { existsSync as existsSync16 } from "node:fs";
71835
+ import { existsSync as existsSync17 } from "node:fs";
71696
71836
  import { mkdir as mkdir15, readFile as readFile22, rename as rename3, rm as rm8, writeFile as writeFile11 } from "node:fs/promises";
71697
- import { dirname as dirname19, join as join26 } from "node:path";
71837
+ import { dirname as dirname20, join as join27 } from "node:path";
71698
71838
  init_cliFeedback();
71699
71839
  init_errors();
71700
71840
  init_exitCode();
71701
- var REVIEW_DECISIONS_FILE = join26("knowledge", "decisions.json");
71841
+ var REVIEW_DECISIONS_FILE = join27("knowledge", "decisions.json");
71702
71842
  var FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/u;
71703
71843
  var COLLECTIONS2 = new Set(KNOWLEDGE_COLLECTIONS);
71704
71844
  function isCandidateId(value) {
@@ -71713,8 +71853,8 @@ function invalidDecisions(reason) {
71713
71853
  });
71714
71854
  }
71715
71855
  async function readRejectedDecisions(projectRoot) {
71716
- const path3 = join26(projectRoot, REVIEW_DECISIONS_FILE);
71717
- if (!existsSync16(path3))
71856
+ const path3 = join27(projectRoot, REVIEW_DECISIONS_FILE);
71857
+ if (!existsSync17(path3))
71718
71858
  return new Map;
71719
71859
  let parsed;
71720
71860
  try {
@@ -71738,14 +71878,14 @@ async function readRejectedDecisions(projectRoot) {
71738
71878
  return decisions;
71739
71879
  }
71740
71880
  async function writeRejectedDecisions(projectRoot, decisions) {
71741
- const path3 = join26(projectRoot, REVIEW_DECISIONS_FILE);
71881
+ const path3 = join27(projectRoot, REVIEW_DECISIONS_FILE);
71742
71882
  if (decisions.size === 0) {
71743
71883
  await rm8(path3, { force: true });
71744
71884
  return;
71745
71885
  }
71746
71886
  const rejected = Object.fromEntries([...decisions.entries()].sort(([left], [right]) => left.localeCompare(right)));
71747
71887
  const tempPath = `${path3}.${process.pid}.tmp`;
71748
- await mkdir15(dirname19(path3), { recursive: true });
71888
+ await mkdir15(dirname20(path3), { recursive: true });
71749
71889
  await writeFile11(tempPath, `${JSON.stringify(rejected, null, 2)}
71750
71890
  `, "utf8");
71751
71891
  await rename3(tempPath, path3);
@@ -71922,7 +72062,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
71922
72062
  issues
71923
72063
  });
71924
72064
  const seenViewRefs = new Set;
71925
- for (const file of await walkMarkdown(join27(projectRoot, "knowledge"))) {
72065
+ for (const file of await walkMarkdown(join28(projectRoot, "knowledge"))) {
71926
72066
  if (isKnowledgeAssetPath(file.relPath))
71927
72067
  continue;
71928
72068
  const content3 = await readFile23(file.absPath, "utf8");
@@ -71945,7 +72085,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
71945
72085
  pageRelPath: `knowledge/${file.relPath}`,
71946
72086
  content: content3
71947
72087
  })) {
71948
- if (!existsSync17(join27(projectRoot, assetPath))) {
72088
+ if (!existsSync18(join28(projectRoot, assetPath))) {
71949
72089
  issues.push({
71950
72090
  severity: "error",
71951
72091
  code: "approved-resource-missing",
@@ -72131,9 +72271,9 @@ init_writeLock();
72131
72271
 
72132
72272
  // src/project/proseCompileBatch.ts
72133
72273
  var import_yaml13 = __toESM(require_dist3(), 1);
72134
- import { existsSync as existsSync19 } from "node:fs";
72274
+ import { existsSync as existsSync20 } from "node:fs";
72135
72275
  import { readFile as readFile25 } from "node:fs/promises";
72136
- import { join as join29 } from "node:path";
72276
+ import { join as join30 } from "node:path";
72137
72277
  init_cliFeedback();
72138
72278
  init_errors();
72139
72279
  init_exitCode();
@@ -72142,9 +72282,9 @@ init_exitCode();
72142
72282
  init_cliFeedback();
72143
72283
  init_errors();
72144
72284
  init_exitCode();
72145
- import { existsSync as existsSync18 } from "node:fs";
72285
+ import { existsSync as existsSync19 } from "node:fs";
72146
72286
  import { readFile as readFile24, readdir as readdir10 } from "node:fs/promises";
72147
- import { basename as basename6, join as join28, relative as relative12 } from "node:path";
72287
+ import { basename as basename6, join as join29, relative as relative12 } from "node:path";
72148
72288
  init_writeLock();
72149
72289
  function candidateSourceKey(record) {
72150
72290
  return record.source === undefined ? undefined : `${record.source.type}:${record.source.name}`;
@@ -72156,11 +72296,11 @@ function toPosixPath8(value) {
72156
72296
  return value.split(/[\\/]+/u).join("/");
72157
72297
  }
72158
72298
  async function approvedPageIdentities(projectRoot) {
72159
- const root = join28(projectRoot, "knowledge");
72299
+ const root = join29(projectRoot, "knowledge");
72160
72300
  const identities = [];
72161
72301
  const visit2 = async (directory) => {
72162
72302
  for (const entry of await readdir10(directory, { withFileTypes: true })) {
72163
- const absolutePath = join28(directory, entry.name);
72303
+ const absolutePath = join29(directory, entry.name);
72164
72304
  if (entry.isDirectory()) {
72165
72305
  await visit2(absolutePath);
72166
72306
  continue;
@@ -72178,7 +72318,7 @@ async function approvedPageIdentities(projectRoot) {
72178
72318
  });
72179
72319
  }
72180
72320
  };
72181
- if (existsSync18(root))
72321
+ if (existsSync19(root))
72182
72322
  await visit2(root);
72183
72323
  return {
72184
72324
  byPath: new Map(identities.map((identity) => [identity.path, identity])),
@@ -72407,7 +72547,7 @@ async function preserveApprovedPathIdentities(input) {
72407
72547
  }
72408
72548
 
72409
72549
  // src/project/proseCompileBatch.ts
72410
- function isRecord13(value) {
72550
+ function isRecord14(value) {
72411
72551
  return value !== null && typeof value === "object" && !Array.isArray(value);
72412
72552
  }
72413
72553
  function stringField2(value, field) {
@@ -72415,11 +72555,11 @@ function stringField2(value, field) {
72415
72555
  return typeof candidate === "string" && candidate.trim().length > 0 ? candidate.trim() : undefined;
72416
72556
  }
72417
72557
  async function readConfirmedStructure(projectRoot) {
72418
- const path3 = join29(projectRoot, LIFECYCLE_STRUCTURE_FILE);
72419
- if (!existsSync19(path3))
72558
+ const path3 = join30(projectRoot, LIFECYCLE_STRUCTURE_FILE);
72559
+ if (!existsSync20(path3))
72420
72560
  return;
72421
72561
  const parsed = import_yaml13.default.parse(await readFile25(path3, "utf8"));
72422
- if (!isRecord13(parsed) || !isRecord13(parsed.lifecycle))
72562
+ if (!isRecord14(parsed) || !isRecord14(parsed.lifecycle))
72423
72563
  return;
72424
72564
  if (parsed.lifecycle.state !== "confirmed" && parsed.lifecycle.state !== "frozen")
72425
72565
  return;
@@ -72434,7 +72574,7 @@ async function readCurrentSnapshotHashes(projectRoot) {
72434
72574
  }
72435
72575
  async function approvedViewRefs(projectRoot, planned) {
72436
72576
  const approved = [];
72437
- for (const file of await walkMarkdown(join29(projectRoot, "knowledge"))) {
72577
+ for (const file of await walkMarkdown(join30(projectRoot, "knowledge"))) {
72438
72578
  if (isKnowledgeAssetPath(file.relPath))
72439
72579
  continue;
72440
72580
  const content3 = await readFile25(file.absPath, "utf8");
@@ -72702,7 +72842,7 @@ function proseCompileBatchNextAction(input) {
72702
72842
 
72703
72843
  // src/project/lifecycleCleanup.ts
72704
72844
  import { rm as rm9 } from "node:fs/promises";
72705
- import { join as join30 } from "node:path";
72845
+ import { join as join31 } from "node:path";
72706
72846
  var COMPLETED_RUNTIME_PATHS = [
72707
72847
  LIFECYCLE_ROOT,
72708
72848
  REVIEW_RUNTIME_ROOT,
@@ -72711,13 +72851,13 @@ var COMPLETED_RUNTIME_PATHS = [
72711
72851
  CANDIDATE_SNAPSHOT_ROOT
72712
72852
  ];
72713
72853
  async function clearCompletedLifecycle(projectRoot) {
72714
- await Promise.all(COMPLETED_RUNTIME_PATHS.map((path3) => rm9(join30(projectRoot, path3), { recursive: true, force: true })));
72854
+ await Promise.all(COMPLETED_RUNTIME_PATHS.map((path3) => rm9(join31(projectRoot, path3), { recursive: true, force: true })));
72715
72855
  }
72716
72856
 
72717
72857
  // src/project/knowledgeAssetRepair.ts
72718
- import { existsSync as existsSync20 } from "node:fs";
72858
+ import { existsSync as existsSync21 } from "node:fs";
72719
72859
  import { mkdir as mkdir16, readFile as readFile26, writeFile as writeFile12 } from "node:fs/promises";
72720
- import { dirname as dirname20, join as join31 } from "node:path";
72860
+ import { dirname as dirname21, join as join32 } from "node:path";
72721
72861
  init_cliFeedback();
72722
72862
  init_errors();
72723
72863
  init_exitCode();
@@ -72728,14 +72868,14 @@ function sourceLocators(frontmatter) {
72728
72868
  ])];
72729
72869
  }
72730
72870
  async function bytesEqual(path3, expected) {
72731
- if (!existsSync20(path3))
72871
+ if (!existsSync21(path3))
72732
72872
  return false;
72733
72873
  const actual = await readFile26(path3);
72734
72874
  return actual.length === expected.length && actual.equals(Buffer.from(expected));
72735
72875
  }
72736
72876
  async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72737
72877
  const affected = [];
72738
- for (const file of await walkMarkdown(join31(projectRoot, "knowledge"))) {
72878
+ for (const file of await walkMarkdown(join32(projectRoot, "knowledge"))) {
72739
72879
  if (isKnowledgeAssetPath(file.relPath))
72740
72880
  continue;
72741
72881
  const content3 = await readFile26(file.absPath, "utf8");
@@ -72809,7 +72949,7 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72809
72949
  for (const asset of assets.values()) {
72810
72950
  if (await bytesEqual(asset.absPath, asset.bytes))
72811
72951
  continue;
72812
- await mkdir16(dirname20(asset.absPath), { recursive: true });
72952
+ await mkdir16(dirname21(asset.absPath), { recursive: true });
72813
72953
  await writeFile12(asset.absPath, asset.bytes);
72814
72954
  writtenAssets.push(asset.relPath);
72815
72955
  }
@@ -72825,7 +72965,7 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72825
72965
 
72826
72966
  // src/project/close.ts
72827
72967
  var KNOWLEDGE_ROOT2 = "knowledge";
72828
- var STRUCTURE_PATH = join32(KNOWLEDGE_ROOT2, "structure.yaml");
72968
+ var STRUCTURE_PATH = join33(KNOWLEDGE_ROOT2, "structure.yaml");
72829
72969
  var STRUCTURE_SCHEMA_VERSION2 = "context.approved-structure.v1";
72830
72970
  var LOCAL_REF2 = /^src-(\d+)(#(?:span|symbol):.+)$/u;
72831
72971
  var APPROVED_NODE_TYPES2 = new Set(["entity", "domain", "action"]);
@@ -72855,13 +72995,13 @@ function requiredFrontmatterString(frontmatter, field, relPath) {
72855
72995
  });
72856
72996
  }
72857
72997
  async function walkFiles2(root) {
72858
- if (!existsSync21(root))
72998
+ if (!existsSync22(root))
72859
72999
  return [];
72860
73000
  const files = [];
72861
73001
  const visit2 = async (dir) => {
72862
73002
  const entries = await readdir11(dir, { withFileTypes: true });
72863
73003
  for (const entry of entries) {
72864
- const absPath = join32(dir, entry.name);
73004
+ const absPath = join33(dir, entry.name);
72865
73005
  if (entry.isDirectory()) {
72866
73006
  await visit2(absPath);
72867
73007
  continue;
@@ -72886,7 +73026,7 @@ function isDeprecated(content3) {
72886
73026
  return parseFrontmatter3(content3).deprecated === true;
72887
73027
  }
72888
73028
  async function approvedKnowledgeFiles(projectRoot) {
72889
- const files = await walkFiles2(join32(projectRoot, KNOWLEDGE_ROOT2));
73029
+ const files = await walkFiles2(join33(projectRoot, KNOWLEDGE_ROOT2));
72890
73030
  const markdown = await Promise.all(files.filter((file) => file.relPath.endsWith(".md") && !isKnowledgeAssetPath(file.relPath)).map(async (file) => ({
72891
73031
  ...file,
72892
73032
  content: await readFile27(file.absPath, "utf8")
@@ -73156,11 +73296,11 @@ function referencesReceipt() {
73156
73296
  }
73157
73297
  async function readProjectCloseStatus(projectRoot) {
73158
73298
  const approved = await approvedKnowledgeFiles(projectRoot);
73159
- const structurePath = join32(projectRoot, STRUCTURE_PATH);
73160
- if (approved.length === 0 && !existsSync21(structurePath))
73299
+ const structurePath = join33(projectRoot, STRUCTURE_PATH);
73300
+ if (approved.length === 0 && !existsSync22(structurePath))
73161
73301
  return { state: "missing", diagnostics: [] };
73162
73302
  const inputHash = await approvedKnowledgeInputHash(projectRoot);
73163
- if (!existsSync21(structurePath))
73303
+ if (!existsSync22(structurePath))
73164
73304
  return { state: "missing", inputHash, diagnostics: [`close structure is missing: ${STRUCTURE_PATH}`] };
73165
73305
  try {
73166
73306
  const parsed = import_yaml14.default.parse(await readFile27(structurePath, "utf8"));
@@ -73229,8 +73369,8 @@ async function closeProjectWorkspace(projectRoot) {
73229
73369
  next: "Fix context verify errors, then rerun context close --format json."
73230
73370
  });
73231
73371
  }
73232
- const outputPath = join32(projectRoot, STRUCTURE_PATH);
73233
- await mkdir17(dirname21(outputPath), { recursive: true });
73372
+ const outputPath = join33(projectRoot, STRUCTURE_PATH);
73373
+ await mkdir17(dirname22(outputPath), { recursive: true });
73234
73374
  await writeFile13(outputPath, `${import_yaml14.default.stringify(structure)}`, "utf8");
73235
73375
  await clearCompletedLifecycle(projectRoot);
73236
73376
  return {
@@ -73279,22 +73419,33 @@ async function runProjectCloseCommand(input) {
73279
73419
  ].join(`
73280
73420
  `));
73281
73421
  }
73422
+ queueContextRuntimeEvent({
73423
+ cwd: result.projectRoot,
73424
+ kind: "knowledge.closed",
73425
+ properties: {
73426
+ node_count: result.nodes,
73427
+ view_count: result.views,
73428
+ edge_count: result.edges,
73429
+ verify_warning_count: result.verifyWarnings,
73430
+ relationship_coverage: result.relationshipCoverage.state
73431
+ }
73432
+ });
73282
73433
  return true;
73283
73434
  }
73284
73435
 
73285
73436
  // src/project/reviewApply.ts
73286
- import { existsSync as existsSync26 } from "node:fs";
73437
+ import { existsSync as existsSync27 } from "node:fs";
73287
73438
  import { mkdir as mkdir22, readFile as readFile34, rm as rm11, writeFile as writeFile18 } from "node:fs/promises";
73288
- import { dirname as dirname26, join as join41 } from "node:path";
73439
+ import { dirname as dirname27, join as join42 } from "node:path";
73289
73440
  init_cliFeedback();
73290
73441
  init_errors();
73291
73442
  init_exitCode();
73292
73443
 
73293
73444
  // src/project/proseCompileStructure.ts
73294
73445
  import { createHash as createHash15 } from "node:crypto";
73295
- import { existsSync as existsSync24 } from "node:fs";
73446
+ import { existsSync as existsSync25 } from "node:fs";
73296
73447
  import { mkdir as mkdir20, readFile as readFile32, writeFile as writeFile16 } from "node:fs/promises";
73297
- import { dirname as dirname24, join as join39 } from "node:path";
73448
+ import { dirname as dirname25, join as join40 } from "node:path";
73298
73449
  init_cliFeedback();
73299
73450
  init_errors();
73300
73451
  init_exitCode();
@@ -73303,7 +73454,7 @@ var import_yaml20 = __toESM(require_dist3(), 1);
73303
73454
  // src/project/proseAlignEvidence.ts
73304
73455
  import { createHash as createHash13 } from "node:crypto";
73305
73456
  import { readFile as readFile28 } from "node:fs/promises";
73306
- import { join as join33 } from "node:path";
73457
+ import { join as join34 } from "node:path";
73307
73458
 
73308
73459
  // src/incremental/rawBlocks.ts
73309
73460
  var import_yaml15 = __toESM(require_dist3(), 1);
@@ -77198,7 +77349,7 @@ async function loadProseEvidence(input) {
77198
77349
  const documents = [];
77199
77350
  const chunks = [];
77200
77351
  for (const [documentIndex, document4] of indexResult.index.documents.entries()) {
77201
- const markdown = await readFile28(join33(input.projectRoot, indexResult.index.materialized_at, document4.path), "utf8");
77352
+ const markdown = await readFile28(join34(input.projectRoot, indexResult.index.materialized_at, document4.path), "utf8");
77202
77353
  const locator = locatorFor({
77203
77354
  sourceType: resolved.sourceType,
77204
77355
  sourceName: resolved.sourceName,
@@ -77673,19 +77824,19 @@ function repairHints(diagnostics, phaseId) {
77673
77824
 
77674
77825
  // src/project/proseAlignStructureSummary.ts
77675
77826
  import { mkdir as mkdir18, writeFile as writeFile14 } from "node:fs/promises";
77676
- import { dirname as dirname22, join as join36 } from "node:path";
77827
+ import { dirname as dirname23, join as join37 } from "node:path";
77677
77828
 
77678
77829
  // src/project/proseAlignExistingApprovedStructure.ts
77679
77830
  var import_yaml16 = __toESM(require_dist3(), 1);
77680
- import { existsSync as existsSync22 } from "node:fs";
77831
+ import { existsSync as existsSync23 } from "node:fs";
77681
77832
  import { readFile as readFile29, readdir as readdir12 } from "node:fs/promises";
77682
- import { basename as basename7, join as join34, relative as relative14 } from "node:path";
77683
- var APPROVED_STRUCTURE_PATH4 = join34("knowledge", "structure.yaml");
77833
+ import { basename as basename7, join as join35, relative as relative14 } from "node:path";
77834
+ var APPROVED_STRUCTURE_PATH4 = join35("knowledge", "structure.yaml");
77684
77835
  var KNOWLEDGE_ROOT3 = "knowledge";
77685
77836
  function uniqueRefs(refs) {
77686
77837
  return [...new Set(refs)].sort();
77687
77838
  }
77688
- function isRecord14(value) {
77839
+ function isRecord15(value) {
77689
77840
  return value !== null && typeof value === "object" && !Array.isArray(value);
77690
77841
  }
77691
77842
  function stringField3(record, key) {
@@ -77702,14 +77853,14 @@ function toPosixPath10(path4) {
77702
77853
  return path4.split(/[\\/]+/u).join("/");
77703
77854
  }
77704
77855
  async function approvedMarkdownFiles(projectRoot) {
77705
- const root2 = join34(projectRoot, KNOWLEDGE_ROOT3);
77706
- if (!existsSync22(root2))
77856
+ const root2 = join35(projectRoot, KNOWLEDGE_ROOT3);
77857
+ if (!existsSync23(root2))
77707
77858
  return [];
77708
77859
  const files = [];
77709
77860
  const visit3 = async (directory) => {
77710
77861
  const entries = await readdir12(directory, { withFileTypes: true });
77711
77862
  for (const entry of entries) {
77712
- const absolutePath = join34(directory, entry.name);
77863
+ const absolutePath = join35(directory, entry.name);
77713
77864
  if (entry.isDirectory()) {
77714
77865
  await visit3(absolutePath);
77715
77866
  continue;
@@ -77726,7 +77877,7 @@ function frontmatterRecord(markdown) {
77726
77877
  if (match === null)
77727
77878
  return;
77728
77879
  const parsed = import_yaml16.default.parse(match[1] ?? "");
77729
- return isRecord14(parsed) ? parsed : undefined;
77880
+ return isRecord15(parsed) ? parsed : undefined;
77730
77881
  }
77731
77882
  function isDeprecatedApprovedPage(markdown) {
77732
77883
  return /^deprecated:\s*true\s*$/mu.test(markdown);
@@ -77775,7 +77926,7 @@ async function parseExistingApprovedMarkdown(projectRoot) {
77775
77926
  node_type: existingNode?.node_type ?? nodeType,
77776
77927
  tags: uniqueRefs([...existingNode?.tags ?? [], ...nodeTags])
77777
77928
  });
77778
- const relPath = toPosixPath10(relative14(join34(projectRoot, KNOWLEDGE_ROOT3), filePath));
77929
+ const relPath = toPosixPath10(relative14(join35(projectRoot, KNOWLEDGE_ROOT3), filePath));
77779
77930
  const location = pathLocation(relPath);
77780
77931
  const collection = viewRef.split(":", 1)[0] ?? location.collection;
77781
77932
  views.set(viewRef, {
@@ -77804,8 +77955,8 @@ async function parseExistingApprovedMarkdown(projectRoot) {
77804
77955
  return { nodes, views, sections, edges: [], diagnostics: [] };
77805
77956
  }
77806
77957
  async function readFreshApprovedStructureEdges(projectRoot) {
77807
- const absolutePath = join34(projectRoot, APPROVED_STRUCTURE_PATH4);
77808
- if (!existsSync22(absolutePath))
77958
+ const absolutePath = join35(projectRoot, APPROVED_STRUCTURE_PATH4);
77959
+ if (!existsSync23(absolutePath))
77809
77960
  return { edges: [], diagnostics: [] };
77810
77961
  let raw;
77811
77962
  try {
@@ -77814,7 +77965,7 @@ async function readFreshApprovedStructureEdges(projectRoot) {
77814
77965
  const message = error instanceof Error ? error.message : String(error);
77815
77966
  return { edges: [], diagnostics: [`knowledge/structure.yaml could not be parsed: ${message}`] };
77816
77967
  }
77817
- if (!isRecord14(raw) || raw.schema_version !== "context.approved-structure.v1") {
77968
+ if (!isRecord15(raw) || raw.schema_version !== "context.approved-structure.v1") {
77818
77969
  return { edges: [], diagnostics: ["knowledge/structure.yaml schema is not current; approved summary uses Markdown projection only."] };
77819
77970
  }
77820
77971
  const expectedInputHash = await approvedKnowledgeInputHash(projectRoot).catch(() => {
@@ -77848,7 +77999,7 @@ function emptyExistingApprovedStructureSummary(diagnostics = []) {
77848
77999
  function parseApprovedEdges(raw) {
77849
78000
  const edges = [];
77850
78001
  for (const rawEdge of Array.isArray(raw.edges) ? raw.edges : []) {
77851
- if (!isRecord14(rawEdge))
78002
+ if (!isRecord15(rawEdge))
77852
78003
  continue;
77853
78004
  const type = stringField3(rawEdge, "type");
77854
78005
  const from = stringField3(rawEdge, "from");
@@ -77918,7 +78069,7 @@ async function readExistingApprovedStructureSummary(input) {
77918
78069
  const freshStructure = await readFreshApprovedStructureEdges(input.projectRoot);
77919
78070
  approved.edges = freshStructure.edges;
77920
78071
  approved.diagnostics.push(...freshStructure.diagnostics);
77921
- if (approved.nodes.size === 0 && approved.views.size === 0 && approved.sections.size === 0 && !existsSync22(join34(input.projectRoot, APPROVED_STRUCTURE_PATH4))) {
78072
+ if (approved.nodes.size === 0 && approved.views.size === 0 && approved.sections.size === 0 && !existsSync23(join35(input.projectRoot, APPROVED_STRUCTURE_PATH4))) {
77922
78073
  return emptyExistingApprovedStructureSummary();
77923
78074
  }
77924
78075
  const endpointRefs = new Set([
@@ -79026,12 +79177,12 @@ function renderStructureSummaryHtml(input) {
79026
79177
 
79027
79178
  // src/project/localHtmlReport.ts
79028
79179
  import { execFile as execFile3 } from "node:child_process";
79029
- import { isAbsolute as isAbsolute7, join as join35 } from "node:path";
79180
+ import { isAbsolute as isAbsolute7, join as join36 } from "node:path";
79030
79181
  import { pathToFileURL } from "node:url";
79031
79182
  import { promisify as promisify3 } from "node:util";
79032
79183
  var execFileAsync3 = promisify3(execFile3);
79033
79184
  function htmlReportReference(input) {
79034
- const absolutePath = isAbsolute7(input.path) ? input.path : join35(input.projectRoot, input.path);
79185
+ const absolutePath = isAbsolute7(input.path) ? input.path : join36(input.projectRoot, input.path);
79035
79186
  return {
79036
79187
  format: "html",
79037
79188
  path: input.path,
@@ -79377,9 +79528,9 @@ function buildStructureSummary(input) {
79377
79528
  async function writeStructureSummaryReport(input) {
79378
79529
  const summary = buildStructureSummary(input);
79379
79530
  const shortDigest = summary.structure_digest.replace(/^sha256:/u, "").slice(0, 16);
79380
- const reportPath = join36(".tmp", "context-runtime", "reports", `structure-summary-${shortDigest}.html`);
79381
- const absolutePath = join36(input.projectRoot, reportPath);
79382
- await mkdir18(dirname22(absolutePath), { recursive: true });
79531
+ const reportPath = join37(".tmp", "context-runtime", "reports", `structure-summary-${shortDigest}.html`);
79532
+ const absolutePath = join37(input.projectRoot, reportPath);
79533
+ await mkdir18(dirname23(absolutePath), { recursive: true });
79383
79534
  await writeFile14(absolutePath, renderStructureSummaryHtml({ summary, diagnostics: input.diagnostics }), "utf8");
79384
79535
  return {
79385
79536
  summary,
@@ -79554,9 +79705,9 @@ function withStructureReviewArtifacts(input) {
79554
79705
  // src/project/proseCompileViews.ts
79555
79706
  var import_yaml17 = __toESM(require_dist3(), 1);
79556
79707
  import { createHash as createHash14 } from "node:crypto";
79557
- import { existsSync as existsSync23 } from "node:fs";
79708
+ import { existsSync as existsSync24 } from "node:fs";
79558
79709
  import { readFile as readFile30 } from "node:fs/promises";
79559
- import { join as join37 } from "node:path";
79710
+ import { join as join38 } from "node:path";
79560
79711
 
79561
79712
  // src/project/proseCompileSemanticRules.ts
79562
79713
  function compileSemanticRules(input) {
@@ -79959,8 +80110,8 @@ function canonicalizeApprovedSourceRef2(ref2, sources) {
79959
80110
  }
79960
80111
  async function existingApprovedNodeSections(input) {
79961
80112
  const relativePath = `knowledge/${input.node.path}`;
79962
- const absolutePath = join37(input.projectRoot, relativePath);
79963
- if (!existsSync23(absolutePath)) {
80113
+ const absolutePath = join38(input.projectRoot, relativePath);
80114
+ if (!existsSync24(absolutePath)) {
79964
80115
  return {
79965
80116
  path: relativePath,
79966
80117
  present: false,
@@ -80342,7 +80493,7 @@ function parsePayloadText(raw) {
80342
80493
  // src/project/proseAlignPayloadStage.ts
80343
80494
  var import_yaml19 = __toESM(require_dist3(), 1);
80344
80495
  import { mkdir as mkdir19, writeFile as writeFile15 } from "node:fs/promises";
80345
- import { dirname as dirname23, join as join38 } from "node:path";
80496
+ import { dirname as dirname24, join as join39 } from "node:path";
80346
80497
  init_writeLock();
80347
80498
  async function resolveStagedPayloadConfirmation(input) {
80348
80499
  await archiveActiveStructure(input.projectRoot);
@@ -80413,7 +80564,7 @@ async function stageAlignPayload(input) {
80413
80564
  next: readPlanCommand
80414
80565
  });
80415
80566
  }
80416
- const structurePath = join38(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
80567
+ const structurePath = join39(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
80417
80568
  const resolved = await resolveStagedPayloadConfirmation(input);
80418
80569
  const effectivePayload = {
80419
80570
  ...resolved.payload,
@@ -80425,7 +80576,7 @@ async function stageAlignPayload(input) {
80425
80576
  if (effectivePayload.lifecycle.state === "confirmed" || effectivePayload.lifecycle.state === "frozen") {
80426
80577
  await writeStructureSnapshot(input.projectRoot, effectivePayload);
80427
80578
  }
80428
- await mkdir19(dirname23(structurePath), { recursive: true });
80579
+ await mkdir19(dirname24(structurePath), { recursive: true });
80429
80580
  await writeFile15(structurePath, import_yaml19.default.stringify(normalizeAlignPayloadForWrite(effectivePayload)), "utf8");
80430
80581
  return {
80431
80582
  structureFile: LIFECYCLE_STRUCTURE_FILE,
@@ -80941,7 +81092,7 @@ function canonicalJson2(value) {
80941
81092
  function digest3(value) {
80942
81093
  return `sha256:${createHash15("sha256").update(canonicalJson2(value)).digest("hex")}`;
80943
81094
  }
80944
- function isRecord15(value) {
81095
+ function isRecord16(value) {
80945
81096
  return value !== null && typeof value === "object" && !Array.isArray(value);
80946
81097
  }
80947
81098
  function stringField4(record, field) {
@@ -80952,8 +81103,8 @@ function stringArray2(value) {
80952
81103
  return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
80953
81104
  }
80954
81105
  async function readStructureFile(projectRoot) {
80955
- const structurePath = join39(projectRoot, LIFECYCLE_STRUCTURE_FILE);
80956
- if (!existsSync24(structurePath)) {
81106
+ const structurePath = join40(projectRoot, LIFECYCLE_STRUCTURE_FILE);
81107
+ if (!existsSync25(structurePath)) {
80957
81108
  return null;
80958
81109
  }
80959
81110
  let raw;
@@ -80978,8 +81129,8 @@ async function readStructureFile(projectRoot) {
80978
81129
  }
80979
81130
  }
80980
81131
  async function readApprovedStructureFile(projectRoot) {
80981
- const structurePath = join39(projectRoot, APPROVED_STRUCTURE_FILE2);
80982
- if (!existsSync24(structurePath))
81132
+ const structurePath = join40(projectRoot, APPROVED_STRUCTURE_FILE2);
81133
+ if (!existsSync25(structurePath))
80983
81134
  return null;
80984
81135
  try {
80985
81136
  return import_yaml20.default.parse(await readFile32(structurePath, "utf8"));
@@ -80994,13 +81145,13 @@ async function readApprovedStructureFile(projectRoot) {
80994
81145
  async function compileStructureSlotDigest(input) {
80995
81146
  const slotDigest = await currentStructureSlotDigest(input.projectRoot, input.sourceKey, input.collection);
80996
81147
  const current2 = await readStructureFile(input.projectRoot);
80997
- if (current2 === null || !isRecord15(current2) || !Array.isArray(current2.sources) || !Array.isArray(current2.views)) {
81148
+ if (current2 === null || !isRecord16(current2) || !Array.isArray(current2.sources) || !Array.isArray(current2.views)) {
80998
81149
  return slotDigest;
80999
81150
  }
81000
- const currentOwnsTarget = current2.sources.includes(input.sourceKey) && current2.views.some((view) => isRecord15(view) && view.collection === input.collection);
81151
+ const currentOwnsTarget = current2.sources.includes(input.sourceKey) && current2.views.some((view) => isRecord16(view) && view.collection === input.collection);
81001
81152
  if (!currentOwnsTarget)
81002
81153
  return slotDigest;
81003
- const lifecycle = isRecord15(current2.lifecycle) ? current2.lifecycle : undefined;
81154
+ const lifecycle = isRecord16(current2.lifecycle) ? current2.lifecycle : undefined;
81004
81155
  const currentDigest = lifecycle === undefined ? undefined : stringField4(lifecycle, "structure_digest");
81005
81156
  return slotDigest !== undefined && slotDigest !== currentDigest ? slotDigest : undefined;
81006
81157
  }
@@ -81009,7 +81160,7 @@ function parseApprovedSections(value, viewRef) {
81009
81160
  return [];
81010
81161
  const sections = [];
81011
81162
  for (const rawSection of value) {
81012
- if (!isRecord15(rawSection))
81163
+ if (!isRecord16(rawSection))
81013
81164
  continue;
81014
81165
  const id2 = stringField4(rawSection, "id");
81015
81166
  const kind = stringField4(rawSection, "kind");
@@ -81032,7 +81183,7 @@ function parseApprovedNodes(value) {
81032
81183
  return [];
81033
81184
  const nodes = [];
81034
81185
  for (const rawNode of value) {
81035
- if (!isRecord15(rawNode))
81186
+ if (!isRecord16(rawNode))
81036
81187
  continue;
81037
81188
  const nodeRef = stringField4(rawNode, "node_ref");
81038
81189
  const title = stringField4(rawNode, "title");
@@ -81056,7 +81207,7 @@ function parseApprovedViews(value, nodes) {
81056
81207
  const nodeByRef = new Map(nodes.map((node3) => [node3.node_ref, node3]));
81057
81208
  const views = [];
81058
81209
  for (const rawView of value) {
81059
- if (!isRecord15(rawView))
81210
+ if (!isRecord16(rawView))
81060
81211
  continue;
81061
81212
  const viewRef = stringField4(rawView, "view_ref");
81062
81213
  const nodeRef = stringField4(rawView, "node_ref");
@@ -81094,7 +81245,7 @@ function parseApprovedEdges2(value) {
81094
81245
  return [];
81095
81246
  const edges = [];
81096
81247
  for (const rawEdge of value) {
81097
- if (!isRecord15(rawEdge))
81248
+ if (!isRecord16(rawEdge))
81098
81249
  continue;
81099
81250
  const type = stringField4(rawEdge, "type");
81100
81251
  const from = stringField4(rawEdge, "from");
@@ -81158,7 +81309,7 @@ function assertApprovedEdgeContract(value, endpointRefs) {
81158
81309
  });
81159
81310
  }
81160
81311
  for (const [index2, rawEdge] of value.entries()) {
81161
- if (!isRecord15(rawEdge)) {
81312
+ if (!isRecord16(rawEdge)) {
81162
81313
  throw workspaceError("knowledge/structure.yaml edge must be an object", {
81163
81314
  path: APPROVED_STRUCTURE_FILE2,
81164
81315
  edge_index: index2,
@@ -81298,7 +81449,7 @@ async function loadConfirmedStructure(input) {
81298
81449
  let rawStructure = input.structureDigest === undefined ? await readStructureFile(input.projectRoot) : await readStructureSnapshot(input.projectRoot, input.structureDigest);
81299
81450
  if (rawStructure === null && input.structureDigest !== undefined) {
81300
81451
  const active = await readStructureFile(input.projectRoot);
81301
- const activeDigest = isRecord15(active) && isRecord15(active.lifecycle) ? stringField4(active.lifecycle, "structure_digest") : undefined;
81452
+ const activeDigest = isRecord16(active) && isRecord16(active.lifecycle) ? stringField4(active.lifecycle, "structure_digest") : undefined;
81302
81453
  if (activeDigest === input.structureDigest) {
81303
81454
  rawStructure = active;
81304
81455
  } else if (input.readOnly !== true) {
@@ -81315,7 +81466,7 @@ async function loadConfirmedStructure(input) {
81315
81466
  });
81316
81467
  }
81317
81468
  const approvedStructure = await readApprovedStructureFile(input.projectRoot);
81318
- if (!isRecord15(approvedStructure)) {
81469
+ if (!isRecord16(approvedStructure)) {
81319
81470
  throw workspaceError("compileProse requires confirmed .tmp/context-runtime/lifecycle/structure.yaml or approved knowledge/structure.yaml", {
81320
81471
  path: LIFECYCLE_STRUCTURE_FILE,
81321
81472
  approved_structure: APPROVED_STRUCTURE_FILE2,
@@ -81411,8 +81562,8 @@ async function freezeStructureIfNeeded(input) {
81411
81562
  };
81412
81563
  await archiveActiveStructure(input.projectRoot);
81413
81564
  await writeStructureSnapshot(input.projectRoot, nextStructure);
81414
- const structurePath = join39(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
81415
- await mkdir20(dirname24(structurePath), { recursive: true });
81565
+ const structurePath = join40(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
81566
+ await mkdir20(dirname25(structurePath), { recursive: true });
81416
81567
  await writeFile16(structurePath, import_yaml20.default.stringify({
81417
81568
  schema_version: nextStructure.schema_version,
81418
81569
  sources: nextStructure.sources,
@@ -81495,9 +81646,9 @@ var import_yaml22 = __toESM(require_dist3(), 1);
81495
81646
 
81496
81647
  // src/project/reviewShared.ts
81497
81648
  import { createHash as createHash16 } from "node:crypto";
81498
- import { existsSync as existsSync25, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "node:fs";
81649
+ import { existsSync as existsSync26, readdirSync as readdirSync2, readFileSync as readFileSync7 } from "node:fs";
81499
81650
  import { mkdir as mkdir21, readFile as readFile33, rm as rm10, rmdir as rmdir2, writeFile as writeFile17 } from "node:fs/promises";
81500
- import { dirname as dirname25, join as join40 } from "node:path";
81651
+ import { dirname as dirname26, join as join41 } from "node:path";
81501
81652
  init_cliFeedback();
81502
81653
  init_errors();
81503
81654
  init_exitCode();
@@ -81527,10 +81678,10 @@ function proseCandidateMarkdown(input) {
81527
81678
 
81528
81679
  // src/project/reviewShared.ts
81529
81680
  init_workspace();
81530
- var SNAPSHOT_ROOT2 = join40(".tmp", "context-runtime", "extract", "candidates");
81531
- var REVIEW_ACTION_ROOT2 = join40(".tmp", "context-runtime", "review-actions");
81681
+ var SNAPSHOT_ROOT2 = join41(".tmp", "context-runtime", "extract", "candidates");
81682
+ var REVIEW_ACTION_ROOT2 = join41(".tmp", "context-runtime", "review-actions");
81532
81683
  var REVIEW_PAYLOAD_SCHEMA = "context.review.decisions.v1";
81533
- function isRecord16(value) {
81684
+ function isRecord17(value) {
81534
81685
  return value !== null && typeof value === "object" && !Array.isArray(value);
81535
81686
  }
81536
81687
  function assertCollection(value) {
@@ -81551,26 +81702,26 @@ function assertCollection(value) {
81551
81702
  }
81552
81703
  function snapshotPath2(projectRoot, candidateId) {
81553
81704
  assertSafeEntityId(candidateId);
81554
- return join40(projectRoot, SNAPSHOT_ROOT2, `${candidateId}.json`);
81705
+ return join41(projectRoot, SNAPSHOT_ROOT2, `${candidateId}.json`);
81555
81706
  }
81556
81707
  async function readCandidateSnapshot(projectRoot, candidateId) {
81557
81708
  const file = snapshotPath2(projectRoot, candidateId);
81558
- if (!existsSync25(file))
81709
+ if (!existsSync26(file))
81559
81710
  return;
81560
81711
  let parsed;
81561
81712
  try {
81562
81713
  parsed = JSON.parse(await readFile33(file, "utf8"));
81563
81714
  } catch (error) {
81564
81715
  const message = error instanceof Error ? error.message : String(error);
81565
- throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid JSON: ${join40(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81716
+ throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid JSON: ${join41(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81566
81717
  category: ErrorCategory.SchemaInvalid,
81567
81718
  candidate_id: candidateId,
81568
81719
  reason: message,
81569
81720
  next: "Rerun the extract phase before reviewing this candidate."
81570
81721
  });
81571
81722
  }
81572
- if (!isRecord16(parsed) || typeof parsed.candidate_id !== "string" || typeof parsed.markdown !== "string") {
81573
- throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid: ${join40(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81723
+ if (!isRecord17(parsed) || typeof parsed.candidate_id !== "string" || typeof parsed.markdown !== "string") {
81724
+ throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid: ${join41(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81574
81725
  category: ErrorCategory.SchemaInvalid,
81575
81726
  candidate_id: candidateId,
81576
81727
  next: "Rerun the extract phase before reviewing this candidate."
@@ -81601,15 +81752,15 @@ async function extractCandidateSnapshotIsCurrent(projectRoot, snapshot) {
81601
81752
  async function removeCandidateSnapshot2(projectRoot, candidateId) {
81602
81753
  const file = snapshotPath2(projectRoot, candidateId);
81603
81754
  await rm10(file, { force: true });
81604
- const snapshotRoot = join40(projectRoot, SNAPSHOT_ROOT2);
81605
- let current2 = dirname25(file);
81755
+ const snapshotRoot = join41(projectRoot, SNAPSHOT_ROOT2);
81756
+ let current2 = dirname26(file);
81606
81757
  while (current2 !== snapshotRoot && current2.startsWith(snapshotRoot)) {
81607
81758
  try {
81608
81759
  await rmdir2(current2);
81609
81760
  } catch {
81610
81761
  break;
81611
81762
  }
81612
- current2 = dirname25(current2);
81763
+ current2 = dirname26(current2);
81613
81764
  }
81614
81765
  }
81615
81766
  function parseCanonicalSourceRef(ref2) {
@@ -81730,11 +81881,11 @@ function findApprovedPageForViewRef(projectRoot, viewRef) {
81730
81881
  }
81731
81882
  const nodeRef = viewRef.slice(separator + 1);
81732
81883
  assertSafeEntityId(nodeRef);
81733
- const collectionRoot = join40(projectRoot, "knowledge", collection);
81734
- if (existsSync25(collectionRoot)) {
81884
+ const collectionRoot = join41(projectRoot, "knowledge", collection);
81885
+ if (existsSync26(collectionRoot)) {
81735
81886
  const visit3 = (dir, relDir) => {
81736
81887
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
81737
- const absPath = join40(dir, entry.name);
81888
+ const absPath = join41(dir, entry.name);
81738
81889
  const rel = relDir.length === 0 ? entry.name : `${relDir}/${entry.name}`;
81739
81890
  if (entry.isDirectory()) {
81740
81891
  const found2 = visit3(absPath, rel);
@@ -81744,16 +81895,16 @@ function findApprovedPageForViewRef(projectRoot, viewRef) {
81744
81895
  }
81745
81896
  if (!entry.isFile() || !entry.name.endsWith(".md"))
81746
81897
  continue;
81747
- const block = frontmatterBlock(readFileSync6(absPath, "utf8"));
81898
+ const block = frontmatterBlock(readFileSync7(absPath, "utf8"));
81748
81899
  if (block === null)
81749
81900
  continue;
81750
81901
  const parsed = import_yaml21.default.parse(block.yaml);
81751
- if (!isRecord16(parsed) || parsed.view_ref !== viewRef)
81902
+ if (!isRecord17(parsed) || parsed.view_ref !== viewRef)
81752
81903
  continue;
81753
81904
  const approvedNodeRef = typeof parsed.node_ref === "string" && parsed.node_ref.trim().length > 0 ? parsed.node_ref.trim() : nodeRef;
81754
81905
  return {
81755
81906
  path: absPath,
81756
- relPath: join40("knowledge", collection, rel),
81907
+ relPath: join41("knowledge", collection, rel),
81757
81908
  nodeRef: approvedNodeRef
81758
81909
  };
81759
81910
  }
@@ -81794,7 +81945,7 @@ function updateFrontmatter(content3, mutate) {
81794
81945
  });
81795
81946
  }
81796
81947
  const parsed = import_yaml21.default.parse(block.yaml);
81797
- if (!isRecord16(parsed)) {
81948
+ if (!isRecord17(parsed)) {
81798
81949
  throw new ContextError(ExitCode.WorkspaceStateError, "approved page frontmatter must be a YAML object", {
81799
81950
  category: ErrorCategory.SchemaInvalid
81800
81951
  });
@@ -81809,16 +81960,16 @@ function parseApprovedSources(content3) {
81809
81960
  if (block === null)
81810
81961
  return [];
81811
81962
  const parsed = import_yaml21.default.parse(block.yaml);
81812
- if (!isRecord16(parsed))
81963
+ if (!isRecord17(parsed))
81813
81964
  return [];
81814
81965
  const sources = parsed.sources;
81815
81966
  return Array.isArray(sources) ? sources.filter((source2) => typeof source2 === "string") : [];
81816
81967
  }
81817
81968
  async function writeReviewActionLog(input) {
81818
81969
  const stamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
81819
- const relPath = join40(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
81820
- const path4 = join40(input.projectRoot, relPath);
81821
- await mkdir21(dirname25(path4), { recursive: true });
81970
+ const relPath = join41(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
81971
+ const path4 = join41(input.projectRoot, relPath);
81972
+ await mkdir21(dirname26(path4), { recursive: true });
81822
81973
  await writeFile17(path4, `${JSON.stringify({
81823
81974
  action: input.action,
81824
81975
  id: input.id,
@@ -82313,7 +82464,7 @@ async function prepareApprovedPage(input) {
82313
82464
  if (input.record.candidate_type !== "prose-align") {
82314
82465
  assertSafeEntityId(input.record.node_ref);
82315
82466
  }
82316
- relPath = join41("knowledge", input.record.path);
82467
+ relPath = join42("knowledge", input.record.path);
82317
82468
  const existingView = findApprovedPageForViewRef(input.projectRoot, input.record.view_ref);
82318
82469
  if (existingView !== undefined && existingView.relPath !== relPath) {
82319
82470
  throw new ContextError(ExitCode.WorkspaceStateError, `approved page already exists for view_ref at a different path: ${input.record.view_ref}`, {
@@ -82325,8 +82476,8 @@ async function prepareApprovedPage(input) {
82325
82476
  next: "Resolve the approved page path migration explicitly before approving this candidate."
82326
82477
  });
82327
82478
  }
82328
- const absPath = join41(input.projectRoot, relPath);
82329
- const existing = existsSync26(absPath) ? await readFile34(absPath, "utf8") : undefined;
82479
+ const absPath = join42(input.projectRoot, relPath);
82480
+ const existing = existsSync27(absPath) ? await readFile34(absPath, "utf8") : undefined;
82330
82481
  if (existing !== undefined) {
82331
82482
  const frontmatter = parseFrontmatterLoose(existing);
82332
82483
  const existingViewRef = typeof frontmatter.view_ref === "string" ? frontmatter.view_ref : undefined;
@@ -82398,11 +82549,11 @@ async function prepareApprovedPage(input) {
82398
82549
  }
82399
82550
  async function writePreparedApprovedPage(page) {
82400
82551
  for (const asset of page.assets) {
82401
- await mkdir22(dirname26(asset.absPath), { recursive: true });
82552
+ await mkdir22(dirname27(asset.absPath), { recursive: true });
82402
82553
  await writeFile18(asset.absPath, asset.bytes);
82403
82554
  }
82404
82555
  if (page.changed) {
82405
- await mkdir22(dirname26(page.absPath), { recursive: true });
82556
+ await mkdir22(dirname27(page.absPath), { recursive: true });
82406
82557
  await writeFile18(page.absPath, page.content, "utf8");
82407
82558
  }
82408
82559
  }
@@ -82633,18 +82784,18 @@ init_errors();
82633
82784
  init_exitCode();
82634
82785
 
82635
82786
  // src/project/repoSources.ts
82636
- import { existsSync as existsSync29 } from "node:fs";
82787
+ import { existsSync as existsSync30 } from "node:fs";
82637
82788
  import { lstat, mkdir as mkdir23, readFile as readFile35, readlink, realpath as realpath2, rm as rm12, symlink } from "node:fs/promises";
82638
82789
  import { execFile as execFile4 } from "node:child_process";
82639
82790
  import { promisify as promisify4 } from "node:util";
82640
- import { dirname as dirname27, isAbsolute as isAbsolute8, join as join44, relative as relative15, resolve as resolve17 } from "node:path";
82791
+ import { dirname as dirname28, isAbsolute as isAbsolute8, join as join45, relative as relative15, resolve as resolve17 } from "node:path";
82641
82792
  init_cliFeedback();
82642
82793
  init_errors();
82643
82794
  init_exitCode();
82644
82795
 
82645
82796
  // src/project/repoSourceModules.ts
82646
- import { existsSync as existsSync27 } from "node:fs";
82647
- import { join as join42, resolve as resolve16 } from "node:path";
82797
+ import { existsSync as existsSync28 } from "node:fs";
82798
+ import { join as join43, resolve as resolve16 } from "node:path";
82648
82799
  function normalizeSubpath(value) {
82649
82800
  if (value === undefined)
82650
82801
  return;
@@ -82671,8 +82822,8 @@ function suggestedModuleName(module) {
82671
82822
  return slug || "module";
82672
82823
  }
82673
82824
  async function inspectRepoSourceModules(input) {
82674
- const inspectPath = input.scopedAbs !== null && existsSync27(input.scopedAbs) ? input.scopedAbs : join42(input.projectRoot, input.status.materializedAt);
82675
- const modules = existsSync27(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
82825
+ const inspectPath = input.scopedAbs !== null && existsSync28(input.scopedAbs) ? input.scopedAbs : join43(input.projectRoot, input.status.materializedAt);
82826
+ const modules = existsSync28(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
82676
82827
  const recommended_sources = modules.filter((module) => module.path !== "." || modules.length === 1).map((module) => {
82677
82828
  const local = sourceModuleLocalForDisplay({ source: input.source, status: input.status, module });
82678
82829
  return {
@@ -82703,8 +82854,8 @@ function resolveRepoSourceScopedPath(localAbs, subpath) {
82703
82854
 
82704
82855
  // src/project/repoSourceRegistry.ts
82705
82856
  var import_yaml24 = __toESM(require_dist3(), 1);
82706
- import { existsSync as existsSync28 } from "node:fs";
82707
- import { join as join43 } from "node:path";
82857
+ import { existsSync as existsSync29 } from "node:fs";
82858
+ import { join as join44 } from "node:path";
82708
82859
  init_cliFeedback();
82709
82860
  init_errors();
82710
82861
  init_exitCode();
@@ -82761,14 +82912,14 @@ function registryEntryToRecord(entry) {
82761
82912
  };
82762
82913
  }
82763
82914
  function registryPath(projectRoot) {
82764
- return join43(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
82915
+ return join44(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
82765
82916
  }
82766
82917
  function defaultRepoMaterializedAt(source2) {
82767
82918
  return `sources/repo/${source2.namespace}/${source2.module}`;
82768
82919
  }
82769
82920
  async function readRepoRegistry(projectRoot) {
82770
82921
  const path4 = registryPath(projectRoot);
82771
- if (!existsSync28(path4))
82922
+ if (!existsSync29(path4))
82772
82923
  return { repos: [] };
82773
82924
  const registry2 = await loadSourcesRegistry({ rootDir: projectRoot });
82774
82925
  return {
@@ -82844,13 +82995,13 @@ async function gitOutput(cwd, args) {
82844
82995
  }
82845
82996
  }
82846
82997
  async function readGitOriginRemote(cwd) {
82847
- const directConfigPath = join44(cwd, ".git", "config");
82998
+ const directConfigPath = join45(cwd, ".git", "config");
82848
82999
  let config = await readFile35(directConfigPath, "utf8").catch(() => "");
82849
83000
  if (config.length === 0) {
82850
83001
  const gitDir = await resolveGitDir(cwd);
82851
83002
  if (gitDir === null)
82852
83003
  return null;
82853
- config = await readFile35(join44(gitDir, "config"), "utf8").catch(() => "");
83004
+ config = await readFile35(join45(gitDir, "config"), "utf8").catch(() => "");
82854
83005
  }
82855
83006
  let inOriginBlock = false;
82856
83007
  for (const line of config.split(/\r?\n/u)) {
@@ -82870,17 +83021,17 @@ async function readGitOriginRemote(cwd) {
82870
83021
  async function resolveGitRoot(cwd) {
82871
83022
  let current2 = resolve17(cwd);
82872
83023
  while (true) {
82873
- if (existsSync29(join44(current2, ".git")))
83024
+ if (existsSync30(join45(current2, ".git")))
82874
83025
  return current2;
82875
- const parent = dirname27(current2);
83026
+ const parent = dirname28(current2);
82876
83027
  if (parent === current2)
82877
83028
  return null;
82878
83029
  current2 = parent;
82879
83030
  }
82880
83031
  }
82881
83032
  async function resolveGitDir(cwd) {
82882
- const dotGit = join44(cwd, ".git");
82883
- if (!existsSync29(dotGit))
83033
+ const dotGit = join45(cwd, ".git");
83034
+ if (!existsSync30(dotGit))
82884
83035
  return null;
82885
83036
  const stats = await lstat(dotGit);
82886
83037
  if (stats.isDirectory())
@@ -82897,17 +83048,17 @@ async function readGitHead(cwd) {
82897
83048
  const gitDir = await resolveGitDir(cwd);
82898
83049
  if (gitDir === null)
82899
83050
  return null;
82900
- const headRaw = (await readFile35(join44(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
83051
+ const headRaw = (await readFile35(join45(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
82901
83052
  if (/^[a-f0-9]{40}$/iu.test(headRaw))
82902
83053
  return headRaw.toLowerCase();
82903
83054
  const match = /^ref:\s*(.+)\s*$/iu.exec(headRaw);
82904
83055
  const refPath = match?.[1];
82905
83056
  if (refPath === undefined)
82906
83057
  return null;
82907
- const looseRef = (await readFile35(join44(gitDir, refPath), "utf8").catch(() => "")).trim();
83058
+ const looseRef = (await readFile35(join45(gitDir, refPath), "utf8").catch(() => "")).trim();
82908
83059
  if (/^[a-f0-9]{40}$/iu.test(looseRef))
82909
83060
  return looseRef.toLowerCase();
82910
- const packedRefs = await readFile35(join44(gitDir, "packed-refs"), "utf8").catch(() => "");
83061
+ const packedRefs = await readFile35(join45(gitDir, "packed-refs"), "utf8").catch(() => "");
82911
83062
  for (const line of packedRefs.split(/\r?\n/u)) {
82912
83063
  if (line.startsWith("#") || line.startsWith("^"))
82913
83064
  continue;
@@ -82918,27 +83069,27 @@ async function readGitHead(cwd) {
82918
83069
  return null;
82919
83070
  }
82920
83071
  async function ensureMaterializedSymlink(input) {
82921
- const linkPath = join44(input.projectRoot, input.materializedAt);
82922
- await mkdir23(dirname27(linkPath), { recursive: true });
82923
- if (existsSync29(linkPath)) {
83072
+ const linkPath = join45(input.projectRoot, input.materializedAt);
83073
+ await mkdir23(dirname28(linkPath), { recursive: true });
83074
+ if (existsSync30(linkPath)) {
82924
83075
  const stats = await lstat(linkPath);
82925
83076
  if (!stats.isSymbolicLink()) {
82926
83077
  input.diagnostics.push(`materialized path exists and is not a symlink: ${input.materializedAt}`);
82927
83078
  return false;
82928
83079
  }
82929
83080
  const current2 = await readlink(linkPath);
82930
- const currentAbs = resolve17(dirname27(linkPath), current2);
83081
+ const currentAbs = resolve17(dirname28(linkPath), current2);
82931
83082
  if (currentAbs === input.localAbs)
82932
83083
  return true;
82933
83084
  await rm12(linkPath);
82934
83085
  }
82935
- const relTarget = relative15(dirname27(linkPath), input.localAbs) || ".";
83086
+ const relTarget = relative15(dirname28(linkPath), input.localAbs) || ".";
82936
83087
  await symlink(relTarget, linkPath);
82937
83088
  return true;
82938
83089
  }
82939
83090
  async function diagnoseMaterializedSymlink(input) {
82940
- const linkPath = join44(input.projectRoot, input.materializedAt);
82941
- if (!existsSync29(linkPath)) {
83091
+ const linkPath = join45(input.projectRoot, input.materializedAt);
83092
+ if (!existsSync30(linkPath)) {
82942
83093
  input.diagnostics.push(`materialized path is missing: ${input.materializedAt}`);
82943
83094
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to materialize the local source link.`);
82944
83095
  return false;
@@ -82949,9 +83100,9 @@ async function diagnoseMaterializedSymlink(input) {
82949
83100
  return false;
82950
83101
  }
82951
83102
  const current2 = await readlink(linkPath);
82952
- const currentAbs = resolve17(dirname27(linkPath), current2);
83103
+ const currentAbs = resolve17(dirname28(linkPath), current2);
82953
83104
  if (currentAbs !== input.localAbs) {
82954
- input.diagnostics.push(`materialized path points to ${current2}, expected local checkout ${relative15(dirname27(linkPath), input.localAbs) || "."}`);
83105
+ input.diagnostics.push(`materialized path points to ${current2}, expected local checkout ${relative15(dirname28(linkPath), input.localAbs) || "."}`);
82955
83106
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to refresh the local source link.`);
82956
83107
  return false;
82957
83108
  }
@@ -82983,7 +83134,7 @@ async function normalizeInputRef(input) {
82983
83134
  next: "Pass --local <path> with a git checkout, or use a full 40-character commit sha."
82984
83135
  });
82985
83136
  }
82986
- if (!existsSync29(localAbs)) {
83137
+ if (!existsSync30(localAbs)) {
82987
83138
  throw new ContextError(ExitCode.UserError, `short repo source ref cannot be resolved because local path is missing: ${input.local}`, {
82988
83139
  category: ErrorCategory.UserInputInvalid,
82989
83140
  sourceName: input.sourceName,
@@ -83035,7 +83186,7 @@ async function normalizeAddInput(input, existing) {
83035
83186
  let gitRootAbs = null;
83036
83187
  if (originalLocal !== undefined) {
83037
83188
  const originalLocalAbs = resolveLocalPath(input.projectRoot, originalLocal);
83038
- if (originalLocalAbs !== null && existsSync29(originalLocalAbs)) {
83189
+ if (originalLocalAbs !== null && existsSync30(originalLocalAbs)) {
83039
83190
  gitRootAbs = await resolveGitRoot(originalLocalAbs);
83040
83191
  if (gitRootAbs !== null && input.local !== undefined) {
83041
83192
  const detectedSubpath = normalizeSubpath2(relative15(gitRootAbs, originalLocalAbs));
@@ -83131,11 +83282,11 @@ async function inspectRepoSource(input) {
83131
83282
  const diagnostics = [];
83132
83283
  const agent_hints = [];
83133
83284
  const localAbs = resolveLocalPath(input.projectRoot, source2.local);
83134
- const localExists = localAbs !== null && existsSync29(localAbs);
83285
+ const localExists = localAbs !== null && existsSync30(localAbs);
83135
83286
  const subpath = normalizeSubpath2(source2.subpath);
83136
83287
  const scopedAbs = localAbs === null ? null : scopedLocalPath(localAbs, subpath);
83137
- const scopeExists = scopedAbs !== null && existsSync29(scopedAbs);
83138
- let materialized = existsSync29(join44(input.projectRoot, materializedAt));
83288
+ const scopeExists = scopedAbs !== null && existsSync30(scopedAbs);
83289
+ let materialized = existsSync30(join45(input.projectRoot, materializedAt));
83139
83290
  const checkout = await inspectRepoCheckout({
83140
83291
  source: source2,
83141
83292
  localAbs,
@@ -83784,24 +83935,24 @@ The approved symbol is no longer present in the current code extraction.
83784
83935
  // src/project/packageBuilder.ts
83785
83936
  init_cliFeedback();
83786
83937
  init_errors();
83787
- init_exitCode();
83788
83938
  var import_yaml28 = __toESM(require_dist3(), 1);
83789
83939
  import { createHash as createHash20 } from "node:crypto";
83790
- import { existsSync as existsSync34 } from "node:fs";
83940
+ import { existsSync as existsSync35 } from "node:fs";
83791
83941
  import { mkdir as mkdir27, readdir as readdir15, readFile as readFile41, rm as rm13, writeFile as writeFile22 } from "node:fs/promises";
83792
- import { dirname as dirname33, join as join51, resolve as resolve19 } from "node:path";
83942
+ import { dirname as dirname34, join as join52, resolve as resolve19 } from "node:path";
83943
+ init_exitCode();
83793
83944
 
83794
83945
  // src/project/packageBuildInventory.ts
83795
83946
  var import_yaml26 = __toESM(require_dist3(), 1);
83796
83947
  import { createHash as createHash17 } from "node:crypto";
83797
- import { existsSync as existsSync31 } from "node:fs";
83948
+ import { existsSync as existsSync32 } from "node:fs";
83798
83949
  import { mkdir as mkdir25, readFile as readFile37, writeFile as writeFile20 } from "node:fs/promises";
83799
- import { dirname as dirname29, join as join46 } from "node:path";
83950
+ import { dirname as dirname30, join as join47 } from "node:path";
83800
83951
 
83801
83952
  // src/project/packageIndexes.ts
83802
- import { existsSync as existsSync30, statSync } from "node:fs";
83953
+ import { existsSync as existsSync31, statSync } from "node:fs";
83803
83954
  import { mkdir as mkdir24, readdir as readdir13, readFile as readFile36, writeFile as writeFile19 } from "node:fs/promises";
83804
- import { dirname as dirname28, join as join45, posix as pathPosix, relative as relative16 } from "node:path";
83955
+ import { dirname as dirname29, join as join46, posix as pathPosix, relative as relative16 } from "node:path";
83805
83956
  init_cliFeedback();
83806
83957
  init_errors();
83807
83958
  init_exitCode();
@@ -83955,7 +84106,7 @@ var PACKAGE_INVENTORY_FIELDS = [
83955
84106
  "candidate_fingerprint"
83956
84107
  ];
83957
84108
  var COMPILER_ONLY_TAGS = new Set(["docs", "prose", "parent-index"]);
83958
- function isRecord17(value) {
84109
+ function isRecord18(value) {
83959
84110
  return value !== null && typeof value === "object" && !Array.isArray(value);
83960
84111
  }
83961
84112
  function stringList2(value) {
@@ -83969,7 +84120,7 @@ function parseKnowledgeFrontmatter(content3) {
83969
84120
  return {};
83970
84121
  try {
83971
84122
  const parsed = import_yaml25.parse(match[1]);
83972
- return isRecord17(parsed) ? parsed : {};
84123
+ return isRecord18(parsed) ? parsed : {};
83973
84124
  } catch {
83974
84125
  return {};
83975
84126
  }
@@ -84064,13 +84215,13 @@ function packageKind(pkg) {
84064
84215
  return pkg.kind === "package.kb" ? "kb" : "llms";
84065
84216
  }
84066
84217
  async function walkFiles3(root2) {
84067
- if (!existsSync30(root2))
84218
+ if (!existsSync31(root2))
84068
84219
  return [];
84069
84220
  const files = [];
84070
84221
  const visit3 = async (dir) => {
84071
84222
  const entries = await readdir13(dir, { withFileTypes: true });
84072
84223
  for (const entry of entries) {
84073
- const absPath = join45(dir, entry.name);
84224
+ const absPath = join46(dir, entry.name);
84074
84225
  if (entry.isDirectory()) {
84075
84226
  await visit3(absPath);
84076
84227
  continue;
@@ -84362,10 +84513,10 @@ async function writeKnowledgeDirectoryIndexes(input) {
84362
84513
  let written = 0;
84363
84514
  for (const directory of collectKnowledgeDirectoryIndexes(input.pkg, input.selected)) {
84364
84515
  assertSafeRenderedPath(directory.relPath, "knowledge directory index path");
84365
- const outputPath = join45(input.projectRoot, input.pkg.outDir, directory.relPath);
84366
- if (existsSync30(outputPath))
84516
+ const outputPath = join46(input.projectRoot, input.pkg.outDir, directory.relPath);
84517
+ if (existsSync31(outputPath))
84367
84518
  continue;
84368
- await mkdir24(dirname28(outputPath), { recursive: true });
84519
+ await mkdir24(dirname29(outputPath), { recursive: true });
84369
84520
  await writeFile19(outputPath, renderKnowledgeDirectoryIndex({
84370
84521
  pkg: input.pkg,
84371
84522
  directory,
@@ -84411,23 +84562,23 @@ function packageLinkTargetExists(packageRoot, targetRelPath) {
84411
84562
  return false;
84412
84563
  }
84413
84564
  const normalized = targetRelPath.endsWith("/") ? `${targetRelPath}index.md` : targetRelPath;
84414
- const targetPath = join45(packageRoot, normalized);
84415
- if (existsSync30(targetPath)) {
84565
+ const targetPath = join46(packageRoot, normalized);
84566
+ if (existsSync31(targetPath)) {
84416
84567
  const stat6 = statSync(targetPath);
84417
84568
  if (stat6.isFile())
84418
84569
  return true;
84419
84570
  if (stat6.isDirectory())
84420
- return existsSync30(join45(targetPath, "index.md"));
84571
+ return existsSync31(join46(targetPath, "index.md"));
84421
84572
  return false;
84422
84573
  }
84423
- if (!pathPosix.extname(normalized) && existsSync30(join45(packageRoot, normalized, "index.md")))
84574
+ if (!pathPosix.extname(normalized) && existsSync31(join46(packageRoot, normalized, "index.md")))
84424
84575
  return true;
84425
84576
  return false;
84426
84577
  }
84427
84578
  async function validatePackageIndexLinks(input) {
84428
84579
  if (packageKind(input.pkg) !== "kb")
84429
84580
  return;
84430
- const packageRoot = join45(input.projectRoot, input.pkg.outDir);
84581
+ const packageRoot = join46(input.projectRoot, input.pkg.outDir);
84431
84582
  const files = await walkFiles3(packageRoot);
84432
84583
  for (const file of files) {
84433
84584
  if (file.relPath !== "index.md" && !file.relPath.endsWith("/index.md"))
@@ -84498,10 +84649,10 @@ function packageKind2(pkg) {
84498
84649
  // src/project/packageBuildInventory.ts
84499
84650
  var PACKAGE_BUILD_INVENTORY_PATH = "context-build-inventory.json";
84500
84651
  function knowledgeStructurePath(projectRoot) {
84501
- return join46(projectRoot, "knowledge", "structure.yaml");
84652
+ return join47(projectRoot, "knowledge", "structure.yaml");
84502
84653
  }
84503
84654
  async function readOptionalText(path4) {
84504
- if (!existsSync31(path4))
84655
+ if (!existsSync32(path4))
84505
84656
  return null;
84506
84657
  return readFile37(path4, "utf8");
84507
84658
  }
@@ -84880,8 +85031,8 @@ function packageBuildInventory(input) {
84880
85031
  };
84881
85032
  }
84882
85033
  async function writePackageBuildInventory(input) {
84883
- const outputPath = join46(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
84884
- await mkdir25(dirname29(outputPath), { recursive: true });
85034
+ const outputPath = join47(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
85035
+ await mkdir25(dirname30(outputPath), { recursive: true });
84885
85036
  await writeFile20(outputPath, `${JSON.stringify(input.inventory, null, 2)}
84886
85037
  `, "utf8");
84887
85038
  return 1;
@@ -84889,12 +85040,12 @@ async function writePackageBuildInventory(input) {
84889
85040
 
84890
85041
  // src/project/packageBuildReceipt.ts
84891
85042
  import { createHash as createHash18 } from "node:crypto";
84892
- import { existsSync as existsSync32 } from "node:fs";
85043
+ import { existsSync as existsSync33 } from "node:fs";
84893
85044
  import { readdir as readdir14, readFile as readFile38 } from "node:fs/promises";
84894
- import { join as join47, relative as relative17 } from "node:path";
85045
+ import { join as join48, relative as relative17 } from "node:path";
84895
85046
  var IGNORED_PACKAGE_FS_ENTRIES = new Set([".DS_Store"]);
84896
85047
  async function walkPackageFiles(root2) {
84897
- if (!existsSync32(root2))
85048
+ if (!existsSync33(root2))
84898
85049
  return [];
84899
85050
  const files = [];
84900
85051
  const visit3 = async (dir) => {
@@ -84902,7 +85053,7 @@ async function walkPackageFiles(root2) {
84902
85053
  for (const entry of entries) {
84903
85054
  if (IGNORED_PACKAGE_FS_ENTRIES.has(entry.name))
84904
85055
  continue;
84905
- const absPath = join47(dir, entry.name);
85056
+ const absPath = join48(dir, entry.name);
84906
85057
  if (entry.isDirectory()) {
84907
85058
  await visit3(absPath);
84908
85059
  continue;
@@ -84933,7 +85084,7 @@ function classifyOutputFile(path4, knowledgeGroups) {
84933
85084
  }
84934
85085
  async function packageOutputSnapshot(projectRoot, pkg, knowledgeGroups, previousOutputs = []) {
84935
85086
  const previousByPath = new Map(previousOutputs.map((file) => [file.path, file]));
84936
- return Promise.all((await walkPackageFiles(join47(projectRoot, pkg.outDir))).map(async (file) => {
85087
+ return Promise.all((await walkPackageFiles(join48(projectRoot, pkg.outDir))).map(async (file) => {
84937
85088
  const current2 = classifyOutputFile(file.relPath, knowledgeGroups);
84938
85089
  const previous3 = previousByPath.get(file.relPath);
84939
85090
  const classification = current2.kind === "file" && previous3 !== undefined ? { path: file.relPath, kind: previous3.kind, ...previous3.group === undefined ? {} : { group: previous3.group } } : current2;
@@ -84947,7 +85098,7 @@ async function packageOutputFingerprint(projectRoot, pkg) {
84947
85098
  const snapshot = await packageOutputSnapshot(projectRoot, pkg, new Map);
84948
85099
  return {
84949
85100
  fingerprint: createHash18("sha256").update(JSON.stringify({
84950
- outDirExists: existsSync32(join47(projectRoot, pkg.outDir)),
85101
+ outDirExists: existsSync33(join48(projectRoot, pkg.outDir)),
84951
85102
  files: snapshot.map(({ path: path4, sha256: sha2564 }) => ({ path: path4, sha256: sha2564 }))
84952
85103
  })).digest("hex"),
84953
85104
  files: snapshot.length
@@ -85021,16 +85172,16 @@ function formatPackageBuildSummary(pkg) {
85021
85172
  }
85022
85173
 
85023
85174
  // src/project/packageBuildContent.ts
85024
- import { existsSync as existsSync33 } from "node:fs";
85175
+ import { existsSync as existsSync34 } from "node:fs";
85025
85176
  import { mkdir as mkdir26, readFile as readFile40, writeFile as writeFile21 } from "node:fs/promises";
85026
- import { dirname as dirname32, join as join50 } from "node:path";
85177
+ import { dirname as dirname33, join as join51 } from "node:path";
85027
85178
 
85028
85179
  // src/project/packageAssets.ts
85029
85180
  init_errors();
85030
85181
  init_cliFeedback();
85031
85182
  init_exitCode();
85032
85183
  import { readFile as readFile39 } from "node:fs/promises";
85033
- import { dirname as dirname30, relative as relative18, sep as sep3 } from "node:path";
85184
+ import { dirname as dirname31, relative as relative18, sep as sep3 } from "node:path";
85034
85185
  function posixPath2(value) {
85035
85186
  return value.split(sep3).join("/");
85036
85187
  }
@@ -85052,7 +85203,7 @@ function packageAssetPath(projectRoot, absolute) {
85052
85203
  };
85053
85204
  }
85054
85205
  function packageMarkdownTarget(pageOutputPath, assetOutputPath) {
85055
- const target = posixPath2(relative18(dirname30(pageOutputPath), assetOutputPath));
85206
+ const target = posixPath2(relative18(dirname31(pageOutputPath), assetOutputPath));
85056
85207
  return target.startsWith(".") ? target : `./${target}`;
85057
85208
  }
85058
85209
  async function projectPackageKnowledgeAssets(input) {
@@ -85092,7 +85243,7 @@ init_errors();
85092
85243
  init_exitCode();
85093
85244
  import { execFile as execFile5 } from "node:child_process";
85094
85245
  import { realpath as realpath3 } from "node:fs/promises";
85095
- import { join as join49, relative as relative19, sep as sep4 } from "node:path";
85246
+ import { join as join50, relative as relative19, sep as sep4 } from "node:path";
85096
85247
  import { promisify as promisify5 } from "node:util";
85097
85248
 
85098
85249
  // src/project/packageAssetOptimization.ts
@@ -85101,7 +85252,7 @@ init_errors();
85101
85252
  init_exitCode();
85102
85253
  import { createHash as createHash19 } from "node:crypto";
85103
85254
  import { createRequire as createRequire4 } from "node:module";
85104
- import { dirname as dirname31, extname as extname10, join as join48 } from "node:path";
85255
+ import { dirname as dirname32, extname as extname10, join as join49 } from "node:path";
85105
85256
  import { pathToFileURL as pathToFileURL2 } from "node:url";
85106
85257
  var PACKAGE_ASSET_OPTIMIZATION_THRESHOLD_BYTES = 20 * 1024 * 1024;
85107
85258
  function isPng(bytes) {
@@ -85123,10 +85274,10 @@ function isWebp(bytes) {
85123
85274
  }
85124
85275
  function contentAddressedWebpPath(asset, bytes) {
85125
85276
  const digest4 = createHash19("sha256").update(bytes).digest("hex");
85126
- return `${dirname31(asset.packageRelPath)}/${digest4}.webp`;
85277
+ return `${dirname32(asset.packageRelPath)}/${digest4}.webp`;
85127
85278
  }
85128
85279
  async function loadSharpProcessor(projectRoot) {
85129
- const requireFromWorkspace = createRequire4(join48(projectRoot, "package.json"));
85280
+ const requireFromWorkspace = createRequire4(join49(projectRoot, "package.json"));
85130
85281
  let resolved;
85131
85282
  try {
85132
85283
  resolved = requireFromWorkspace.resolve("sharp");
@@ -85246,7 +85397,7 @@ async function git(projectRoot, args) {
85246
85397
  }
85247
85398
  }
85248
85399
  function repositoryPath(repoRoot, projectRoot, asset) {
85249
- const path4 = relative19(repoRoot, join49(projectRoot, asset.knowledgeRelPath)).split(sep4).join("/");
85400
+ const path4 = relative19(repoRoot, join50(projectRoot, asset.knowledgeRelPath)).split(sep4).join("/");
85250
85401
  if (path4 === ".." || path4.startsWith("../") || path4.startsWith("/")) {
85251
85402
  throw new ContextError(ExitCode.WorkspaceStateError, "knowledge asset is outside the current Git repository", {
85252
85403
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -85553,8 +85704,8 @@ async function writeRenderedPackageTemplate(input) {
85553
85704
  templateRelPath: renderedRelPath,
85554
85705
  logicalTemplateRelPath: renderedLogicalRelPath
85555
85706
  });
85556
- const outputPath = join50(input.projectRoot, input.pkg.outDir, renderedRelPath);
85557
- await mkdir26(dirname32(outputPath), { recursive: true });
85707
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, renderedRelPath);
85708
+ await mkdir26(dirname33(outputPath), { recursive: true });
85558
85709
  await writeFile21(outputPath, renderTemplateText(file.content, contentVars), "utf8");
85559
85710
  written++;
85560
85711
  }
@@ -85580,7 +85731,7 @@ async function writeSelectedPackageKnowledge(input) {
85580
85731
  const { projectedPages, delivered } = input.prepared ?? await prepareSelectedPackageKnowledge(input);
85581
85732
  for (const projected of projectedPages) {
85582
85733
  assertSafeRenderedPath2(projected.pageOutputPath, "knowledge path");
85583
- const outputPath = join50(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
85734
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
85584
85735
  const rewritten = replaceMarkdownInlineLinkTargets(projected.content, (link2) => {
85585
85736
  for (const [inputPath, outputPath2] of delivered.targetByOriginal) {
85586
85737
  if (link2.target === packageMarkdownTarget(projected.pageOutputPath, inputPath)) {
@@ -85589,14 +85740,14 @@ async function writeSelectedPackageKnowledge(input) {
85589
85740
  }
85590
85741
  return;
85591
85742
  });
85592
- await mkdir26(dirname32(outputPath), { recursive: true });
85743
+ await mkdir26(dirname33(outputPath), { recursive: true });
85593
85744
  await writeFile21(outputPath, projectPackageKnowledgeMarkdown(rewritten), "utf8");
85594
85745
  }
85595
85746
  const deliveredAssets = new Map(delivered.assets.map((asset) => [asset.packageRelPath, asset]));
85596
85747
  for (const asset of deliveredAssets.values()) {
85597
85748
  assertSafeRenderedPath2(asset.packageRelPath, "package resource path");
85598
- const outputPath = join50(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
85599
- await mkdir26(dirname32(outputPath), { recursive: true });
85749
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
85750
+ await mkdir26(dirname33(outputPath), { recursive: true });
85600
85751
  await writeFile21(outputPath, asset.bytes);
85601
85752
  }
85602
85753
  return {
@@ -85609,8 +85760,8 @@ async function writeSelectedPackageKnowledge(input) {
85609
85760
  async function appendLlmsKnowledge(input) {
85610
85761
  if (packageKind2(input.pkg) !== "llms" || input.templateConsumesKnowledge || input.knowledgeCount === 0)
85611
85762
  return 0;
85612
- const outputPath = join50(input.projectRoot, input.pkg.outDir, "llms.txt");
85613
- const existed = existsSync33(outputPath);
85763
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, "llms.txt");
85764
+ const existed = existsSync34(outputPath);
85614
85765
  const existing = existed ? await readFile40(outputPath, "utf8") : "";
85615
85766
  const content3 = existing.trim().length > 0 ? `${existing.trimEnd()}
85616
85767
 
@@ -85619,7 +85770,7 @@ async function appendLlmsKnowledge(input) {
85619
85770
  ${input.bundle}
85620
85771
  ` : `${input.bundle}
85621
85772
  `;
85622
- await mkdir26(dirname32(outputPath), { recursive: true });
85773
+ await mkdir26(dirname33(outputPath), { recursive: true });
85623
85774
  await writeFile21(outputPath, content3, "utf8");
85624
85775
  return existed ? 0 : 1;
85625
85776
  }
@@ -85805,7 +85956,7 @@ function validateRenderedSkillDefinition(input) {
85805
85956
  init_workspace();
85806
85957
  init_packageTemplateReview();
85807
85958
  var KNOWLEDGE_ROOT4 = "knowledge";
85808
- var PACKAGE_FINGERPRINT_ROOT = join51(".tmp", "context-runtime", "packages");
85959
+ var PACKAGE_FINGERPRINT_ROOT = join52(".tmp", "context-runtime", "packages");
85809
85960
  var PACKAGE_BUILDER_PROTOCOL_VERSION = "v14-git-asset-identity";
85810
85961
  function packageAssetDeliverySummary(value) {
85811
85962
  if (value === null || typeof value !== "object" || Array.isArray(value))
@@ -85828,10 +85979,10 @@ function assertPackageOutputDir(pkg) {
85828
85979
  }
85829
85980
  function packageFingerprintPath(projectRoot, pkg) {
85830
85981
  assertSafeRenderedPath2(`${pkg.name}.json`, "package fingerprint path");
85831
- return join51(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
85982
+ return join52(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
85832
85983
  }
85833
85984
  async function listApprovedKnowledge(projectRoot) {
85834
- const files = await walkPackageFiles(join51(projectRoot, KNOWLEDGE_ROOT4));
85985
+ const files = await walkPackageFiles(join52(projectRoot, KNOWLEDGE_ROOT4));
85835
85986
  const knowledge = await Promise.all(files.filter((file) => file.relPath.endsWith(".md") && !file.relPath.startsWith("assets/")).map(async (file) => ({
85836
85987
  ...file,
85837
85988
  content: await readFile41(file.absPath, "utf8")
@@ -85852,7 +86003,7 @@ function isDeprecatedKnowledge(content3) {
85852
86003
  async function listTemplateFiles(projectRoot, templatePath) {
85853
86004
  assertSafeRenderedPath2(templatePath, "package template path");
85854
86005
  const templateRoot = resolve19(projectRoot, templatePath);
85855
- if (!existsSync34(templateRoot)) {
86006
+ if (!existsSync35(templateRoot)) {
85856
86007
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${templatePath}`, {
85857
86008
  category: ErrorCategory.WorkspaceStateInvalid,
85858
86009
  path: templatePath,
@@ -85914,7 +86065,7 @@ async function packageInputFingerprint(input) {
85914
86065
  }
85915
86066
  async function readPackageManifest(projectRoot, pkg) {
85916
86067
  const filePath = packageFingerprintPath(projectRoot, pkg);
85917
- if (!existsSync34(filePath))
86068
+ if (!existsSync35(filePath))
85918
86069
  return null;
85919
86070
  try {
85920
86071
  const parsed = JSON.parse(await readFile41(filePath, "utf8"));
@@ -85947,7 +86098,7 @@ async function readPackageManifest(projectRoot, pkg) {
85947
86098
  }
85948
86099
  async function writePackageFingerprint(input) {
85949
86100
  const filePath = packageFingerprintPath(input.projectRoot, input.pkg);
85950
- await mkdir27(dirname33(filePath), { recursive: true });
86101
+ await mkdir27(dirname34(filePath), { recursive: true });
85951
86102
  await writeFile22(filePath, `${JSON.stringify({
85952
86103
  package: input.pkg.name,
85953
86104
  kind: packageKind2(input.pkg),
@@ -85962,12 +86113,12 @@ async function writePackageFingerprint(input) {
85962
86113
  `, "utf8");
85963
86114
  }
85964
86115
  async function removeOrphanPackageDirs(projectRoot, packages) {
85965
- const distRoot = join51(projectRoot, "dist");
85966
- if (!existsSync34(distRoot))
86116
+ const distRoot = join52(projectRoot, "dist");
86117
+ if (!existsSync35(distRoot))
85967
86118
  return;
85968
86119
  const declaredNames = new Set(packages.map((pkg) => pkg.name));
85969
86120
  const entries = await readdir15(distRoot, { withFileTypes: true });
85970
- await Promise.all(entries.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm13(join51(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
86121
+ await Promise.all(entries.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm13(join52(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
85971
86122
  }
85972
86123
  async function collectPackageFreshness(projectRoot, packages) {
85973
86124
  const approved = await listApprovedKnowledge(projectRoot);
@@ -85975,8 +86126,8 @@ async function collectPackageFreshness(projectRoot, packages) {
85975
86126
  assertPackageOutputDir(pkg);
85976
86127
  const selected = selectPackageKnowledge(approved, pkg);
85977
86128
  assertSafeRenderedPath2(pkg.template.path, "package template path");
85978
- const templateRoot = join51(projectRoot, pkg.template.path);
85979
- const templateExists = existsSync34(templateRoot);
86129
+ const templateRoot = join52(projectRoot, pkg.template.path);
86130
+ const templateExists = existsSync35(templateRoot);
85980
86131
  if (!templateExists) {
85981
86132
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${pkg.template.path}`, {
85982
86133
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -86110,8 +86261,8 @@ async function buildProjectPackages(projectRoot) {
86110
86261
  files: selected,
86111
86262
  ...assetProcessor === undefined ? {} : { assetProcessor }
86112
86263
  });
86113
- await rm13(join51(projectRoot, pkg.outDir), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
86114
- await mkdir27(join51(projectRoot, pkg.outDir), { recursive: true });
86264
+ await rm13(join52(projectRoot, pkg.outDir), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
86265
+ await mkdir27(join52(projectRoot, pkg.outDir), { recursive: true });
86115
86266
  const rendered = await writeRenderedPackageTemplate({
86116
86267
  projectRoot,
86117
86268
  pkg,
@@ -86249,20 +86400,32 @@ async function runProjectBuildCommand(input) {
86249
86400
  return false;
86250
86401
  const result = await buildProjectPackages(found.projectRoot);
86251
86402
  process.stdout.write(formatProjectBuildResult(result, input.format ?? "text", input.verbose === true));
86403
+ queueContextRuntimeEvent({
86404
+ cwd: result.projectRoot,
86405
+ kind: "package.build.completed",
86406
+ properties: {
86407
+ package_count: result.packages.length,
86408
+ created_count: result.packages.filter((pkg) => pkg.state === "created").length,
86409
+ updated_count: result.packages.filter((pkg) => pkg.state === "updated").length,
86410
+ unchanged_count: result.packages.filter((pkg) => pkg.state === "unchanged").length,
86411
+ output_file_count: result.packages.reduce((total, pkg) => total + pkg.files, 0),
86412
+ resource_file_count: result.packages.reduce((total, pkg) => total + pkg.resources.files, 0)
86413
+ }
86414
+ });
86252
86415
  return true;
86253
86416
  }
86254
86417
 
86255
86418
  // src/project/statusReaders.ts
86256
86419
  init_workspace();
86257
86420
  async function countFiles(root2, predicate) {
86258
- if (!existsSync35(root2))
86421
+ if (!existsSync36(root2))
86259
86422
  return 0;
86260
86423
  let count = 0;
86261
86424
  const visit3 = async (dir, prefix = "") => {
86262
86425
  const entries = await readdir16(dir, { withFileTypes: true });
86263
86426
  for (const entry of entries) {
86264
86427
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
86265
- const abs = join52(dir, entry.name);
86428
+ const abs = join53(dir, entry.name);
86266
86429
  if (entry.isDirectory())
86267
86430
  await visit3(abs, rel);
86268
86431
  else if (entry.isFile() && predicate(rel))
@@ -86304,14 +86467,14 @@ async function readDraftCandidateStatus(projectRoot) {
86304
86467
  throw error;
86305
86468
  }
86306
86469
  }
86307
- function isRecord18(value) {
86470
+ function isRecord19(value) {
86308
86471
  return value !== null && typeof value === "object" && !Array.isArray(value);
86309
86472
  }
86310
86473
  function stagedStructureCounts(parsed) {
86311
86474
  const views = Array.isArray(parsed.views) ? parsed.views : [];
86312
- const sections = views.flatMap((view) => isRecord18(view) && Array.isArray(view.sections) ? view.sections : []);
86475
+ const sections = views.flatMap((view) => isRecord19(view) && Array.isArray(view.sections) ? view.sections : []);
86313
86476
  const sourceRefs = new Set(sections.flatMap((section) => {
86314
- if (!isRecord18(section))
86477
+ if (!isRecord19(section))
86315
86478
  return [];
86316
86479
  return [
86317
86480
  ...typeof section.source_ref === "string" ? [section.source_ref] : [],
@@ -86328,12 +86491,12 @@ function stagedStructureCounts(parsed) {
86328
86491
  };
86329
86492
  }
86330
86493
  function readStructureDraftStatus(projectRoot) {
86331
- const structurePath = join52(projectRoot, LIFECYCLE_STRUCTURE_FILE);
86332
- if (!existsSync35(structurePath))
86494
+ const structurePath = join53(projectRoot, LIFECYCLE_STRUCTURE_FILE);
86495
+ if (!existsSync36(structurePath))
86333
86496
  return { state: "missing", sourceKeys: [], collections: [], diagnostics: [] };
86334
86497
  try {
86335
- const parsed = import_yaml29.default.parse(readFileSync7(structurePath, "utf8"));
86336
- if (!isRecord18(parsed)) {
86498
+ const parsed = import_yaml29.default.parse(readFileSync8(structurePath, "utf8"));
86499
+ if (!isRecord19(parsed)) {
86337
86500
  return {
86338
86501
  state: "invalid",
86339
86502
  sourceKeys: [],
@@ -86341,7 +86504,7 @@ function readStructureDraftStatus(projectRoot) {
86341
86504
  diagnostics: [`${LIFECYCLE_STRUCTURE_FILE} must be a YAML object`]
86342
86505
  };
86343
86506
  }
86344
- const lifecycle = isRecord18(parsed.lifecycle) ? parsed.lifecycle : {};
86507
+ const lifecycle = isRecord19(parsed.lifecycle) ? parsed.lifecycle : {};
86345
86508
  const lifecycleState = lifecycle.state;
86346
86509
  if (lifecycleState === "draft" || lifecycleState === "confirmed" || lifecycleState === "frozen") {
86347
86510
  const structureDigest = typeof parsed.structure_digest === "string" ? parsed.structure_digest : typeof lifecycle.structure_digest === "string" ? lifecycle.structure_digest : undefined;
@@ -86351,7 +86514,7 @@ function readStructureDraftStatus(projectRoot) {
86351
86514
  lifecycleState,
86352
86515
  ...typeof lifecycle.phase_collection === "string" ? { phaseCollection: lifecycle.phase_collection } : {},
86353
86516
  sourceKeys: Array.isArray(parsed.sources) ? parsed.sources.filter((item) => typeof item === "string") : [],
86354
- collections: Array.isArray(parsed.views) ? [...new Set(parsed.views.flatMap((view) => isRecord18(view) && typeof view.collection === "string" ? [view.collection] : []))].sort() : [],
86517
+ collections: Array.isArray(parsed.views) ? [...new Set(parsed.views.flatMap((view) => isRecord19(view) && typeof view.collection === "string" ? [view.collection] : []))].sort() : [],
86355
86518
  ...structureDigest === undefined ? {} : { structureDigest },
86356
86519
  ...evidenceSnapshotHash === undefined ? {} : { evidenceSnapshotHash },
86357
86520
  ...stagedStructureCounts(parsed),
@@ -86528,8 +86691,8 @@ async function documentSourceSiteHint(input) {
86528
86691
  });
86529
86692
  }
86530
86693
  function documentSnapshotReadiness(input) {
86531
- const manifestPath = join52(input.projectRoot, input.manifest);
86532
- if (!existsSync35(manifestPath)) {
86694
+ const manifestPath = join53(input.projectRoot, input.manifest);
86695
+ if (!existsSync36(manifestPath)) {
86533
86696
  return {
86534
86697
  ready: false,
86535
86698
  diagnostics: [`snapshot is missing: ${input.manifest}`],
@@ -86537,7 +86700,7 @@ function documentSnapshotReadiness(input) {
86537
86700
  };
86538
86701
  }
86539
86702
  try {
86540
- const manifest = findDocumentSnapshotForSource(JSON.parse(readFileSync7(manifestPath, "utf8")), input.sourceName);
86703
+ const manifest = findDocumentSnapshotForSource(JSON.parse(readFileSync8(manifestPath, "utf8")), input.sourceName);
86541
86704
  if (manifest === null) {
86542
86705
  return {
86543
86706
  ready: false,
@@ -86598,7 +86761,7 @@ function documentSnapshotReadiness(input) {
86598
86761
  const missingFiles = [
86599
86762
  ...manifest.files.map((file) => file.path),
86600
86763
  ...(manifest.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
86601
- ].filter((path4) => !existsSync35(join52(input.projectRoot, input.materializedAt, path4)));
86764
+ ].filter((path4) => !existsSync36(join53(input.projectRoot, input.materializedAt, path4)));
86602
86765
  if (missingFiles.length > 0) {
86603
86766
  return {
86604
86767
  ready: false,
@@ -86845,9 +87008,9 @@ async function readActiveStructuresStatus(projectRoot, currentSnapshotHashes) {
86845
87008
  init_packageTemplateReview();
86846
87009
 
86847
87010
  // src/project/workflow/workflowProvider.ts
86848
- import { existsSync as existsSync36 } from "node:fs";
86849
- import { dirname as dirname34, resolve as resolve20 } from "node:path";
86850
- import { fileURLToPath as fileURLToPath6 } from "node:url";
87011
+ import { existsSync as existsSync37 } from "node:fs";
87012
+ import { dirname as dirname35, resolve as resolve20 } from "node:path";
87013
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
86851
87014
 
86852
87015
  // src/project/workflow/verifyFacts.ts
86853
87016
  var CLOSE_REPAIRABLE_APPROVED_STRUCTURE_CODES = new Set([
@@ -87419,7 +87582,7 @@ function planForResolvedCommandPlan(commandPlan, observation) {
87419
87582
 
87420
87583
  // src/project/workflow/workflowEvidenceResources.ts
87421
87584
  import { createHash as createHash21 } from "node:crypto";
87422
- import { join as join53 } from "node:path";
87585
+ import { join as join54 } from "node:path";
87423
87586
  function sourceKeysForRoute(node3, observation) {
87424
87587
  if (node3 === "classify-document") {
87425
87588
  return observation.unclassifiedDocumentTargets.map((target) => target.sourceKey);
@@ -87471,7 +87634,7 @@ async function currentSourceBodyResources(input) {
87471
87634
  kind: "context-view",
87472
87635
  media_type: "text/markdown",
87473
87636
  digest: document4.content_hash,
87474
- path: join53(input.observation.projectRoot, source2.materializedAt, document4.path),
87637
+ path: join54(input.observation.projectRoot, source2.materializedAt, document4.path),
87475
87638
  read_state: isCurrent(id2, document4.content_hash, input.receipts) ? "current" : "read-required"
87476
87639
  });
87477
87640
  }
@@ -87483,7 +87646,7 @@ async function currentSourceBodyResources(input) {
87483
87646
  // src/project/workflow/workflowProvider.ts
87484
87647
  var providerPromise;
87485
87648
  function providerCandidates() {
87486
- const moduleDir2 = dirname34(fileURLToPath6(import.meta.url));
87649
+ const moduleDir2 = dirname35(fileURLToPath7(import.meta.url));
87487
87650
  return [
87488
87651
  ...process.env.C4A_CONTEXT_WORKFLOW_PROVIDER ? [resolve20(process.env.C4A_CONTEXT_WORKFLOW_PROVIDER)] : [],
87489
87652
  resolve20(moduleDir2, "providers", "context", "manifest.json"),
@@ -87491,7 +87654,7 @@ function providerCandidates() {
87491
87654
  ];
87492
87655
  }
87493
87656
  function contextWorkflowProviderPath() {
87494
- const candidate = providerCandidates().find((path4) => existsSync36(path4));
87657
+ const candidate = providerCandidates().find((path4) => existsSync37(path4));
87495
87658
  if (candidate === undefined) {
87496
87659
  throw new Error("Context workflow Provider is missing. Rebuild @c4a/context-cli or reinstall the published package.");
87497
87660
  }
@@ -88505,13 +88668,13 @@ async function collectProjectStatusSnapshot(projectRoot, options = {}) {
88505
88668
  requestedCollections: [...new Set(alignTargets.map((target) => target.collection))],
88506
88669
  requestedGroups: alignGroups
88507
88670
  });
88508
- const approvedPages = await countFiles(join54(projectRoot, "knowledge"), (rel) => rel.endsWith(".md") && !rel.startsWith("assets/"));
88671
+ const approvedPages = await countFiles(join55(projectRoot, "knowledge"), (rel) => rel.endsWith(".md") && !rel.startsWith("assets/"));
88509
88672
  const approvedCollections = (await Promise.all(KNOWLEDGE_COLLECTIONS.map(async (collection) => ({
88510
88673
  collection,
88511
- count: await countFiles(join54(projectRoot, "knowledge", collection), (rel) => rel.endsWith(".md"))
88674
+ count: await countFiles(join55(projectRoot, "knowledge", collection), (rel) => rel.endsWith(".md"))
88512
88675
  })))).filter((item) => item.count > 0).map((item) => item.collection);
88513
88676
  const closeStatus = await readCloseStatus(projectRoot);
88514
- const distFiles = await countFiles(join54(projectRoot, "dist"), () => true);
88677
+ const distFiles = await countFiles(join55(projectRoot, "dist"), () => true);
88515
88678
  const sourceFreshness = phaseStatus.projectEntryValid ? await collectSourceFreshness({
88516
88679
  projectRoot,
88517
88680
  phases,
@@ -88875,6 +89038,7 @@ async function runProjectStatusCommand(input) {
88875
89038
  } else {
88876
89039
  process.stdout.write(formatProjectStatus(status));
88877
89040
  }
89041
+ input.onSuccess?.(status);
88878
89042
  return true;
88879
89043
  }
88880
89044
  async function assertProjectWorkflowRevision(input) {
@@ -88931,11 +89095,11 @@ function shellQuote6(value) {
88931
89095
  }
88932
89096
  function receiptSetPath(receipts) {
88933
89097
  const token = digestText(JSON.stringify(receipts)).slice("sha256:".length);
88934
- return join55(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
89098
+ return join56(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
88935
89099
  }
88936
89100
  async function writeReceiptContinuation(input) {
88937
89101
  const path4 = receiptSetPath(input.receipts);
88938
- await writeJsonAtomic(join55(input.projectRoot, path4), input.receipts);
89102
+ await writeJsonAtomic(join56(input.projectRoot, path4), input.receipts);
88939
89103
  const command2 = input.managed ? [
88940
89104
  "context",
88941
89105
  "--workflow-resource-receipts",
@@ -88996,7 +89160,7 @@ async function materializeContextWorkflowResource(input) {
88996
89160
  }
88997
89161
  const content3 = renderContextWorkflowResource(resourceId2, status);
88998
89162
  const location = await materializeResource(await loadContextWorkflowProvider(), resourceId2, {
88999
- cache: join55(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
89163
+ cache: join56(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
89000
89164
  workspace: found.projectRoot,
89001
89165
  revision: input.revision,
89002
89166
  input: {
@@ -89222,7 +89386,7 @@ function registerContextWorkflowResourceCommands(program2) {
89222
89386
  }
89223
89387
 
89224
89388
  // src/commands/runProject.ts
89225
- import { fileURLToPath as fileURLToPath7 } from "node:url";
89389
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
89226
89390
  init_cliFeedback();
89227
89391
  init_errors();
89228
89392
 
@@ -89233,11 +89397,11 @@ init_exitCode();
89233
89397
 
89234
89398
  // src/project/documentCaptureLark.ts
89235
89399
  import { readdir as readdir18, readFile as readFile44 } from "node:fs/promises";
89236
- import { basename as basename8, extname as extname12, join as join58 } from "node:path";
89400
+ import { basename as basename8, extname as extname12, join as join59 } from "node:path";
89237
89401
 
89238
89402
  // src/lib/atomicFileBatch.ts
89239
89403
  import { lstat as lstat2, mkdir as mkdir28, mkdtemp, rename as rename4, rm as rm14, writeFile as writeFile23 } from "node:fs/promises";
89240
- import { dirname as dirname35, join as join56, resolve as resolve22 } from "node:path";
89404
+ import { dirname as dirname36, join as join57, resolve as resolve22 } from "node:path";
89241
89405
  async function existingFileKind(path4) {
89242
89406
  try {
89243
89407
  const stats = await lstat2(path4);
@@ -89267,9 +89431,9 @@ async function applyAtomicFileBatch(input) {
89267
89431
  for (const path4 of writesByPath.keys())
89268
89432
  removalPaths.delete(path4);
89269
89433
  await mkdir28(input.transactionRoot, { recursive: true });
89270
- const transactionDir = await mkdtemp(join56(input.transactionRoot, "batch-"));
89271
- const stagedRoot = join56(transactionDir, "staged");
89272
- const backupRoot = join56(transactionDir, "backup");
89434
+ const transactionDir = await mkdtemp(join57(input.transactionRoot, "batch-"));
89435
+ const stagedRoot = join57(transactionDir, "staged");
89436
+ const backupRoot = join57(transactionDir, "backup");
89273
89437
  const writes = [...writesByPath.values()].sort((left, right) => left.path.localeCompare(right.path));
89274
89438
  const affectedPaths = [...new Set([...writesByPath.keys(), ...removalPaths])].sort();
89275
89439
  const staged = new Map;
@@ -89279,20 +89443,20 @@ async function applyAtomicFileBatch(input) {
89279
89443
  try {
89280
89444
  await mkdir28(stagedRoot, { recursive: true });
89281
89445
  for (const [index2, write] of writes.entries()) {
89282
- const path4 = join56(stagedRoot, String(index2));
89446
+ const path4 = join57(stagedRoot, String(index2));
89283
89447
  await writeFile23(path4, write.bytes);
89284
89448
  staged.set(write.path, path4);
89285
89449
  }
89286
89450
  for (const [index2, path4] of affectedPaths.entries()) {
89287
89451
  if (await existingFileKind(path4) === "missing")
89288
89452
  continue;
89289
- const backupPath = join56(backupRoot, String(index2));
89290
- await mkdir28(dirname35(backupPath), { recursive: true });
89453
+ const backupPath = join57(backupRoot, String(index2));
89454
+ await mkdir28(dirname36(backupPath), { recursive: true });
89291
89455
  await rename4(path4, backupPath);
89292
89456
  backups.set(path4, backupPath);
89293
89457
  }
89294
89458
  for (const write of writes) {
89295
- await mkdir28(dirname35(write.path), { recursive: true });
89459
+ await mkdir28(dirname36(write.path), { recursive: true });
89296
89460
  await rename4(staged.get(write.path), write.path);
89297
89461
  installed.push(write.path);
89298
89462
  }
@@ -89304,7 +89468,7 @@ async function applyAtomicFileBatch(input) {
89304
89468
  });
89305
89469
  }
89306
89470
  for (const [path4, backupPath] of [...backups.entries()].reverse()) {
89307
- await mkdir28(dirname35(path4), { recursive: true });
89471
+ await mkdir28(dirname36(path4), { recursive: true });
89308
89472
  await rename4(backupPath, path4).catch((rollbackError) => {
89309
89473
  rollbackFailures.push(`restore ${path4}: ${String(rollbackError)}`);
89310
89474
  });
@@ -89341,7 +89505,7 @@ function detectExternalEnvironmentIssue(value) {
89341
89505
  }
89342
89506
 
89343
89507
  // src/lib/feishu.ts
89344
- import { spawn as spawn2 } from "node:child_process";
89508
+ import { spawn as spawn3 } from "node:child_process";
89345
89509
 
89346
89510
  // src/lib/larkDocxXml.ts
89347
89511
  import { createHash as createHash23 } from "node:crypto";
@@ -93626,7 +93790,7 @@ function projectLarkDocxXmlBlock(input) {
93626
93790
  // src/lib/larkResourceMaterialization.ts
93627
93791
  import { createHash as createHash24 } from "node:crypto";
93628
93792
  import { mkdtemp as mkdtemp2, readFile as readFile43, readdir as readdir17, rm as rm15 } from "node:fs/promises";
93629
- import { extname as extname11, join as join57 } from "node:path";
93793
+ import { extname as extname11, join as join58 } from "node:path";
93630
93794
  import { tmpdir } from "node:os";
93631
93795
 
93632
93796
  // src/lib/larkResourceCommand.ts
@@ -93825,7 +93989,7 @@ function findBooleanField(value, name2) {
93825
93989
  return;
93826
93990
  }
93827
93991
  async function downloadedFile(input) {
93828
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-resource-"));
93992
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-resource-"));
93829
93993
  try {
93830
93994
  await runLarkResourceCommand(input.runner, [
93831
93995
  "docs",
@@ -93846,7 +94010,7 @@ async function downloadedFile(input) {
93846
94010
  if (entries.length !== 1)
93847
94011
  throw new Error(`media download produced ${entries.length} files, expected exactly one`);
93848
94012
  const path4 = entries[0]?.name ?? "resource.bin";
93849
- const bytes = await readFile43(join57(tempRoot, path4));
94013
+ const bytes = await readFile43(join58(tempRoot, path4));
93850
94014
  return { path: path4, bytes, mediaType: mediaTypeFor(path4, bytes) };
93851
94015
  } finally {
93852
94016
  await rm15(tempRoot, { recursive: true, force: true });
@@ -93937,9 +94101,9 @@ async function sheetMaterialization(resource, runner2) {
93937
94101
  const sheetId = resource.attributes["sheet-id"];
93938
94102
  if (token === undefined || sheetId === undefined)
93939
94103
  throw new Error("embedded Sheet requires token and sheet-id");
93940
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-sheet-"));
94104
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-sheet-"));
93941
94105
  try {
93942
- const outputPath = join57(tempRoot, "sheet.json");
94106
+ const outputPath = join58(tempRoot, "sheet.json");
93943
94107
  const stdout = await runLarkResourceCommand(runner2, [
93944
94108
  "sheets",
93945
94109
  "+csv-get",
@@ -94095,7 +94259,7 @@ async function whiteboardMaterialization(resource, runner2) {
94095
94259
  if (token === undefined)
94096
94260
  throw new Error(`${resource.kind} has no whiteboard token`);
94097
94261
  const preview = await downloadedFile({ runner: runner2, token, type: "whiteboard" });
94098
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-whiteboard-"));
94262
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-whiteboard-"));
94099
94263
  let rawPayload;
94100
94264
  try {
94101
94265
  await runLarkResourceCommand(runner2, [
@@ -94113,7 +94277,7 @@ async function whiteboardMaterialization(resource, runner2) {
94113
94277
  "--format",
94114
94278
  "json"
94115
94279
  ], { cwd: tempRoot });
94116
- rawPayload = JSON.parse(await readFile43(join57(tempRoot, "raw.json"), "utf8"));
94280
+ rawPayload = JSON.parse(await readFile43(join58(tempRoot, "raw.json"), "utf8"));
94117
94281
  } finally {
94118
94282
  await rm15(tempRoot, { recursive: true, force: true });
94119
94283
  }
@@ -94386,7 +94550,7 @@ class LarkCliError extends Error {
94386
94550
  }
94387
94551
  }
94388
94552
  var defaultRunner = (args, options) => new Promise((resolve8, reject) => {
94389
- const child = spawn2(LARK_BIN, args, {
94553
+ const child = spawn3(LARK_BIN, args, {
94390
94554
  ...options?.cwd === undefined ? {} : { cwd: options.cwd },
94391
94555
  stdio: ["ignore", "pipe", "pipe"]
94392
94556
  });
@@ -94793,7 +94957,7 @@ async function fileContentMatches(path4, content3) {
94793
94957
  }
94794
94958
  }
94795
94959
  function sourceManifestPath2(entry) {
94796
- return entry.snapshot?.manifest ?? join58(entry.materializedAt, "manifest.json");
94960
+ return entry.snapshot?.manifest ?? join59(entry.materializedAt, "manifest.json");
94797
94961
  }
94798
94962
  function larkRuntimeError(message, detail) {
94799
94963
  return new ContextError(ExitCode.ExternalToolError, message, {
@@ -94919,7 +95083,7 @@ function assetManifestEntry(asset, assetRoot) {
94919
95083
  };
94920
95084
  }
94921
95085
  async function listSnapshotAssetFiles(root2, assetRoot) {
94922
- const assetsRoot = join58(root2, assetRoot);
95086
+ const assetsRoot = join59(root2, assetRoot);
94923
95087
  const files = [];
94924
95088
  const visit3 = async (dir, prefix = assetRoot) => {
94925
95089
  let entries;
@@ -94932,7 +95096,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
94932
95096
  }
94933
95097
  for (const entry of entries) {
94934
95098
  const relPath = `${prefix}/${entry.name}`;
94935
- const absolutePath = join58(dir, entry.name);
95099
+ const absolutePath = join59(dir, entry.name);
94936
95100
  if (entry.isDirectory()) {
94937
95101
  await visit3(absolutePath, relPath);
94938
95102
  continue;
@@ -94947,7 +95111,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
94947
95111
  }
94948
95112
  async function staleSnapshotAssetPaths(input) {
94949
95113
  const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
94950
- return existingPaths.filter((path4) => !input.currentPaths.has(path4)).map((path4) => join58(input.materializedAtAbsPath, path4));
95114
+ return existingPaths.filter((path4) => !input.currentPaths.has(path4)).map((path4) => join59(input.materializedAtAbsPath, path4));
94951
95115
  }
94952
95116
  function normalizeLarkError(error, sourceName) {
94953
95117
  if (error instanceof ContextError)
@@ -95021,9 +95185,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
95021
95185
  locator
95022
95186
  }];
95023
95187
  const manifestPath = sourceManifestPath2(entry);
95024
- const manifestAbsPath = join58(input.projectRoot, manifestPath);
95188
+ const manifestAbsPath = join59(input.projectRoot, manifestPath);
95025
95189
  const materializedAt = entry.materializedAt;
95026
- const materializedAtAbsPath = join58(input.projectRoot, materializedAt);
95190
+ const materializedAtAbsPath = join59(input.projectRoot, materializedAt);
95027
95191
  const manifest = createDocumentSnapshotManifest({
95028
95192
  sourceType: "lark",
95029
95193
  sourceName: resolved.sourceName,
@@ -95053,13 +95217,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
95053
95217
  }));
95054
95218
  try {
95055
95219
  const requestedWrites = [{
95056
- path: join58(materializedAtAbsPath, documentPath),
95220
+ path: join59(materializedAtAbsPath, documentPath),
95057
95221
  bytes: normalized
95058
95222
  }];
95059
95223
  for (const asset of assets) {
95060
95224
  if (asset.bytes !== undefined) {
95061
95225
  requestedWrites.push({
95062
- path: join58(materializedAtAbsPath, asset.entry.path),
95226
+ path: join59(materializedAtAbsPath, asset.entry.path),
95063
95227
  bytes: asset.bytes
95064
95228
  });
95065
95229
  }
@@ -95076,7 +95240,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
95076
95240
  currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
95077
95241
  });
95078
95242
  await applyAtomicFileBatch({
95079
- transactionRoot: join58(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
95243
+ transactionRoot: join59(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
95080
95244
  writes,
95081
95245
  removals
95082
95246
  });
@@ -97499,7 +97663,7 @@ function compileDiagnostic(severity, code3, family, message, field, extra = {})
97499
97663
  ...extra
97500
97664
  };
97501
97665
  }
97502
- function isRecord19(value) {
97666
+ function isRecord20(value) {
97503
97667
  return value !== null && typeof value === "object" && !Array.isArray(value);
97504
97668
  }
97505
97669
 
@@ -97894,7 +98058,7 @@ function compileActionFromFields(fields) {
97894
98058
  return action;
97895
98059
  }
97896
98060
  function parseCompileAction(raw, index2, diagnostics) {
97897
- if (!isRecord19(raw)) {
98061
+ if (!isRecord20(raw)) {
97898
98062
  diagnostics.push(compileDiagnostic("error", "schema.action_object", "schema", "Each action must be an object.", `actions[${index2}]`));
97899
98063
  return;
97900
98064
  }
@@ -97906,7 +98070,7 @@ function parseCompileAction(raw, index2, diagnostics) {
97906
98070
  }
97907
98071
  function parseCompilePayload(value) {
97908
98072
  const diagnostics = [];
97909
- if (!isRecord19(value)) {
98073
+ if (!isRecord20(value)) {
97910
98074
  return {
97911
98075
  diagnostics: [compileDiagnostic("error", "schema.payload_object", "schema", "Compile action payload must be an object.", "schema")]
97912
98076
  };
@@ -98869,9 +99033,9 @@ init_atomicWrite();
98869
99033
  init_cliFeedback();
98870
99034
  init_errors();
98871
99035
  init_exitCode();
98872
- import { existsSync as existsSync37 } from "node:fs";
99036
+ import { existsSync as existsSync38 } from "node:fs";
98873
99037
  import { readFile as readFile46 } from "node:fs/promises";
98874
- import { join as join59 } from "node:path";
99038
+ import { join as join60 } from "node:path";
98875
99039
  init_writeLock();
98876
99040
  var CUSTOM_PHASE_MANIFEST = ".tmp/context-runtime/extract/custom-phase-candidates.json";
98877
99041
  function customInputError(phaseId, message, detail = {}) {
@@ -99025,8 +99189,8 @@ function candidateFromCustom(input) {
99025
99189
  };
99026
99190
  }
99027
99191
  async function readManifest(projectRoot) {
99028
- const path4 = join59(projectRoot, CUSTOM_PHASE_MANIFEST);
99029
- if (!existsSync37(path4))
99192
+ const path4 = join60(projectRoot, CUSTOM_PHASE_MANIFEST);
99193
+ if (!existsSync38(path4))
99030
99194
  return { version: 2, phases: {} };
99031
99195
  try {
99032
99196
  const parsed = JSON.parse(await readFile46(path4, "utf8"));
@@ -99126,7 +99290,7 @@ async function runExtractCustomPhase(input) {
99126
99290
  symbols: built.flatMap((item) => item.symbols),
99127
99291
  removeSymbols: previousOwned?.symbols ?? []
99128
99292
  });
99129
- await atomicWriteFile(join59(input.projectRoot, CUSTOM_PHASE_MANIFEST), `${JSON.stringify({
99293
+ await atomicWriteFile(join60(input.projectRoot, CUSTOM_PHASE_MANIFEST), `${JSON.stringify({
99130
99294
  version: 2,
99131
99295
  phases: {
99132
99296
  ...manifest.phases,
@@ -99186,7 +99350,7 @@ async function runExtractCustomPhase(input) {
99186
99350
 
99187
99351
  // src/project/reviewHtml.ts
99188
99352
  import { mkdir as mkdir29, writeFile as writeFile24 } from "node:fs/promises";
99189
- import { dirname as dirname36, isAbsolute as isAbsolute9, join as join61, resolve as resolve23 } from "node:path";
99353
+ import { dirname as dirname37, isAbsolute as isAbsolute9, join as join62, resolve as resolve23 } from "node:path";
99190
99354
  import { pathToFileURL as pathToFileURL3 } from "node:url";
99191
99355
 
99192
99356
  // src/project/reviewSourceExcerpts.ts
@@ -99296,9 +99460,9 @@ async function collectReviewSourceExcerpts(projectRoot, candidates) {
99296
99460
  }
99297
99461
 
99298
99462
  // src/project/reviewHtmlPresentation.ts
99299
- import { existsSync as existsSync38 } from "node:fs";
99463
+ import { existsSync as existsSync39 } from "node:fs";
99300
99464
  import { readFile as readFile47 } from "node:fs/promises";
99301
- import { join as join60 } from "node:path";
99465
+ import { join as join61 } from "node:path";
99302
99466
  var import_yaml31 = __toESM(require_dist3(), 1);
99303
99467
  function escapeHtml3(value) {
99304
99468
  return value.replace(/&/gu, "&amp;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;").replace(/"/gu, "&quot;");
@@ -99379,8 +99543,8 @@ function filterEdgePreviewForCandidate(record, edges) {
99379
99543
  return edges.filter((edge2) => endpoints.has(edge2.from) || endpoints.has(edge2.to));
99380
99544
  }
99381
99545
  async function readEdgePreview(projectRoot) {
99382
- const filePath = join60(projectRoot, LIFECYCLE_STRUCTURE_FILE);
99383
- if (!existsSync38(filePath))
99546
+ const filePath = join61(projectRoot, LIFECYCLE_STRUCTURE_FILE);
99547
+ if (!existsSync39(filePath))
99384
99548
  return [];
99385
99549
  try {
99386
99550
  const parsed = import_yaml31.default.parse(await readFile47(filePath, "utf8"));
@@ -99557,7 +99721,7 @@ var REVIEW_HTML_STYLES = `
99557
99721
  `;
99558
99722
 
99559
99723
  // src/project/reviewHtml.ts
99560
- var REVIEW_HTML_ROOT = join61(".tmp", "context-runtime", "review");
99724
+ var REVIEW_HTML_ROOT = join62(".tmp", "context-runtime", "review");
99561
99725
  function decodedLinkTarget(value) {
99562
99726
  try {
99563
99727
  return decodeURIComponent(value);
@@ -99571,7 +99735,7 @@ function linkedResourcePreviews(input) {
99571
99735
  const target = link2.target;
99572
99736
  if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("/"))
99573
99737
  continue;
99574
- const assetPath = join61(dirname36(input.documentPath), decodedLinkTarget(target)).split("\\").join("/");
99738
+ const assetPath = join62(dirname37(input.documentPath), decodedLinkTarget(target)).split("\\").join("/");
99575
99739
  const asset = input.assetsByPath.get(assetPath);
99576
99740
  if (asset?.content_hash === undefined || asset.role === "audit")
99577
99741
  continue;
@@ -99579,7 +99743,7 @@ function linkedResourcePreviews(input) {
99579
99743
  label: link2.label || "Resource",
99580
99744
  kind: asset.source?.kind ?? "resource",
99581
99745
  status: "materialized",
99582
- url: pathToFileURL3(join61(input.projectRoot, input.materializedAt, asset.path)).href,
99746
+ url: pathToFileURL3(join62(input.projectRoot, input.materializedAt, asset.path)).href,
99583
99747
  media_type: asset.media_type ?? "application/octet-stream",
99584
99748
  image: asset.media_type?.startsWith("image/") === true
99585
99749
  });
@@ -99588,7 +99752,7 @@ function linkedResourcePreviews(input) {
99588
99752
  }
99589
99753
  function materializationPreview(input) {
99590
99754
  const linkedAsset = input.item.asset_paths.flatMap((path4) => [path4, path4.startsWith("assets/") ? path4 : `assets/${path4}`]).map((path4) => input.assetsByPath.get(path4)).find((asset) => asset !== undefined && asset.role !== "audit");
99591
- const url = input.existing?.url ?? (linkedAsset?.content_hash === undefined ? undefined : pathToFileURL3(join61(input.projectRoot, input.materializedAt, linkedAsset.path)).href);
99755
+ const url = input.existing?.url ?? (linkedAsset?.content_hash === undefined ? undefined : pathToFileURL3(join62(input.projectRoot, input.materializedAt, linkedAsset.path)).href);
99592
99756
  return {
99593
99757
  key: linkedAsset?.path ?? input.item.locator,
99594
99758
  preview: {
@@ -100132,7 +100296,7 @@ function renderReviewHtml(candidates, reviewScope, edgePreview, sourceExcerpts,
100132
100296
  }
100133
100297
  function resolveOutputPath(projectRoot, outPath, reviewScope) {
100134
100298
  if (outPath === undefined)
100135
- return join61(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
100299
+ return join62(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
100136
100300
  return isAbsolute9(outPath) ? outPath : resolve23(projectRoot, outPath);
100137
100301
  }
100138
100302
  async function writeReviewHtml(input) {
@@ -100145,7 +100309,7 @@ async function writeReviewHtml(input) {
100145
100309
  const sourceExcerpts = await collectReviewSourceExcerpts(input.projectRoot, candidates);
100146
100310
  const resourcePreviews = await collectReviewResourcePreviews(input.projectRoot, candidates);
100147
100311
  const outPath = resolveOutputPath(input.projectRoot, input.out, reviewScope);
100148
- await mkdir29(dirname36(outPath), { recursive: true });
100312
+ await mkdir29(dirname37(outPath), { recursive: true });
100149
100313
  await writeFile24(outPath, renderReviewHtml(candidates, reviewScope, edgePreview, sourceExcerpts, resourcePreviews), "utf8");
100150
100314
  return {
100151
100315
  path: outPath,
@@ -100560,17 +100724,17 @@ function compactJsonResult(result, verbose) {
100560
100724
  }
100561
100725
 
100562
100726
  // src/project/runLog.ts
100563
- import { randomUUID as randomUUID2 } from "node:crypto";
100727
+ import { randomUUID as randomUUID3 } from "node:crypto";
100564
100728
  import { mkdir as mkdir30, writeFile as writeFile25 } from "node:fs/promises";
100565
- import { dirname as dirname37, join as join62 } from "node:path";
100729
+ import { dirname as dirname38, join as join63 } from "node:path";
100566
100730
  var createPhaseRunId = () => {
100567
100731
  const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
100568
- return `run_${timestamp}_${randomUUID2().slice(0, 8)}`;
100732
+ return `run_${timestamp}_${randomUUID3().slice(0, 8)}`;
100569
100733
  };
100570
100734
  async function writePhaseRunLog(input) {
100571
- const relPath = join62(".tmp", "context-runtime", "runs", `${input.runId}.json`);
100572
- const absPath = join62(input.projectRoot, relPath);
100573
- await mkdir30(dirname37(absPath), { recursive: true });
100735
+ const relPath = join63(".tmp", "context-runtime", "runs", `${input.runId}.json`);
100736
+ const absPath = join63(input.projectRoot, relPath);
100737
+ await mkdir30(dirname38(absPath), { recursive: true });
100574
100738
  await writeFile25(absPath, `${JSON.stringify({
100575
100739
  run_id: input.runId,
100576
100740
  phase_id: input.phase.id,
@@ -101271,14 +101435,14 @@ init_exitCode();
101271
101435
  import { resolve as resolve24 } from "node:path";
101272
101436
  init_workspace();
101273
101437
  var PROSE_STRUCTURE_BATCH_SCHEMA = "context.prose.structure-batch.v1";
101274
- function isRecord20(value) {
101438
+ function isRecord21(value) {
101275
101439
  return value !== null && typeof value === "object" && !Array.isArray(value);
101276
101440
  }
101277
101441
  function shellQuote8(value) {
101278
101442
  return /^[A-Za-z0-9._/=-]+$/u.test(value) ? value : `'${value.replace(/'/gu, `'"'"'`)}'`;
101279
101443
  }
101280
101444
  function parseBatchPayload(value) {
101281
- if (!isRecord20(value) || value.schema !== PROSE_STRUCTURE_BATCH_SCHEMA || !Array.isArray(value.items)) {
101445
+ if (!isRecord21(value) || value.schema !== PROSE_STRUCTURE_BATCH_SCHEMA || !Array.isArray(value.items)) {
101282
101446
  throw new ContextError(ExitCode.UserError, `batch input must match ${PROSE_STRUCTURE_BATCH_SCHEMA}`, {
101283
101447
  category: ErrorCategory.UserInputInvalid,
101284
101448
  next: "Read the current Route action input_schema and provide one phase_id/input pair per pending structure slot."
@@ -101291,7 +101455,7 @@ function parseBatchPayload(value) {
101291
101455
  }
101292
101456
  const seen = new Set;
101293
101457
  return value.items.map((item, index2) => {
101294
- if (!isRecord20(item) || typeof item.phase_id !== "string" || typeof item.input !== "string") {
101458
+ if (!isRecord21(item) || typeof item.phase_id !== "string" || typeof item.input !== "string") {
101295
101459
  throw new ContextError(ExitCode.UserError, `structure batch items[${index2}] requires phase_id and input`, {
101296
101460
  category: ErrorCategory.UserInputInvalid
101297
101461
  });
@@ -101323,7 +101487,7 @@ function alignPhase(phases, phaseId) {
101323
101487
  return phase;
101324
101488
  }
101325
101489
  function validationSummary(phaseId, input, result) {
101326
- const counts2 = result.structure_summary_compact !== undefined && isRecord20(result.structure_summary_compact.counts) ? result.structure_summary_compact.counts : undefined;
101490
+ const counts2 = result.structure_summary_compact !== undefined && isRecord21(result.structure_summary_compact.counts) ? result.structure_summary_compact.counts : undefined;
101327
101491
  return {
101328
101492
  phase_id: phaseId,
101329
101493
  input,
@@ -101817,7 +101981,7 @@ init_debugTrace();
101817
101981
  // src/project/workflow/workflowExecutionRuntime.ts
101818
101982
  init_debugTrace();
101819
101983
  import { createHash as createHash26 } from "node:crypto";
101820
- import { spawn as spawn3 } from "node:child_process";
101984
+ import { spawn as spawn4 } from "node:child_process";
101821
101985
  function digestText2(value, includeTail) {
101822
101986
  const bytes = Buffer.byteLength(value);
101823
101987
  return {
@@ -101967,7 +102131,7 @@ execution scope cleanup failed`, true)
101967
102131
  try {
101968
102132
  receipt = await new Promise((resolve8, reject) => {
101969
102133
  let settled = false;
101970
- const child = spawn3(process.execPath, [this.cliEntryPath, ...args], {
102134
+ const child = spawn4(process.execPath, [this.cliEntryPath, ...args], {
101971
102135
  cwd: input.cwd,
101972
102136
  env: { ...process.env, ...debugChildEnvironment() },
101973
102137
  stdio: ["ignore", "pipe", "pipe"],
@@ -102332,7 +102496,7 @@ function requirePayloadHeaderField(value, field) {
102332
102496
  return value;
102333
102497
  }
102334
102498
  function parsePayloadLineDecision(value, index2) {
102335
- if (!isRecord16(value) || typeof value.candidate_id !== "string") {
102499
+ if (!isRecord17(value) || typeof value.candidate_id !== "string") {
102336
102500
  throw new ContextError(ExitCode.UserError, `review payload line ${index2} must contain candidate_id and status`, {
102337
102501
  category: ErrorCategory.UserInputInvalid
102338
102502
  });
@@ -102345,7 +102509,7 @@ function parsePayloadLineDecision(value, index2) {
102345
102509
  function parsePayloadScope(value) {
102346
102510
  if (value === undefined)
102347
102511
  return;
102348
- if (!isRecord16(value) || typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || typeof value.ids_sha256 !== "string" || !/^[a-f0-9]{64}$/iu.test(value.ids_sha256)) {
102512
+ if (!isRecord17(value) || typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || typeof value.ids_sha256 !== "string" || !/^[a-f0-9]{64}$/iu.test(value.ids_sha256)) {
102349
102513
  throw new ContextError(ExitCode.UserError, "review payload scope must contain count and ids_sha256", {
102350
102514
  category: ErrorCategory.UserInputInvalid
102351
102515
  });
@@ -102384,7 +102548,7 @@ function parsePayloadScope(value) {
102384
102548
  }
102385
102549
  function parsePayloadValues(parsed) {
102386
102550
  const first = parsed[0];
102387
- if (!isRecord16(first)) {
102551
+ if (!isRecord17(first)) {
102388
102552
  throw new ContextError(ExitCode.UserError, "review payload header must be a JSON object", {
102389
102553
  category: ErrorCategory.UserInputInvalid
102390
102554
  });
@@ -103296,7 +103460,7 @@ async function runManagedUntil(input) {
103296
103460
  const resourceReceipts = input.resourceReceiptsReference === undefined ? undefined : await parseWorkflowResourceReceipts(input.resourceReceiptsReference, found.projectRoot);
103297
103461
  const runtime = new WorkspaceExecutionRuntime({
103298
103462
  projectRoot: found.projectRoot,
103299
- cliEntryPath: fileURLToPath7(input.cliModuleUrl),
103463
+ cliEntryPath: fileURLToPath8(input.cliModuleUrl),
103300
103464
  inProcess: createWorkflowInProcessExecutor()
103301
103465
  });
103302
103466
  let result;
@@ -103441,10 +103605,10 @@ function registerDebugCommands(program2) {
103441
103605
 
103442
103606
  // src/commands/cleanClaudePluginCache.ts
103443
103607
  init_cliFeedback();
103444
- import { existsSync as existsSync39 } from "node:fs";
103608
+ import { existsSync as existsSync40 } from "node:fs";
103445
103609
  import { readdir as readdir19, rm as rm16 } from "node:fs/promises";
103446
103610
  import { homedir } from "node:os";
103447
- import { join as join63 } from "node:path";
103611
+ import { join as join64 } from "node:path";
103448
103612
  var ORPHAN_MARKER = ".orphaned_at";
103449
103613
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
103450
103614
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -103453,7 +103617,7 @@ async function cleanClaudePluginCache(opts = {}) {
103453
103617
  const lines = [];
103454
103618
  let removed = 0;
103455
103619
  let scanned = 0;
103456
- if (!existsSync39(cacheRoot)) {
103620
+ if (!existsSync40(cacheRoot)) {
103457
103621
  lines.push("· claude plugin cache: missing — nothing to clean");
103458
103622
  return { lines, removed, scanned };
103459
103623
  }
@@ -103461,20 +103625,20 @@ async function cleanClaudePluginCache(opts = {}) {
103461
103625
  for (const mp of marketplaces) {
103462
103626
  if (!mp.isDirectory())
103463
103627
  continue;
103464
- const mpDir = join63(cacheRoot, mp.name);
103628
+ const mpDir = join64(cacheRoot, mp.name);
103465
103629
  const plugins = await readdir19(mpDir, { withFileTypes: true });
103466
103630
  for (const pl of plugins) {
103467
103631
  if (!pl.isDirectory())
103468
103632
  continue;
103469
- const plDir = join63(mpDir, pl.name);
103633
+ const plDir = join64(mpDir, pl.name);
103470
103634
  const versions = await readdir19(plDir, { withFileTypes: true });
103471
103635
  for (const ver of versions) {
103472
103636
  if (!ver.isDirectory())
103473
103637
  continue;
103474
103638
  scanned += 1;
103475
- const verDir = join63(plDir, ver.name);
103476
- const markerPath = join63(verDir, ORPHAN_MARKER);
103477
- if (!existsSync39(markerPath))
103639
+ const verDir = join64(plDir, ver.name);
103640
+ const markerPath = join64(verDir, ORPHAN_MARKER);
103641
+ if (!existsSync40(markerPath))
103478
103642
  continue;
103479
103643
  const label3 = `${mp.name}/${pl.name}/${ver.name}`;
103480
103644
  if (opts.dryRun) {
@@ -103505,7 +103669,7 @@ function resolveClaudePluginCacheRoot(opts) {
103505
103669
  if (explicitRoot)
103506
103670
  return explicitRoot;
103507
103671
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
103508
- return join63(home, ".claude", "plugins", "cache");
103672
+ return join64(home, ".claude", "plugins", "cache");
103509
103673
  }
103510
103674
  async function isEmptyDir(dir) {
103511
103675
  try {
@@ -103531,17 +103695,17 @@ async function runDoctorCleanClaudePluginCache(opts = {}) {
103531
103695
  }
103532
103696
 
103533
103697
  // src/commands/cleanCache.ts
103534
- import { existsSync as existsSync41 } from "node:fs";
103698
+ import { existsSync as existsSync42 } from "node:fs";
103535
103699
  import { readdir as readdir20, rm as rm17 } from "node:fs/promises";
103536
- import { join as join67 } from "node:path";
103700
+ import { join as join68 } from "node:path";
103537
103701
 
103538
103702
  // src/incremental/cache.ts
103539
- import { basename as basename10, dirname as dirname39, isAbsolute as isAbsolute11, join as join66, resolve as resolve27 } from "node:path";
103703
+ import { basename as basename10, dirname as dirname40, isAbsolute as isAbsolute11, join as join67, resolve as resolve27 } from "node:path";
103540
103704
 
103541
103705
  // src/lib/workspaceLayout.ts
103542
103706
  var import_yaml32 = __toESM(require_dist3(), 1);
103543
- import { existsSync as existsSync40, readFileSync as readFileSync8, statSync as statSync2 } from "node:fs";
103544
- import { dirname as dirname38, join as join64, parse as parse7, resolve as resolve26 } from "node:path";
103707
+ import { existsSync as existsSync41, readFileSync as readFileSync9, statSync as statSync2 } from "node:fs";
103708
+ import { dirname as dirname39, join as join65, parse as parse7, resolve as resolve26 } from "node:path";
103545
103709
  function isDirectorySafe(path4) {
103546
103710
  try {
103547
103711
  return statSync2(path4).isDirectory();
@@ -103550,11 +103714,11 @@ function isDirectorySafe(path4) {
103550
103714
  }
103551
103715
  }
103552
103716
  function hasRootLayoutMarker(dir) {
103553
- const configPath = join64(dir, "config.yaml");
103554
- if (!existsSync40(configPath))
103717
+ const configPath = join65(dir, "config.yaml");
103718
+ if (!existsSync41(configPath))
103555
103719
  return false;
103556
103720
  try {
103557
- const parsed = import_yaml32.default.parse(readFileSync8(configPath, "utf8"));
103721
+ const parsed = import_yaml32.default.parse(readFileSync9(configPath, "utf8"));
103558
103722
  if (!parsed || typeof parsed !== "object")
103559
103723
  return false;
103560
103724
  const workspace = parsed.workspace;
@@ -103567,8 +103731,8 @@ function hasRootLayoutMarker(dir) {
103567
103731
  }
103568
103732
  function findWorkspaceAt(dir) {
103569
103733
  const root2 = resolve26(dir);
103570
- const embedded = join64(root2, ".context");
103571
- if (existsSync40(join64(embedded, "config.yaml")) && isDirectorySafe(embedded)) {
103734
+ const embedded = join65(root2, ".context");
103735
+ if (existsSync41(join65(embedded, "config.yaml")) && isDirectorySafe(embedded)) {
103572
103736
  return { ctxDir: embedded, workspaceRoot: root2, layout: "embedded" };
103573
103737
  }
103574
103738
  if (hasRootLayoutMarker(root2)) {
@@ -103585,7 +103749,7 @@ function findNearestWorkspace(startDir = process.cwd()) {
103585
103749
  return found;
103586
103750
  if (dir === root2)
103587
103751
  return null;
103588
- const parent = dirname38(dir);
103752
+ const parent = dirname39(dir);
103589
103753
  if (parent === dir)
103590
103754
  return null;
103591
103755
  dir = parent;
@@ -103593,9 +103757,9 @@ function findNearestWorkspace(startDir = process.cwd()) {
103593
103757
  }
103594
103758
 
103595
103759
  // src/lib/userCache.ts
103596
- import { basename as basename9, join as join65 } from "node:path";
103760
+ import { basename as basename9, join as join66 } from "node:path";
103597
103761
  function workspaceLocalUserCacheRoot(ctxDir) {
103598
- return join65(ctxDir, ".tmp", "context-cli");
103762
+ return join66(ctxDir, ".tmp", "context-cli");
103599
103763
  }
103600
103764
 
103601
103765
  // src/incremental/cache.ts
@@ -103605,7 +103769,7 @@ function resolveCachePath(value) {
103605
103769
  }
103606
103770
  function workspaceCacheHome(workspaceRoot) {
103607
103771
  const location = findWorkspaceAt(workspaceRoot);
103608
- return workspaceLocalUserCacheRoot(location?.ctxDir ?? join66(workspaceRoot, ".context"));
103772
+ return workspaceLocalUserCacheRoot(location?.ctxDir ?? join67(workspaceRoot, ".context"));
103609
103773
  }
103610
103774
  function resolveCacheHome(input = {}) {
103611
103775
  const explicit = input.cacheHome ?? process.env.C4A_CONTEXT_CACHE_HOME;
@@ -103614,24 +103778,24 @@ function resolveCacheHome(input = {}) {
103614
103778
  if (input.workspaceRoot !== undefined)
103615
103779
  return workspaceCacheHome(resolveCachePath(input.workspaceRoot));
103616
103780
  const nearest = findNearestWorkspace(process.cwd());
103617
- return workspaceLocalUserCacheRoot(nearest?.ctxDir ?? join66(process.cwd(), ".context"));
103781
+ return workspaceLocalUserCacheRoot(nearest?.ctxDir ?? join67(process.cwd(), ".context"));
103618
103782
  }
103619
103783
 
103620
103784
  // src/commands/cleanCache.ts
103621
103785
  async function countFiles2(dir) {
103622
- if (!existsSync41(dir))
103786
+ if (!existsSync42(dir))
103623
103787
  return 0;
103624
103788
  let count = 0;
103625
103789
  for (const entry of await readdir20(dir, { withFileTypes: true })) {
103626
- const full = join67(dir, entry.name);
103790
+ const full = join68(dir, entry.name);
103627
103791
  count += entry.isDirectory() ? await countFiles2(full) : 1;
103628
103792
  }
103629
103793
  return count;
103630
103794
  }
103631
103795
  async function inspectAllRetrievalCache() {
103632
103796
  const cacheHome = resolveCacheHome();
103633
- const cacheRoot = join67(cacheHome, "retrieval");
103634
- const projectIds = existsSync41(cacheRoot) ? (await readdir20(cacheRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort() : [];
103797
+ const cacheRoot = join68(cacheHome, "retrieval");
103798
+ const projectIds = existsSync42(cacheRoot) ? (await readdir20(cacheRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort() : [];
103635
103799
  const files = await countFiles2(cacheRoot);
103636
103800
  return { cacheRoot, projects: projectIds.length, files, projectIds };
103637
103801
  }
@@ -103649,8 +103813,6 @@ async function cleanAllRetrievalCache() {
103649
103813
  init_errors();
103650
103814
  init_cliFeedback();
103651
103815
  init_exitCode();
103652
- init_workspace();
103653
- init_packageTemplateReview();
103654
103816
 
103655
103817
  // src/project/sourceCommands.ts
103656
103818
  import { readFile as readFile54 } from "node:fs/promises";
@@ -103665,9 +103827,9 @@ init_cliFeedback();
103665
103827
  init_errors();
103666
103828
  init_exitCode();
103667
103829
  import { execFile as execFile6 } from "node:child_process";
103668
- import { existsSync as existsSync42 } from "node:fs";
103830
+ import { existsSync as existsSync43 } from "node:fs";
103669
103831
  import { lstat as lstat3, mkdir as mkdir31, readlink as readlink2, realpath as realpath4, rm as rm18, symlink as symlink2 } from "node:fs/promises";
103670
- import { basename as basename11, dirname as dirname40, isAbsolute as isAbsolute12, relative as relative20, resolve as resolve28 } from "node:path";
103832
+ import { basename as basename11, dirname as dirname41, isAbsolute as isAbsolute12, relative as relative20, resolve as resolve28 } from "node:path";
103671
103833
  import { promisify as promisify6 } from "node:util";
103672
103834
  init_writeLock();
103673
103835
  var execFileAsync6 = promisify6(execFile6);
@@ -103809,7 +103971,7 @@ async function git2(cwd, args) {
103809
103971
  }
103810
103972
  async function resolveGitRoot2(path4) {
103811
103973
  const root2 = await git2(path4, ["rev-parse", "--show-toplevel"]);
103812
- if (root2.length === 0 || !existsSync42(root2)) {
103974
+ if (root2.length === 0 || !existsSync43(root2)) {
103813
103975
  throw userInputError3(`local repository path is not a Git checkout: ${path4}`, { path: path4 });
103814
103976
  }
103815
103977
  return realpath4(root2);
@@ -103830,13 +103992,13 @@ async function verifyCheckout(input) {
103830
103992
  }
103831
103993
  async function cloneCheckout(input) {
103832
103994
  const target = resolve28(input.projectRoot, input.target ?? `.tmp/repo/${repositorySlug(input.remote)}-${input.ref.slice(0, 12)}`);
103833
- if (existsSync42(target)) {
103995
+ if (existsSync43(target)) {
103834
103996
  throw userInputError3(`clone target already exists: ${target}`, {
103835
103997
  target,
103836
103998
  next: `Use local mode with path ${JSON.stringify(target)} after inspecting the existing checkout.`
103837
103999
  });
103838
104000
  }
103839
- await mkdir31(dirname40(target), { recursive: true });
104001
+ await mkdir31(dirname41(target), { recursive: true });
103840
104002
  const cloneArgs = ["clone", "--no-checkout", "--depth=1", "--filter=blob:none", input.remote, target];
103841
104003
  try {
103842
104004
  await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
@@ -103885,7 +104047,7 @@ async function bindLocalAlias(input) {
103885
104047
  const stats = await lstat3(alias).catch(() => null);
103886
104048
  if (stats !== null) {
103887
104049
  if (stats.isSymbolicLink()) {
103888
- const actual = resolve28(dirname40(alias), await readlink2(alias));
104050
+ const actual = resolve28(dirname41(alias), await readlink2(alias));
103889
104051
  const actualReal = await realpath4(actual).catch(() => null);
103890
104052
  if (actualReal !== null && actualReal === await realpath4(input.checkout))
103891
104053
  return;
@@ -103901,8 +104063,8 @@ async function bindLocalAlias(input) {
103901
104063
  });
103902
104064
  }
103903
104065
  }
103904
- await mkdir31(dirname40(alias), { recursive: true });
103905
- await symlink2(relative20(dirname40(alias), input.checkout) || ".", alias);
104066
+ await mkdir31(dirname41(alias), { recursive: true });
104067
+ await symlink2(relative20(dirname41(alias), input.checkout) || ".", alias);
103906
104068
  }
103907
104069
  function selectPhysicalGroup(sources, selector) {
103908
104070
  const direct = selectRepoSources(sources, selector);
@@ -103989,13 +104151,13 @@ async function restoreRepositorySources(input) {
103989
104151
  }
103990
104152
 
103991
104153
  // src/project/sourceDocumentStatus.ts
103992
- import { existsSync as existsSync43 } from "node:fs";
104154
+ import { existsSync as existsSync44 } from "node:fs";
103993
104155
  import { readFile as readFile51 } from "node:fs/promises";
103994
- import { join as join69 } from "node:path";
104156
+ import { join as join70 } from "node:path";
103995
104157
 
103996
104158
  // src/project/sourceCommandViews.ts
103997
104159
  import { readFile as readFile50 } from "node:fs/promises";
103998
- import { join as join68 } from "node:path";
104160
+ import { join as join69 } from "node:path";
103999
104161
  init_workspace();
104000
104162
  function repoSourceAgentView(source2) {
104001
104163
  return {
@@ -104057,7 +104219,7 @@ async function fileSourceAgentViewWithNextAction(input) {
104057
104219
  };
104058
104220
  }
104059
104221
  function documentSourceManifestPath(source2) {
104060
- return source2.snapshot?.manifest ?? join68(source2.materializedAt, "manifest.json");
104222
+ return source2.snapshot?.manifest ?? join69(source2.materializedAt, "manifest.json");
104061
104223
  }
104062
104224
  async function fileSourceDocumentSiteHint(input) {
104063
104225
  const detection = await detectDocumentSiteFiles({
@@ -104067,7 +104229,7 @@ async function fileSourceDocumentSiteHint(input) {
104067
104229
  let snapshotConfigured = false;
104068
104230
  const manifest = documentSourceManifestPath(input.source);
104069
104231
  try {
104070
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile50(join68(input.projectRoot, manifest), "utf8")), input.source.name);
104232
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile50(join69(input.projectRoot, manifest), "utf8")), input.source.name);
104071
104233
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
104072
104234
  } catch {
104073
104235
  snapshotConfigured = false;
@@ -104098,12 +104260,12 @@ async function larkSourceAgentViewWithNextAction(input) {
104098
104260
 
104099
104261
  // src/project/sourceDocumentStatus.ts
104100
104262
  function documentSourceManifestPath2(source2) {
104101
- return source2.snapshot?.manifest ?? join69(source2.materializedAt, "manifest.json");
104263
+ return source2.snapshot?.manifest ?? join70(source2.materializedAt, "manifest.json");
104102
104264
  }
104103
104265
  async function documentSnapshotState(input) {
104104
104266
  const manifest = documentSourceManifestPath2(input.source);
104105
- const manifestPath = join69(input.projectRoot, manifest);
104106
- if (!existsSync43(manifestPath)) {
104267
+ const manifestPath = join70(input.projectRoot, manifest);
104268
+ if (!existsSync44(manifestPath)) {
104107
104269
  return {
104108
104270
  snapshotReady: false,
104109
104271
  state: "needs-capture",
@@ -104181,7 +104343,7 @@ async function documentSnapshotState(input) {
104181
104343
  const missing = [
104182
104344
  ...parsed.files.map((file) => file.path),
104183
104345
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
104184
- ].find((path4) => !existsSync43(join69(input.projectRoot, input.source.materializedAt, path4)));
104346
+ ].find((path4) => !existsSync44(join70(input.projectRoot, input.source.materializedAt, path4)));
104185
104347
  if (missing !== undefined) {
104186
104348
  return {
104187
104349
  snapshotReady: false,
@@ -104253,7 +104415,7 @@ async function inspectDocumentSources(input) {
104253
104415
  // src/project/documentSourceRegistration.ts
104254
104416
  import { createHash as createHash27 } from "node:crypto";
104255
104417
  import { readFile as readFile52, realpath as realpath5 } from "node:fs/promises";
104256
- import { basename as basename12, extname as extname13, isAbsolute as isAbsolute13, join as join70, relative as relative21, resolve as resolve29 } from "node:path";
104418
+ import { basename as basename12, extname as extname13, isAbsolute as isAbsolute13, join as join71, relative as relative21, resolve as resolve29 } from "node:path";
104257
104419
  init_atomicWrite();
104258
104420
  init_cliFeedback();
104259
104421
  init_errors();
@@ -104354,7 +104516,7 @@ function assertSafeFileInclude(value) {
104354
104516
  }
104355
104517
  async function readRegistryDocument(projectRoot, registryPath2) {
104356
104518
  try {
104357
- const content3 = await readFile52(join70(projectRoot, registryPath2), "utf8");
104519
+ const content3 = await readFile52(join71(projectRoot, registryPath2), "utf8");
104358
104520
  return content3.trim().length === 0 ? { sources: [] } : import_yaml33.default.parse(content3);
104359
104521
  } catch (error) {
104360
104522
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -104472,7 +104634,7 @@ async function addFileSourceUnlocked(input) {
104472
104634
  const record2 = entry2;
104473
104635
  return record2.name !== input.name && record2.id !== input.name;
104474
104636
  }), nextEntry];
104475
- await atomicWriteFile(join70(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104637
+ await atomicWriteFile(join71(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104476
104638
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
104477
104639
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
104478
104640
  if (entry === undefined) {
@@ -104528,7 +104690,7 @@ async function addLarkSourceUnlocked(input) {
104528
104690
  const record2 = entry2;
104529
104691
  return record2.name !== input.name && record2.id !== input.name;
104530
104692
  }), nextEntry];
104531
- await atomicWriteFile(join70(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104693
+ await atomicWriteFile(join71(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104532
104694
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
104533
104695
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
104534
104696
  if (entry === undefined) {
@@ -104716,10 +104878,10 @@ async function registerSourceBatch(input) {
104716
104878
  }
104717
104879
 
104718
104880
  // src/project/sourceRemoval.ts
104719
- import { existsSync as existsSync44 } from "node:fs";
104881
+ import { existsSync as existsSync45 } from "node:fs";
104720
104882
  import { createHash as createHash28 } from "node:crypto";
104721
104883
  import { readFile as readFile53, readdir as readdir21, rm as rm19 } from "node:fs/promises";
104722
- import { isAbsolute as isAbsolute14, join as join71, relative as relative22, resolve as resolve30, sep as sep6 } from "node:path";
104884
+ import { isAbsolute as isAbsolute14, join as join72, relative as relative22, resolve as resolve30, sep as sep6 } from "node:path";
104723
104885
  var import_yaml34 = __toESM(require_dist3(), 1);
104724
104886
  init_atomicWrite();
104725
104887
  init_cliFeedback();
@@ -104758,8 +104920,8 @@ function collectStrings(value, output) {
104758
104920
  }
104759
104921
  }
104760
104922
  async function yamlReferences(input) {
104761
- const absolutePath = join71(input.projectRoot, input.path);
104762
- if (!existsSync44(absolutePath))
104923
+ const absolutePath = join72(input.projectRoot, input.path);
104924
+ if (!existsSync45(absolutePath))
104763
104925
  return false;
104764
104926
  const parsed = import_yaml34.default.parse(await readFile53(absolutePath, "utf8"));
104765
104927
  const strings = [];
@@ -104866,8 +105028,8 @@ function removeDocumentEntry(document4, source2) {
104866
105028
  }
104867
105029
  async function registryRemovalWrite(projectRoot, source2) {
104868
105030
  const path4 = registryPath2(source2.type);
104869
- const absolutePath = join71(projectRoot, path4);
104870
- const document4 = existsSync44(absolutePath) ? import_yaml34.default.parse(await readFile53(absolutePath, "utf8")) : { sources: [] };
105031
+ const absolutePath = join72(projectRoot, path4);
105032
+ const document4 = existsSync45(absolutePath) ? import_yaml34.default.parse(await readFile53(absolutePath, "utf8")) : { sources: [] };
104871
105033
  return {
104872
105034
  path: absolutePath,
104873
105035
  bytes: import_yaml34.default.stringify(removeDocumentEntry(document4, source2))
@@ -104885,7 +105047,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
104885
105047
  return absolute;
104886
105048
  }
104887
105049
  function safeManagedManifestPath(projectRoot, source2) {
104888
- const manifest = source2.manifest ?? join71(source2.materializedAt, "manifest.json");
105050
+ const manifest = source2.manifest ?? join72(source2.materializedAt, "manifest.json");
104889
105051
  if (isAbsolute14(manifest))
104890
105052
  throw unsafeOwnership(source2, manifest);
104891
105053
  const absolute = resolve30(projectRoot, manifest);
@@ -104991,7 +105153,7 @@ async function createRemovalPlan(projectRoot, selector) {
104991
105153
  }
104992
105154
  } else {
104993
105155
  const materializedPath = safeManagedMaterializedPath(projectRoot, source2);
104994
- if (materializedPath !== undefined && sharedMaterializedBy.length === 0 && existsSync44(materializedPath)) {
105156
+ if (materializedPath !== undefined && sharedMaterializedBy.length === 0 && existsSync45(materializedPath)) {
104995
105157
  absoluteRemovals.push(materializedPath);
104996
105158
  cleanup = {
104997
105159
  mode: "exclusive-materialization",
@@ -105037,9 +105199,9 @@ function publicRemovalResult(plan, action) {
105037
105199
  };
105038
105200
  }
105039
105201
  async function pruneExtractRuntime(projectRoot, source2) {
105040
- const fingerprintPath = join71(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
105202
+ const fingerprintPath = join72(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
105041
105203
  const removedPhaseIds = new Set;
105042
- if (existsSync44(fingerprintPath)) {
105204
+ if (existsSync45(fingerprintPath)) {
105043
105205
  const parsed = JSON.parse(await readFile53(fingerprintPath, "utf8"));
105044
105206
  const phases = parsed.phases ?? {};
105045
105207
  const next = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
@@ -105054,20 +105216,20 @@ async function pruneExtractRuntime(projectRoot, source2) {
105054
105216
  await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next }, null, 2)}
105055
105217
  `);
105056
105218
  }
105057
- const symbolPath = join71(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
105058
- if (existsSync44(symbolPath)) {
105219
+ const symbolPath = join72(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
105220
+ if (existsSync45(symbolPath)) {
105059
105221
  const parsed = JSON.parse(await readFile53(symbolPath, "utf8"));
105060
105222
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
105061
105223
  const phaseFingerprints = Object.fromEntries(Object.entries(parsed.phaseFingerprints ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
105062
105224
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
105063
105225
  `);
105064
105226
  }
105065
- const snapshotRoot = join71(projectRoot, ".tmp/context-runtime/extract/candidates");
105227
+ const snapshotRoot = join72(projectRoot, ".tmp/context-runtime/extract/candidates");
105066
105228
  const visit3 = async (directory) => {
105067
- if (!existsSync44(directory))
105229
+ if (!existsSync45(directory))
105068
105230
  return;
105069
105231
  for (const entry of await readdir21(directory, { withFileTypes: true })) {
105070
- const path4 = join71(directory, entry.name);
105232
+ const path4 = join72(directory, entry.name);
105071
105233
  if (entry.isDirectory()) {
105072
105234
  await visit3(path4);
105073
105235
  continue;
@@ -105117,7 +105279,7 @@ async function removeProjectSource(input) {
105117
105279
  });
105118
105280
  }
105119
105281
  await applyAtomicFileBatch({
105120
- transactionRoot: join71(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
105282
+ transactionRoot: join72(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
105121
105283
  writes: [plan.registryWrite, ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
105122
105284
  removals: plan.absoluteRemovals
105123
105285
  });
@@ -105515,16 +105677,147 @@ the CLI derives a lowercase path-safe module and rejects duplicate batch identit
105515
105677
  });
105516
105678
  }
105517
105679
 
105680
+ // src/cli.ts
105681
+ init_debugTrace();
105682
+
105683
+ // src/registerProjectLifecycleCommands.ts
105684
+ init_cliFeedback();
105685
+ init_errors();
105686
+ init_workspace();
105687
+ init_exitCode();
105688
+ function registerProjectInitCommand(program2) {
105689
+ program2.command("init [project-dir]").description("Initialize a project-local context workspace").option("--name <name>", "display/package name override").option("--language <language>", "workspace and starter-template language: en | zh-CN").option("--dev", "initialize with the locally linked @c4a/context SDK").option("--debug", "enable workspace-local command and Agent Graph tracing").option("--allow-nonempty", "after explicit confirmation, preserve existing files and initialize inside a non-empty non-Context directory").action(async (projectDir, options) => {
105690
+ const targetRoot = resolveContextProjectInitTarget(process.cwd(), projectDir);
105691
+ const wasContextWorkspace = isContextProjectRoot(targetRoot);
105692
+ const result = await initContextProject({
105693
+ cwd: process.cwd(),
105694
+ ...projectDir !== undefined ? { projectDir } : {},
105695
+ ...typeof options.name === "string" ? { name: options.name } : {},
105696
+ ...typeof options.language === "string" ? { language: projectLanguage(options.language) } : {},
105697
+ ...options.dev === true ? { dev: true } : {},
105698
+ ...options.debug === true ? { debug: true } : {},
105699
+ ...options.allowNonempty === true ? { allowNonempty: true } : {}
105700
+ });
105701
+ process.stdout.write(formatProjectInitResult(result));
105702
+ if (!wasContextWorkspace) {
105703
+ queueContextRuntimeEvent({
105704
+ cwd: result.projectRoot,
105705
+ kind: "workspace.initialized",
105706
+ properties: {
105707
+ init_mode: result.kept.length > 0 ? "nonempty_existing" : "new",
105708
+ language: result.language,
105709
+ created_file_count: result.created.length
105710
+ }
105711
+ });
105712
+ }
105713
+ });
105714
+ }
105715
+ function registerProjectStatusCommand(program2) {
105716
+ program2.command("status").description("Print workspace overview and suggested next actions").option("--format <format>", "output format: table | json", "table").option("--view <view>", "with --format json, output view: summary | full", "summary").option("--managed", "use explicit current-conversation managed approval for this status loop").option("--resource-receipts <json-or-@file>", "current-conversation Agent Graph resource read receipts").addOption(new Option("--authority <authority>", "current-conversation scoped authority granted by the user; repeatable").argParser(collectWorkflowAuthorityOption).default([])).action(async (options) => {
105717
+ const rootOptions = program2.opts();
105718
+ const resourceReceiptsReference = typeof options.resourceReceipts === "string" ? options.resourceReceipts : typeof rootOptions.workflowResourceReceipts === "string" ? rootOptions.workflowResourceReceipts : undefined;
105719
+ const resourceReceipts = resourceReceiptsReference !== undefined ? await parseWorkflowResourceReceipts(resourceReceiptsReference, process.cwd()) : undefined;
105720
+ if (await runProjectStatusCommand({
105721
+ cwd: process.cwd(),
105722
+ format: options.format === "json" ? "json" : "table",
105723
+ view: options.view === "full" ? "full" : "summary",
105724
+ managed: options.managed === true,
105725
+ authorities: workflowAuthorities(options.authority),
105726
+ ...resourceReceipts === undefined ? {} : { resourceReceipts },
105727
+ ...resourceReceiptsReference === undefined ? {} : { resourceReceiptsReference },
105728
+ onSuccess: (status) => {
105729
+ queueContextRuntimeEvent({
105730
+ cwd: status.projectRoot,
105731
+ kind: "workspace.active",
105732
+ properties: { workflow_status: status.workflow.status }
105733
+ });
105734
+ }
105735
+ })) {
105736
+ return;
105737
+ }
105738
+ throw new ContextError(ExitCode.WorkspaceStateError, "status requires a context project workspace", {
105739
+ category: ErrorCategory.WorkspaceNotFound
105740
+ });
105741
+ });
105742
+ }
105743
+ function registerProjectCloseAndBuildCommands(program2) {
105744
+ program2.command("close").description("Close approved project knowledge by deriving structure and running final verification").option("--format <format>", "output format: text | json", "text").action(async (options) => {
105745
+ if (options.format !== "text" && options.format !== "json") {
105746
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
105747
+ category: ErrorCategory.UserInputInvalid
105748
+ });
105749
+ }
105750
+ if (await runProjectCloseCommand({
105751
+ cwd: process.cwd(),
105752
+ format: options.format === "json" ? "json" : "text"
105753
+ })) {
105754
+ return;
105755
+ }
105756
+ throw new ContextError(ExitCode.WorkspaceStateError, "close requires a context project workspace", {
105757
+ category: ErrorCategory.WorkspaceNotFound
105758
+ });
105759
+ });
105760
+ program2.command("build").description("Build declared project packages").option("--format <format>", "output format: text | json", "text").option("--verbose", "include per-file build changes in JSON output").action(async (options) => {
105761
+ if (options.format !== "text" && options.format !== "json") {
105762
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
105763
+ category: ErrorCategory.UserInputInvalid
105764
+ });
105765
+ }
105766
+ if (await runProjectBuildCommand({
105767
+ cwd: process.cwd(),
105768
+ format: options.format === "json" ? "json" : "text",
105769
+ verbose: options.verbose === true
105770
+ })) {
105771
+ return;
105772
+ }
105773
+ throw new ContextError(ExitCode.WorkspaceStateError, "build requires a context project workspace", {
105774
+ category: ErrorCategory.WorkspaceNotFound
105775
+ });
105776
+ });
105777
+ }
105778
+ function registerProjectVerifyCommand(program2) {
105779
+ program2.command("verify").description("Validate knowledge workspace").option("--format <format>", "output format: table | json", "table").option("--compact", "return grouped diagnostics without the complete issue list").option("--view <view>", "read a verification view: diagnostics").option("--page-size <n>", "with --view diagnostics, limit returned issues").option("--page-token <token>", "with --view diagnostics, continue pagination").action(async (options) => {
105780
+ if (options.format !== "table" && options.format !== "json") {
105781
+ throw new ContextError(ExitCode.UserError, "--format must be table or json", {
105782
+ category: ErrorCategory.UserInputInvalid
105783
+ });
105784
+ }
105785
+ if (options.view !== undefined && options.view !== "diagnostics") {
105786
+ throw new ContextError(ExitCode.UserError, "--view must be diagnostics", {
105787
+ category: ErrorCategory.UserInputInvalid
105788
+ });
105789
+ }
105790
+ if (options.view === "diagnostics" && options.format !== "json") {
105791
+ throw new ContextError(ExitCode.UserError, "--view diagnostics requires --format json", {
105792
+ category: ErrorCategory.UserInputInvalid
105793
+ });
105794
+ }
105795
+ if (await runProjectVerifyCommand({
105796
+ cwd: process.cwd(),
105797
+ format: options.format === "json" ? "json" : "table",
105798
+ ...options.compact === true ? { compact: true } : {},
105799
+ ...options.view === "diagnostics" ? { view: "diagnostics" } : {},
105800
+ ...typeof options.pageSize === "string" ? { pageSize: options.pageSize } : {},
105801
+ ...typeof options.pageToken === "string" ? { pageToken: options.pageToken } : {}
105802
+ })) {
105803
+ return;
105804
+ }
105805
+ throw new ContextError(ExitCode.WorkspaceStateError, "verify requires a context project workspace", {
105806
+ category: ErrorCategory.WorkspaceNotFound
105807
+ });
105808
+ });
105809
+ }
105810
+
105518
105811
  // src/project/pluginInstall.ts
105519
105812
  init_cliFeedback();
105520
105813
  init_errors();
105521
105814
  init_exitCode();
105522
- import { existsSync as existsSync45 } from "node:fs";
105815
+ import { existsSync as existsSync46 } from "node:fs";
105523
105816
  import { cp, mkdir as mkdir32, readdir as readdir22, readFile as readFile55, rename as rename5, rm as rm20, writeFile as writeFile27 } from "node:fs/promises";
105524
105817
  import { execFile as execFile7 } from "node:child_process";
105525
105818
  import { homedir as homedir2 } from "node:os";
105526
- import { dirname as dirname41, join as join72, resolve as resolve32 } from "node:path";
105527
- import { fileURLToPath as fileURLToPath8 } from "node:url";
105819
+ import { dirname as dirname42, join as join73, resolve as resolve32 } from "node:path";
105820
+ import { fileURLToPath as fileURLToPath9 } from "node:url";
105528
105821
  import { promisify as promisify7 } from "node:util";
105529
105822
  var execFileAsync7 = promisify7(execFile7);
105530
105823
  var MARKETPLACE_NAME = "c4a";
@@ -105563,10 +105856,10 @@ function pluginAgentOption(value) {
105563
105856
  }
105564
105857
  function packageCandidateDirs() {
105565
105858
  const dirs = [];
105566
- let dir = dirname41(fileURLToPath8(import.meta.url));
105859
+ let dir = dirname42(fileURLToPath9(import.meta.url));
105567
105860
  for (let index2 = 0;index2 < 8; index2++) {
105568
105861
  dirs.push(dir);
105569
- const parent = dirname41(dir);
105862
+ const parent = dirname42(dir);
105570
105863
  if (parent === dir)
105571
105864
  break;
105572
105865
  dir = parent;
@@ -105579,13 +105872,13 @@ function pluginRootCandidates() {
105579
105872
  return [resolve32(envRoot)];
105580
105873
  const candidates = [];
105581
105874
  for (const dir of packageCandidateDirs()) {
105582
- candidates.push(join72(dir, "plugins"));
105583
- candidates.push(join72(dir, "dist", "plugins"));
105875
+ candidates.push(join73(dir, "plugins"));
105876
+ candidates.push(join73(dir, "dist", "plugins"));
105584
105877
  }
105585
105878
  return [...new Set(candidates)];
105586
105879
  }
105587
105880
  function isInstallablePluginRoot(root2) {
105588
- return existsSync45(join72(root2, ".claude-plugin", "marketplace.json")) && existsSync45(join72(root2, ".agents", "plugins", "marketplace.json")) && existsSync45(join72(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync45(join72(root2, "codex", ".codex-plugin", "plugin.json"));
105881
+ return existsSync46(join73(root2, ".claude-plugin", "marketplace.json")) && existsSync46(join73(root2, ".agents", "plugins", "marketplace.json")) && existsSync46(join73(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync46(join73(root2, "codex", ".codex-plugin", "plugin.json"));
105589
105882
  }
105590
105883
  function resolveBundledPluginsRoot() {
105591
105884
  const candidates = pluginRootCandidates();
@@ -105650,14 +105943,14 @@ function failedAgentResult(agent, error) {
105650
105943
  };
105651
105944
  }
105652
105945
  function codexHome() {
105653
- return process.env.CODEX_HOME?.trim() || join72(homedir2(), ".codex");
105946
+ return process.env.CODEX_HOME?.trim() || join73(homedir2(), ".codex");
105654
105947
  }
105655
105948
  function claudePluginCacheRoot() {
105656
105949
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
105657
105950
  if (explicitRoot)
105658
105951
  return explicitRoot;
105659
105952
  const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
105660
- return join72(home, ".claude", "plugins", "cache");
105953
+ return join73(home, ".claude", "plugins", "cache");
105661
105954
  }
105662
105955
  function blockHeader(line) {
105663
105956
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -105708,7 +106001,7 @@ function pruneLegacyCodexConfigContent(content3) {
105708
106001
  `), removed };
105709
106002
  }
105710
106003
  async function pruneLegacyCodexConfig(dryRun, steps) {
105711
- const configPath = join72(codexHome(), "config.toml");
106004
+ const configPath = join73(codexHome(), "config.toml");
105712
106005
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105713
106006
  if (!current2)
105714
106007
  return;
@@ -105725,8 +106018,8 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
105725
106018
  }
105726
106019
  }
105727
106020
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
105728
- const cacheRoot = join72(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
105729
- if (!existsSync45(cacheRoot))
106021
+ const cacheRoot = join73(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
106022
+ if (!existsSync46(cacheRoot))
105730
106023
  return;
105731
106024
  const versions = (await readdir22(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
105732
106025
  if (versions.length === 0)
@@ -105737,7 +106030,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
105737
106030
  status: dryRun ? "planned" : "ran"
105738
106031
  });
105739
106032
  if (!dryRun)
105740
- await Promise.all(versions.map((version3) => rm20(join72(cacheRoot, version3), { recursive: true, force: true })));
106033
+ await Promise.all(versions.map((version3) => rm20(join73(cacheRoot, version3), { recursive: true, force: true })));
105741
106034
  }
105742
106035
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
105743
106036
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -105754,22 +106047,22 @@ async function isEmptyDir2(dir) {
105754
106047
  }
105755
106048
  async function pruneClaudeOrphanContextCache(dryRun, steps) {
105756
106049
  const cacheRoot = claudePluginCacheRoot();
105757
- if (!existsSync45(cacheRoot))
106050
+ if (!existsSync46(cacheRoot))
105758
106051
  return;
105759
106052
  const removed = [];
105760
106053
  const marketplaces = await readdir22(cacheRoot, { withFileTypes: true }).catch(() => []);
105761
106054
  for (const marketplace of marketplaces) {
105762
106055
  if (!marketplace.isDirectory())
105763
106056
  continue;
105764
- const pluginDir = join72(cacheRoot, marketplace.name, PLUGIN_NAME);
105765
- if (!existsSync45(pluginDir))
106057
+ const pluginDir = join73(cacheRoot, marketplace.name, PLUGIN_NAME);
106058
+ if (!existsSync46(pluginDir))
105766
106059
  continue;
105767
106060
  const versions = await readdir22(pluginDir, { withFileTypes: true }).catch(() => []);
105768
106061
  for (const version3 of versions) {
105769
106062
  if (!version3.isDirectory())
105770
106063
  continue;
105771
- const versionDir = join72(pluginDir, version3.name);
105772
- if (!existsSync45(join72(versionDir, ORPHAN_MARKER2)))
106064
+ const versionDir = join73(pluginDir, version3.name);
106065
+ if (!existsSync46(join73(versionDir, ORPHAN_MARKER2)))
105773
106066
  continue;
105774
106067
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
105775
106068
  if (!dryRun) {
@@ -105779,7 +106072,7 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
105779
106072
  if (!dryRun && await isEmptyDir2(pluginDir)) {
105780
106073
  await rm20(pluginDir, { recursive: true, force: true });
105781
106074
  }
105782
- const marketplaceDir = join72(cacheRoot, marketplace.name);
106075
+ const marketplaceDir = join73(cacheRoot, marketplace.name);
105783
106076
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
105784
106077
  await rm20(marketplaceDir, { recursive: true, force: true });
105785
106078
  }
@@ -105796,12 +106089,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
105796
106089
  if (LEGACY_PLUGIN_NAMES.length === 0)
105797
106090
  return;
105798
106091
  const cacheRoot = claudePluginCacheRoot();
105799
- if (!existsSync45(cacheRoot))
106092
+ if (!existsSync46(cacheRoot))
105800
106093
  return;
105801
106094
  const removed = [];
105802
106095
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
105803
- const pluginDir = join72(cacheRoot, MARKETPLACE_NAME, pluginName);
105804
- if (!existsSync45(pluginDir))
106096
+ const pluginDir = join73(cacheRoot, MARKETPLACE_NAME, pluginName);
106097
+ if (!existsSync46(pluginDir))
105805
106098
  continue;
105806
106099
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
105807
106100
  if (!dryRun) {
@@ -105817,11 +106110,11 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
105817
106110
  }
105818
106111
  }
105819
106112
  async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
105820
- const manifest = await readFile55(join72(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
106113
+ const manifest = await readFile55(join73(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
105821
106114
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
105822
106115
  if (!currentVersion)
105823
106116
  return;
105824
- const pluginDir = join72(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
106117
+ const pluginDir = join73(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
105825
106118
  const staleVersions = (await readdir22(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
105826
106119
  if (staleVersions.length === 0)
105827
106120
  return;
@@ -105831,7 +106124,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
105831
106124
  status: dryRun ? "planned" : "ran"
105832
106125
  });
105833
106126
  if (!dryRun) {
105834
- await Promise.all(staleVersions.map((version3) => rm20(join72(pluginDir, version3), { recursive: true, force: true })));
106127
+ await Promise.all(staleVersions.map((version3) => rm20(join73(pluginDir, version3), { recursive: true, force: true })));
105835
106128
  }
105836
106129
  }
105837
106130
  function enableCodexPluginConfig(content3) {
@@ -105895,8 +106188,8 @@ source = ${JSON.stringify(root2)}
105895
106188
  `;
105896
106189
  }
105897
106190
  async function ensureCodexPluginEnabled() {
105898
- const configPath = join72(codexHome(), "config.toml");
105899
- await mkdir32(dirname41(configPath), { recursive: true });
106191
+ const configPath = join73(codexHome(), "config.toml");
106192
+ await mkdir32(dirname42(configPath), { recursive: true });
105900
106193
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105901
106194
  const next = enableCodexPluginConfig(current2);
105902
106195
  if (next !== current2) {
@@ -105904,8 +106197,8 @@ async function ensureCodexPluginEnabled() {
105904
106197
  }
105905
106198
  }
105906
106199
  async function ensureCodexLocalMarketplace(root2) {
105907
- const configPath = join72(codexHome(), "config.toml");
105908
- await mkdir32(dirname41(configPath), { recursive: true });
106200
+ const configPath = join73(codexHome(), "config.toml");
106201
+ await mkdir32(dirname42(configPath), { recursive: true });
105909
106202
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105910
106203
  const next = upsertCodexLocalMarketplaceConfig(current2, root2);
105911
106204
  if (next !== current2) {
@@ -105913,7 +106206,7 @@ async function ensureCodexLocalMarketplace(root2) {
105913
106206
  }
105914
106207
  }
105915
106208
  async function codexPluginVersion(root2) {
105916
- const manifestPath = join72(root2, "codex", ".codex-plugin", "plugin.json");
106209
+ const manifestPath = join73(root2, "codex", ".codex-plugin", "plugin.json");
105917
106210
  const manifest = JSON.parse(await readFile55(manifestPath, "utf8"));
105918
106211
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
105919
106212
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
@@ -105921,10 +106214,10 @@ async function codexPluginVersion(root2) {
105921
106214
  return manifest.version;
105922
106215
  }
105923
106216
  function codexPluginCacheDir(version3) {
105924
- return join72(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
106217
+ return join73(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
105925
106218
  }
105926
106219
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105927
- const source2 = join72(root2, "codex");
106220
+ const source2 = join73(root2, "codex");
105928
106221
  const target = codexPluginCacheDir(version3);
105929
106222
  steps.push({
105930
106223
  agent: "codex",
@@ -105933,12 +106226,12 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105933
106226
  });
105934
106227
  if (dryRun)
105935
106228
  return;
105936
- await mkdir32(dirname41(target), { recursive: true });
106229
+ await mkdir32(dirname42(target), { recursive: true });
105937
106230
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
105938
106231
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
105939
106232
  await rm20(temporary, { recursive: true, force: true });
105940
106233
  await cp(source2, temporary, { recursive: true, force: true });
105941
- const hadPrevious = existsSync45(target);
106234
+ const hadPrevious = existsSync46(target);
105942
106235
  try {
105943
106236
  if (hadPrevious)
105944
106237
  await rename5(target, previous3);
@@ -105947,7 +106240,7 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105947
106240
  await rm20(previous3, { recursive: true, force: true });
105948
106241
  } catch (error) {
105949
106242
  await rm20(temporary, { recursive: true, force: true });
105950
- if (hadPrevious && !existsSync45(target) && existsSync45(previous3))
106243
+ if (hadPrevious && !existsSync46(target) && existsSync46(previous3))
105951
106244
  await rename5(previous3, target);
105952
106245
  throw error;
105953
106246
  }
@@ -105982,12 +106275,12 @@ async function installCodex(root2, dryRun, steps) {
105982
106275
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
105983
106276
  steps.push({
105984
106277
  agent: "codex",
105985
- command: `ensure ${shellQuote9(join72(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
106278
+ command: `ensure ${shellQuote9(join73(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
105986
106279
  status: dryRun ? "planned" : "ran"
105987
106280
  });
105988
106281
  steps.push({
105989
106282
  agent: "codex",
105990
- command: `ensure ${shellQuote9(join72(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
106283
+ command: `ensure ${shellQuote9(join73(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
105991
106284
  status: dryRun ? "planned" : "ran"
105992
106285
  });
105993
106286
  if (dryRun) {
@@ -106098,8 +106391,75 @@ function formatPluginInstallResult(result) {
106098
106391
  });
106099
106392
  }
106100
106393
 
106394
+ // src/registerPluginCommands.ts
106395
+ function registerPluginCommands(program2) {
106396
+ const plugin = program2.command("plugin").description("Install or inspect global Context agent plugins");
106397
+ plugin.command("path").description("Print the bundled plugin marketplace root used by `context plugin install`").action(async () => {
106398
+ process.stdout.write(formatPluginPathResult(await runPluginPathCommand()));
106399
+ });
106400
+ plugin.command("status").description("Inspect the bundled plugin marketplace root and global agent availability").option("--agent <agent>", "agent target: claude | codex | all", "all").action(async (options) => {
106401
+ const agent = pluginAgentOption(options.agent);
106402
+ process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
106403
+ });
106404
+ plugin.command("install").description("Install the bundled Context plugin globally for Claude and/or Codex").option("--agent <agent>", "agent target: claude | codex | all", "all").option("--dry-run", "Print install commands without mutating global agent config").action(async (options) => {
106405
+ const agent = pluginAgentOption(options.agent);
106406
+ const result = await runPluginInstallCommand({
106407
+ agent,
106408
+ dryRun: options.dryRun === true
106409
+ });
106410
+ process.stdout.write(formatPluginInstallResult(result));
106411
+ });
106412
+ }
106413
+
106414
+ // src/registerPackageCommands.ts
106415
+ init_cliFeedback();
106416
+ init_errors();
106417
+ init_packageTemplateReview();
106418
+ init_workspace();
106419
+ init_exitCode();
106420
+ function registerPackageCommands(program2) {
106421
+ const packageCommand = program2.command("package").description("Inspect or resolve package output configuration");
106422
+ const packageTemplate = packageCommand.command("template").description("Manage package template review state");
106423
+ packageTemplate.command("accept [package-name]").description("Explicitly accept an unchanged generated starter template").option("--all", "accept all unchanged generated starter templates").option("--format <format>", "output format: text | json", "text").action(async (packageName, options) => {
106424
+ if (packageName === undefined === (options.all !== true)) {
106425
+ throw new ContextError(ExitCode.UserError, "provide one package name or --all", { category: ErrorCategory.UserInputInvalid });
106426
+ }
106427
+ if (options.format !== "text" && options.format !== "json") {
106428
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106429
+ category: ErrorCategory.UserInputInvalid
106430
+ });
106431
+ }
106432
+ const found = findContextProjectRoot(process.cwd());
106433
+ if (!found) {
106434
+ throw new ContextError(ExitCode.WorkspaceStateError, "package template acceptance requires a context project workspace", { category: ErrorCategory.WorkspaceNotFound });
106435
+ }
106436
+ const result = await acceptStarterPackageTemplates({
106437
+ projectRoot: found.projectRoot,
106438
+ ...packageName === undefined ? {} : { packageNames: [packageName] }
106439
+ });
106440
+ if (options.format === "json") {
106441
+ process.stdout.write(`${JSON.stringify({
106442
+ action: "package-template-accepted",
106443
+ ...result,
106444
+ next_action: {
106445
+ kind: "reevaluate-workspace",
106446
+ command: "context status --format json"
106447
+ }
106448
+ }, null, 2)}
106449
+ `);
106450
+ } else {
106451
+ process.stdout.write(formatFeedback({
106452
+ symbol: "✓",
106453
+ action: "accepted",
106454
+ subject: result.accepted.join(", ") || "package templates",
106455
+ headline: "starter package template",
106456
+ body: result.alreadyResolved.length === 0 ? [] : [`already resolved: ${result.alreadyResolved.join(", ")}`]
106457
+ }));
106458
+ }
106459
+ });
106460
+ }
106461
+
106101
106462
  // src/cli.ts
106102
- init_debugTrace();
106103
106463
  var TOP_LEVEL_COMMANDS = new Set([
106104
106464
  "init",
106105
106465
  "plugin",
@@ -106135,14 +106495,14 @@ function inferErrorCategory(message) {
106135
106495
  }
106136
106496
  function readPackageVersion() {
106137
106497
  try {
106138
- let dir = dirname42(fileURLToPath9(import.meta.url));
106498
+ let dir = dirname43(fileURLToPath10(import.meta.url));
106139
106499
  for (let i2 = 0;i2 < 8; i2++) {
106140
- const pkg = join73(dir, "package.json");
106141
- if (existsSync46(pkg)) {
106142
- const parsed = JSON.parse(readFileSync9(pkg, "utf8"));
106500
+ const pkg = join74(dir, "package.json");
106501
+ if (existsSync47(pkg)) {
106502
+ const parsed = JSON.parse(readFileSync10(pkg, "utf8"));
106143
106503
  return parsed.version ?? "unknown";
106144
106504
  }
106145
- const parent = dirname42(dir);
106505
+ const parent = dirname43(dir);
106146
106506
  if (parent === dir)
106147
106507
  break;
106148
106508
  dir = parent;
@@ -106152,21 +106512,21 @@ function readPackageVersion() {
106152
106512
  }
106153
106513
  function readQuickstartPath() {
106154
106514
  try {
106155
- let dir = dirname42(fileURLToPath9(import.meta.url));
106515
+ let dir = dirname43(fileURLToPath10(import.meta.url));
106156
106516
  for (let i2 = 0;i2 < 8; i2++) {
106157
- const candidate = join73(dir, "docs", "quickstart.md");
106158
- if (existsSync46(candidate))
106517
+ const candidate = join74(dir, "docs", "quickstart.md");
106518
+ if (existsSync47(candidate))
106159
106519
  return candidate;
106160
- const pkg = join73(dir, "package.json");
106161
- if (existsSync46(pkg))
106520
+ const pkg = join74(dir, "package.json");
106521
+ if (existsSync47(pkg))
106162
106522
  return candidate;
106163
- const parent = dirname42(dir);
106523
+ const parent = dirname43(dir);
106164
106524
  if (parent === dir)
106165
106525
  break;
106166
106526
  dir = parent;
106167
106527
  }
106168
106528
  } catch {}
106169
- return join73(dirname42(fileURLToPath9(import.meta.url)), "docs", "quickstart.md");
106529
+ return join74(dirname43(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
106170
106530
  }
106171
106531
  var GREEN = "\x1B[32m";
106172
106532
  var RESET = "\x1B[0m";
@@ -106251,94 +106611,12 @@ function createCliProgram() {
106251
106611
  });
106252
106612
  const baseHelpInformation = program2.helpInformation.bind(program2);
106253
106613
  program2.helpInformation = () => `${headerHelpText()}${baseHelpInformation()}${quickstartHelpText()}`;
106254
- program2.command("init [project-dir]").description("Initialize a project-local context workspace").option("--name <name>", "display/package name override").option("--language <language>", "workspace and starter-template language: en | zh-CN").option("--dev", "initialize with the locally linked @c4a/context SDK").option("--debug", "enable workspace-local command and Agent Graph tracing").option("--allow-nonempty", "after explicit confirmation, preserve existing files and initialize inside a non-empty non-Context directory").action(async (projectDir, options) => {
106255
- const result = await initContextProject({
106256
- cwd: process.cwd(),
106257
- ...projectDir !== undefined ? { projectDir } : {},
106258
- ...typeof options.name === "string" ? { name: options.name } : {},
106259
- ...typeof options.language === "string" ? { language: projectLanguage(options.language) } : {},
106260
- ...options.dev === true ? { dev: true } : {},
106261
- ...options.debug === true ? { debug: true } : {},
106262
- ...options.allowNonempty === true ? { allowNonempty: true } : {}
106263
- });
106264
- process.stdout.write(formatProjectInitResult(result));
106265
- });
106266
- const plugin = program2.command("plugin").description("Install or inspect global Context agent plugins");
106614
+ registerProjectInitCommand(program2);
106615
+ registerPluginCommands(program2);
106267
106616
  registerDebugCommands(program2);
106268
- plugin.command("path").description("Print the bundled plugin marketplace root used by `context plugin install`").action(async () => {
106269
- process.stdout.write(formatPluginPathResult(await runPluginPathCommand()));
106270
- });
106271
- plugin.command("status").description("Inspect the bundled plugin marketplace root and global agent availability").option("--agent <agent>", "agent target: claude | codex | all", "all").action(async (options) => {
106272
- const agent = pluginAgentOption(options.agent);
106273
- process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
106274
- });
106275
- plugin.command("install").description("Install the bundled Context plugin globally for Claude and/or Codex").option("--agent <agent>", "agent target: claude | codex | all", "all").option("--dry-run", "Print install commands without mutating global agent config").action(async (options) => {
106276
- const agent = pluginAgentOption(options.agent);
106277
- const result = await runPluginInstallCommand({
106278
- agent,
106279
- dryRun: options.dryRun === true
106280
- });
106281
- process.stdout.write(formatPluginInstallResult(result));
106282
- });
106283
106617
  registerContextWorkflowResourceCommands(program2);
106284
- const packageCommand = program2.command("package").description("Inspect or resolve package output configuration");
106285
- const packageTemplate = packageCommand.command("template").description("Manage package template review state");
106286
- packageTemplate.command("accept [package-name]").description("Explicitly accept an unchanged generated starter template").option("--all", "accept all unchanged generated starter templates").option("--format <format>", "output format: text | json", "text").action(async (packageName, options) => {
106287
- if (packageName === undefined === (options.all !== true)) {
106288
- throw new ContextError(ExitCode.UserError, "provide one package name or --all", { category: ErrorCategory.UserInputInvalid });
106289
- }
106290
- if (options.format !== "text" && options.format !== "json") {
106291
- throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106292
- category: ErrorCategory.UserInputInvalid
106293
- });
106294
- }
106295
- const found = findContextProjectRoot(process.cwd());
106296
- if (!found) {
106297
- throw new ContextError(ExitCode.WorkspaceStateError, "package template acceptance requires a context project workspace", { category: ErrorCategory.WorkspaceNotFound });
106298
- }
106299
- const result = await acceptStarterPackageTemplates({
106300
- projectRoot: found.projectRoot,
106301
- ...packageName === undefined ? {} : { packageNames: [packageName] }
106302
- });
106303
- if (options.format === "json") {
106304
- process.stdout.write(`${JSON.stringify({
106305
- action: "package-template-accepted",
106306
- ...result,
106307
- next_action: {
106308
- kind: "reevaluate-workspace",
106309
- command: "context status --format json"
106310
- }
106311
- }, null, 2)}
106312
- `);
106313
- } else {
106314
- process.stdout.write(formatFeedback({
106315
- symbol: "✓",
106316
- action: "accepted",
106317
- subject: result.accepted.join(", ") || "package templates",
106318
- headline: "starter package template",
106319
- body: result.alreadyResolved.length === 0 ? [] : [`already resolved: ${result.alreadyResolved.join(", ")}`]
106320
- }));
106321
- }
106322
- });
106323
- program2.command("status").description("Print workspace overview and suggested next actions").option("--format <format>", "output format: table | json", "table").option("--view <view>", "with --format json, output view: summary | full", "summary").option("--managed", "use explicit current-conversation managed approval for this status loop").option("--resource-receipts <json-or-@file>", "current-conversation Agent Graph resource read receipts").addOption(new Option("--authority <authority>", "current-conversation scoped authority granted by the user; repeatable").argParser(collectWorkflowAuthorityOption).default([])).action(async (options) => {
106324
- const rootOptions = program2.opts();
106325
- const resourceReceiptsReference = typeof options.resourceReceipts === "string" ? options.resourceReceipts : typeof rootOptions.workflowResourceReceipts === "string" ? rootOptions.workflowResourceReceipts : undefined;
106326
- const resourceReceipts = resourceReceiptsReference !== undefined ? await parseWorkflowResourceReceipts(resourceReceiptsReference, process.cwd()) : undefined;
106327
- if (await runProjectStatusCommand({
106328
- cwd: process.cwd(),
106329
- format: options.format === "json" ? "json" : "table",
106330
- view: options.view === "full" ? "full" : "summary",
106331
- managed: options.managed === true,
106332
- authorities: workflowAuthorities(options.authority),
106333
- ...resourceReceipts === undefined ? {} : { resourceReceipts },
106334
- ...resourceReceiptsReference === undefined ? {} : { resourceReceiptsReference }
106335
- })) {
106336
- return;
106337
- }
106338
- throw new ContextError(ExitCode.WorkspaceStateError, "status requires a context project workspace", {
106339
- category: ErrorCategory.WorkspaceNotFound
106340
- });
106341
- });
106618
+ registerPackageCommands(program2);
106619
+ registerProjectStatusCommand(program2);
106342
106620
  registerProjectRunCommand(program2, import.meta.url);
106343
106621
  const review = program2.command("review").description("Review draft project candidates and apply approval decisions");
106344
106622
  review.command("html [collection]").description("Render a self-contained local review HTML page").option("--all", "review all draft candidates across internal collections").option("--out <file>", "output HTML path, defaults to .tmp/context-runtime/review/<collection>.html").option("--open", "open the generated HTML with the system default browser").option("--format <format>", "output format: text | json", "text").action(async (collection, options) => {
@@ -106486,70 +106764,9 @@ function createCliProgram() {
106486
106764
  format: options.format === "json" ? "json" : "text"
106487
106765
  });
106488
106766
  });
106489
- program2.command("close").description("Close approved project knowledge by deriving structure and running final verification").option("--format <format>", "output format: text | json", "text").action(async (options) => {
106490
- if (options.format !== "text" && options.format !== "json") {
106491
- throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106492
- category: ErrorCategory.UserInputInvalid
106493
- });
106494
- }
106495
- if (await runProjectCloseCommand({
106496
- cwd: process.cwd(),
106497
- format: options.format === "json" ? "json" : "text"
106498
- })) {
106499
- return;
106500
- }
106501
- throw new ContextError(ExitCode.WorkspaceStateError, "close requires a context project workspace", {
106502
- category: ErrorCategory.WorkspaceNotFound
106503
- });
106504
- });
106505
- program2.command("build").description("Build declared project packages").option("--format <format>", "output format: text | json", "text").option("--verbose", "include per-file build changes in JSON output").action(async (options) => {
106506
- if (options.format !== "text" && options.format !== "json") {
106507
- throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106508
- category: ErrorCategory.UserInputInvalid
106509
- });
106510
- }
106511
- if (await runProjectBuildCommand({
106512
- cwd: process.cwd(),
106513
- format: options.format === "json" ? "json" : "text",
106514
- verbose: options.verbose === true
106515
- })) {
106516
- return;
106517
- }
106518
- throw new ContextError(ExitCode.WorkspaceStateError, "build requires a context project workspace", {
106519
- category: ErrorCategory.WorkspaceNotFound
106520
- });
106521
- });
106767
+ registerProjectCloseAndBuildCommands(program2);
106522
106768
  registerProjectSourceCommands(program2);
106523
- program2.command("verify").description("Validate knowledge workspace").option("--format <format>", "output format: table | json", "table").option("--compact", "return grouped diagnostics without the complete issue list").option("--view <view>", "read a verification view: diagnostics").option("--page-size <n>", "with --view diagnostics, limit returned issues").option("--page-token <token>", "with --view diagnostics, continue pagination").action(async (options) => {
106524
- if (options.format !== "table" && options.format !== "json") {
106525
- throw new ContextError(ExitCode.UserError, "--format must be table or json", {
106526
- category: ErrorCategory.UserInputInvalid
106527
- });
106528
- }
106529
- if (options.view !== undefined && options.view !== "diagnostics") {
106530
- throw new ContextError(ExitCode.UserError, "--view must be diagnostics", {
106531
- category: ErrorCategory.UserInputInvalid
106532
- });
106533
- }
106534
- if (options.view === "diagnostics" && options.format !== "json") {
106535
- throw new ContextError(ExitCode.UserError, "--view diagnostics requires --format json", {
106536
- category: ErrorCategory.UserInputInvalid
106537
- });
106538
- }
106539
- if (await runProjectVerifyCommand({
106540
- cwd: process.cwd(),
106541
- format: options.format === "json" ? "json" : "table",
106542
- ...options.compact === true ? { compact: true } : {},
106543
- ...options.view === "diagnostics" ? { view: "diagnostics" } : {},
106544
- ...typeof options.pageSize === "string" ? { pageSize: options.pageSize } : {},
106545
- ...typeof options.pageToken === "string" ? { pageToken: options.pageToken } : {}
106546
- })) {
106547
- return;
106548
- }
106549
- throw new ContextError(ExitCode.WorkspaceStateError, "verify requires a context project workspace", {
106550
- category: ErrorCategory.WorkspaceNotFound
106551
- });
106552
- });
106769
+ registerProjectVerifyCommand(program2);
106553
106770
  const cleanCacheAction = async (options) => {
106554
106771
  const dryRun = options.dryRun === true;
106555
106772
  await runDoctorCleanClaudePluginCache({ dryRun });
@@ -106581,10 +106798,12 @@ function createCliProgram() {
106581
106798
  return program2;
106582
106799
  }
106583
106800
  async function cli_main(argv = process.argv) {
106584
- await withDebugCliInvocation(argv, async () => {
106585
- assertKnownTopLevelCommand(argv);
106586
- const program2 = createCliProgram();
106587
- await program2.parseAsync(argv);
106801
+ await withContextRuntimeEventDelivery(async () => {
106802
+ await withDebugCliInvocation(argv, async () => {
106803
+ assertKnownTopLevelCommand(argv);
106804
+ const program2 = createCliProgram();
106805
+ await program2.parseAsync(argv);
106806
+ });
106588
106807
  });
106589
106808
  }
106590
106809
  function isDirectCliInvocation(metaUrl, argv1) {