@c4a/context-cli 0.6.5 → 0.6.7

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,235 @@ 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 {
68959
+ existsSync as existsSync8,
68960
+ mkdirSync,
68961
+ readFileSync as readFileSync4,
68962
+ renameSync,
68963
+ writeFileSync
68964
+ } from "node:fs";
68965
+ import { spawn as spawn2 } from "node:child_process";
68966
+ import { dirname as dirname15, join as join17 } from "node:path";
68967
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
68968
+ var CONTEXT_RUNTIME_EVENT_BATCH_SCHEMA = "context.runtime-event-batch.v1";
68969
+ var CONTEXT_RUNTIME_EVENT_SINK_SCHEMA = "context.runtime-event-sink.v1";
68970
+ var CONTEXT_RUNTIME_EVENT_DELIVERY_TIMEOUT_MS = 3000;
68971
+ var CONTEXT_WORKSPACE_ACTIVE_THROTTLE_MS = 60 * 60 * 1000;
68972
+ var RUNTIME_EVENT_STATE_SCHEMA = "context.runtime-event-state.v1";
68973
+ var RUNTIME_EVENT_STATE_FILE = "runtime-event-state.json";
68974
+ var activeScope;
68975
+ function isRecord8(value) {
68976
+ return value !== null && typeof value === "object" && !Array.isArray(value);
68977
+ }
68978
+ function parseContextRuntimeEventSink(value) {
68979
+ if (!isRecord8(value))
68980
+ return null;
68981
+ if (value.schema !== CONTEXT_RUNTIME_EVENT_SINK_SCHEMA || value.transport !== "command")
68982
+ return null;
68983
+ if (typeof value.command !== "string" || value.command.trim().length === 0)
68984
+ return null;
68985
+ if (!Array.isArray(value.args) || !value.args.every((arg) => typeof arg === "string"))
68986
+ return null;
68987
+ return {
68988
+ schema: CONTEXT_RUNTIME_EVENT_SINK_SCHEMA,
68989
+ transport: "command",
68990
+ command: value.command,
68991
+ args: [...value.args]
68992
+ };
68993
+ }
68994
+ function readRuntimePackageMetadata() {
68995
+ try {
68996
+ let dir = dirname15(fileURLToPath4(import.meta.url));
68997
+ for (let index2 = 0;index2 < 8; index2++) {
68998
+ const packagePath = join17(dir, "package.json");
68999
+ if (existsSync8(packagePath)) {
69000
+ const parsed = JSON.parse(readFileSync4(packagePath, "utf8"));
69001
+ if (isRecord8(parsed)) {
69002
+ return {
69003
+ contextVersion: typeof parsed.version === "string" ? parsed.version : "unknown",
69004
+ sink: parseContextRuntimeEventSink(parsed.contextRuntimeEventSink)
69005
+ };
69006
+ }
69007
+ }
69008
+ const parent = dirname15(dir);
69009
+ if (parent === dir)
69010
+ break;
69011
+ dir = parent;
69012
+ }
69013
+ } catch {}
69014
+ return { contextVersion: "unknown", sink: null };
69015
+ }
69016
+ function dispatchCommand(sink, batch, cwd) {
69017
+ return new Promise((resolve8) => {
69018
+ let settled = false;
69019
+ let timer;
69020
+ const finish = (delivered) => {
69021
+ if (settled)
69022
+ return;
69023
+ settled = true;
69024
+ if (timer !== undefined)
69025
+ clearTimeout(timer);
69026
+ resolve8(delivered);
69027
+ };
69028
+ try {
69029
+ const child = spawn2(sink.command, sink.args, {
69030
+ cwd,
69031
+ env: process.env,
69032
+ shell: false,
69033
+ stdio: ["pipe", "ignore", "ignore"]
69034
+ });
69035
+ child.once("error", () => finish(false));
69036
+ child.once("exit", (code) => finish(code === 0));
69037
+ child.stdin.once("error", () => {
69038
+ child.kill();
69039
+ finish(false);
69040
+ });
69041
+ child.stdin.end(JSON.stringify(batch));
69042
+ timer = setTimeout(() => {
69043
+ child.kill();
69044
+ finish(false);
69045
+ }, CONTEXT_RUNTIME_EVENT_DELIVERY_TIMEOUT_MS);
69046
+ } catch {
69047
+ finish(false);
69048
+ }
69049
+ });
69050
+ }
69051
+ function runtimeEventStatePath(cwd) {
69052
+ return join17(cwd, ".tmp", "context-runtime", RUNTIME_EVENT_STATE_FILE);
69053
+ }
69054
+ function readRuntimeEventState(cwd) {
69055
+ try {
69056
+ const parsed = JSON.parse(readFileSync4(runtimeEventStatePath(cwd), "utf8"));
69057
+ if (!isRecord8(parsed) || parsed.schema !== RUNTIME_EVENT_STATE_SCHEMA)
69058
+ return null;
69059
+ const active = parsed.workspace_active;
69060
+ if (active === undefined)
69061
+ return { schema: RUNTIME_EVENT_STATE_SCHEMA };
69062
+ if (!isRecord8(active) || typeof active.workflow_status !== "string" || typeof active.delivered_at !== "number" || !Number.isFinite(active.delivered_at)) {
69063
+ return null;
69064
+ }
69065
+ return {
69066
+ schema: RUNTIME_EVENT_STATE_SCHEMA,
69067
+ workspace_active: {
69068
+ workflow_status: active.workflow_status,
69069
+ delivered_at: active.delivered_at
69070
+ }
69071
+ };
69072
+ } catch {
69073
+ return null;
69074
+ }
69075
+ }
69076
+ function shouldDeliverWorkspaceActive(event, state) {
69077
+ const workflowStatus = event.properties.workflow_status;
69078
+ if (typeof workflowStatus !== "string")
69079
+ return true;
69080
+ const previous2 = state?.workspace_active;
69081
+ if (previous2 === undefined || previous2.workflow_status !== workflowStatus)
69082
+ return true;
69083
+ return event.event_time - previous2.delivered_at >= CONTEXT_WORKSPACE_ACTIVE_THROTTLE_MS;
69084
+ }
69085
+ function selectRuntimeEventsForDelivery(events, state) {
69086
+ return events.filter((event) => event.kind !== "workspace.active" || shouldDeliverWorkspaceActive(event, state));
69087
+ }
69088
+ function persistDeliveredWorkspaceActive(cwd, events) {
69089
+ const delivered = [...events].reverse().find((event) => event.kind === "workspace.active");
69090
+ const workflowStatus = delivered?.properties.workflow_status;
69091
+ if (delivered === undefined || typeof workflowStatus !== "string")
69092
+ return;
69093
+ try {
69094
+ const statePath = runtimeEventStatePath(cwd);
69095
+ const stateDir = dirname15(statePath);
69096
+ const temporaryPath = `${statePath}.${process.pid}.tmp`;
69097
+ mkdirSync(stateDir, { recursive: true });
69098
+ writeFileSync(temporaryPath, `${JSON.stringify({
69099
+ schema: RUNTIME_EVENT_STATE_SCHEMA,
69100
+ workspace_active: {
69101
+ workflow_status: workflowStatus,
69102
+ delivered_at: delivered.event_time
69103
+ }
69104
+ })}
69105
+ `, "utf8");
69106
+ renameSync(temporaryPath, statePath);
69107
+ } catch {}
69108
+ }
69109
+ async function flushRuntimeEvents(scope) {
69110
+ const grouped = new Map;
69111
+ for (const queued of scope.events) {
69112
+ const events = grouped.get(queued.cwd) ?? [];
69113
+ events.push(queued.event);
69114
+ grouped.set(queued.cwd, events);
69115
+ }
69116
+ await Promise.all([...grouped.entries()].map(async ([cwd, events]) => {
69117
+ try {
69118
+ const selectedEvents = selectRuntimeEventsForDelivery(events, readRuntimeEventState(cwd));
69119
+ if (selectedEvents.length === 0)
69120
+ return;
69121
+ try {
69122
+ await scope.dispatch(scope.sink, {
69123
+ schema: CONTEXT_RUNTIME_EVENT_BATCH_SCHEMA,
69124
+ context_version: scope.contextVersion,
69125
+ events: selectedEvents
69126
+ }, cwd);
69127
+ } finally {
69128
+ persistDeliveredWorkspaceActive(cwd, selectedEvents);
69129
+ }
69130
+ } catch {}
69131
+ }));
69132
+ }
69133
+ function queueContextRuntimeEvent(input) {
69134
+ if (activeScope === undefined)
69135
+ return;
69136
+ activeScope.events.push({
69137
+ cwd: input.cwd,
69138
+ event: {
69139
+ event_id: randomUUID2(),
69140
+ event_time: Date.now(),
69141
+ kind: input.kind,
69142
+ properties: input.properties ?? {}
69143
+ }
69144
+ });
69145
+ }
69146
+ async function withContextRuntimeEventDelivery(work, options = {}) {
69147
+ if (activeScope !== undefined || process.env.CONTEXT_RUNTIME_EVENTS_DISABLED === "1" && options.forceDelivery !== true) {
69148
+ return work();
69149
+ }
69150
+ const metadata = readRuntimePackageMetadata();
69151
+ const sink = options.sink === undefined ? metadata.sink : options.sink;
69152
+ if (sink === null)
69153
+ return work();
69154
+ const scope = {
69155
+ contextVersion: options.contextVersion ?? metadata.contextVersion,
69156
+ dispatch: options.dispatch ?? dispatchCommand,
69157
+ events: [],
69158
+ sink
69159
+ };
69160
+ activeScope = scope;
69161
+ try {
69162
+ return await work();
69163
+ } finally {
69164
+ activeScope = undefined;
69165
+ await flushRuntimeEvents(scope);
69166
+ }
69167
+ }
69168
+
69169
+ // src/project/close.ts
69170
+ init_exitCode();
68952
69171
 
68953
69172
  // src/project/approvedStructureEdges.ts
68954
69173
  init_cliFeedback();
68955
69174
  init_errors();
68956
69175
  init_exitCode();
68957
69176
  var import_yaml10 = __toESM(require_dist3(), 1);
68958
- import { existsSync as existsSync10 } from "node:fs";
69177
+ import { existsSync as existsSync11 } from "node:fs";
68959
69178
  import { readFile as readFile17 } from "node:fs/promises";
68960
- import { join as join19 } from "node:path";
69179
+ import { join as join20 } from "node:path";
68961
69180
 
68962
69181
  // src/project/proseAlignTypes.ts
68963
69182
  import { createHash as createHash9 } from "node:crypto";
@@ -69014,21 +69233,21 @@ function slugify2(input, maxLen = 60) {
69014
69233
  // src/project/semanticRules.ts
69015
69234
  var import_yaml8 = __toESM(require_dist3(), 1);
69016
69235
  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";
69236
+ import { existsSync as existsSync9, readFileSync as readFileSync5, readdirSync } from "node:fs";
69237
+ import { basename as basename4, dirname as dirname16, join as join18 } from "node:path";
69238
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
69020
69239
  function sha256(value) {
69021
69240
  return `sha256:${createHash8("sha256").update(value).digest("hex")}`;
69022
69241
  }
69023
69242
  function workflowRootCandidates() {
69024
- const runtimeDir = dirname15(fileURLToPath4(import.meta.url));
69243
+ const runtimeDir = dirname16(fileURLToPath5(import.meta.url));
69025
69244
  return [
69026
- join17(runtimeDir, "providers", "context"),
69027
- join17(runtimeDir, "..", "..", "context-workflow")
69245
+ join18(runtimeDir, "providers", "context"),
69246
+ join18(runtimeDir, "..", "..", "context-workflow")
69028
69247
  ];
69029
69248
  }
69030
69249
  function semanticRuleMetadata(scope, filePath) {
69031
- const content3 = readFileSync4(filePath, "utf8").replaceAll(`\r
69250
+ const content3 = readFileSync5(filePath, "utf8").replaceAll(`\r
69032
69251
  `, `
69033
69252
  `);
69034
69253
  const end = content3.indexOf(`
@@ -69059,19 +69278,19 @@ function semanticRuleMetadata(scope, filePath) {
69059
69278
  }
69060
69279
  function semanticRuleDescriptors(scope) {
69061
69280
  for (const root of workflowRootCandidates()) {
69062
- const directory = join17(root, "resources", "semantic", scope);
69063
- if (!existsSync8(directory))
69281
+ const directory = join18(root, "resources", "semantic", scope);
69282
+ if (!existsSync9(directory))
69064
69283
  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)));
69284
+ 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
69285
  }
69067
69286
  throw new Error(`Context ${scope} semantic workflow resources are missing. Rebuild or reinstall @c4a/context-cli.`);
69068
69287
  }
69069
69288
  function ruleContent(rulePath) {
69070
69289
  for (const root of workflowRootCandidates()) {
69071
- const absolute = join17(root, rulePath);
69072
- if (existsSync8(absolute)) {
69290
+ const absolute = join18(root, rulePath);
69291
+ if (existsSync9(absolute)) {
69073
69292
  return {
69074
- content: readFileSync4(absolute, "utf8"),
69293
+ content: readFileSync5(absolute, "utf8"),
69075
69294
  available: true,
69076
69295
  filePath: absolute
69077
69296
  };
@@ -69484,15 +69703,15 @@ init_cliFeedback();
69484
69703
  init_errors();
69485
69704
  init_exitCode();
69486
69705
  var import_yaml9 = __toESM(require_dist3(), 1);
69487
- import { existsSync as existsSync9 } from "node:fs";
69706
+ import { existsSync as existsSync10 } from "node:fs";
69488
69707
  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";
69708
+ import { dirname as dirname17, join as join19 } from "node:path";
69490
69709
 
69491
69710
  // src/project/proseAlignPayloadParse.ts
69492
69711
  import { createHash as createHash10 } from "node:crypto";
69493
69712
 
69494
69713
  // src/project/proseAlignSchemaUtils.ts
69495
- function isRecord8(value) {
69714
+ function isRecord9(value) {
69496
69715
  return value !== null && typeof value === "object" && !Array.isArray(value);
69497
69716
  }
69498
69717
  function stringValue2(record, field) {
@@ -69559,7 +69778,7 @@ function parsePreferredNodes(value, diagnostics) {
69559
69778
  }
69560
69779
  const nodes = [];
69561
69780
  for (const [index2, rawNode] of value.entries()) {
69562
- if (!isRecord8(rawNode)) {
69781
+ if (!isRecord9(rawNode)) {
69563
69782
  diagnostics.push(diagnostic("error", "schema.preferred_node_object", "schema", "preferred_nodes item must be an object.", `user_or_agent_hints.preferred_nodes[${index2}]`));
69564
69783
  continue;
69565
69784
  }
@@ -69584,7 +69803,7 @@ function parsePreferredNodes(value, diagnostics) {
69584
69803
  function parseUserOrAgentHints(value, diagnostics) {
69585
69804
  if (value === undefined)
69586
69805
  return;
69587
- if (!isRecord8(value)) {
69806
+ if (!isRecord9(value)) {
69588
69807
  diagnostics.push(diagnostic("error", "schema.user_or_agent_hints_object", "schema", "user_or_agent_hints must be an object.", "user_or_agent_hints"));
69589
69808
  return;
69590
69809
  }
@@ -69787,7 +70006,7 @@ function parseNodes(value, diagnostics) {
69787
70006
  diagnostics.push(diagnostic("error", "schema.nodes_missing", "schema", "Payload must include at least one node.", "nodes"));
69788
70007
  const nodes = [];
69789
70008
  for (const [index2, rawNode] of value.entries()) {
69790
- if (!isRecord8(rawNode)) {
70009
+ if (!isRecord9(rawNode)) {
69791
70010
  diagnostics.push(diagnostic("error", "schema.node_object", "schema", `Node ${index2 + 1} must be an object.`, `nodes[${index2}]`));
69792
70011
  continue;
69793
70012
  }
@@ -69824,7 +70043,7 @@ function parseSections(input) {
69824
70043
  const sectionIds = new Set;
69825
70044
  for (const [sectionIndex, rawSection] of input.value.entries()) {
69826
70045
  const field = `views[${input.viewIndex}].sections[${sectionIndex}]`;
69827
- if (!isRecord8(rawSection)) {
70046
+ if (!isRecord9(rawSection)) {
69828
70047
  input.diagnostics.push(diagnostic("error", "schema.section_object", "schema", "Section must be an object.", field));
69829
70048
  continue;
69830
70049
  }
@@ -69926,7 +70145,7 @@ function parseViews(value, nodes, diagnostics) {
69926
70145
  const nodeByRef = new Map(nodes.map((node3) => [node3.node_ref, node3]));
69927
70146
  const views = [];
69928
70147
  for (const [index2, rawView] of value.entries()) {
69929
- if (!isRecord8(rawView)) {
70148
+ if (!isRecord9(rawView)) {
69930
70149
  diagnostics.push(diagnostic("error", "schema.view_object", "schema", `View ${index2 + 1} must be an object.`, `views[${index2}]`));
69931
70150
  continue;
69932
70151
  }
@@ -69945,7 +70164,7 @@ function parseEdges(value, diagnostics) {
69945
70164
  }
69946
70165
  const edges = [];
69947
70166
  for (const [index2, rawEdge] of value.entries()) {
69948
- if (!isRecord8(rawEdge)) {
70167
+ if (!isRecord9(rawEdge)) {
69949
70168
  diagnostics.push(diagnostic("error", "schema.edge_object", "schema", `Edge ${index2 + 1} must be an object.`, `edges[${index2}]`));
69950
70169
  continue;
69951
70170
  }
@@ -69992,7 +70211,7 @@ function parseUnresolved(value, diagnostics) {
69992
70211
  }
69993
70212
  const unresolved = [];
69994
70213
  for (const [index2, rawIssue] of value.entries()) {
69995
- if (!isRecord8(rawIssue)) {
70214
+ if (!isRecord9(rawIssue)) {
69996
70215
  diagnostics.push(diagnostic("error", "schema.unresolved_object", "schema", `Unresolved issue ${index2 + 1} must be an object.`, `unresolved[${index2}]`));
69997
70216
  continue;
69998
70217
  }
@@ -70015,7 +70234,7 @@ function parseUnresolved(value, diagnostics) {
70015
70234
  function parseLifecycle(value, diagnostics) {
70016
70235
  if (value === undefined)
70017
70236
  return { state: "draft" };
70018
- if (!isRecord8(value)) {
70237
+ if (!isRecord9(value)) {
70019
70238
  diagnostics.push(diagnostic("error", "schema.lifecycle_object", "schema", "Payload lifecycle must be an object.", "lifecycle"));
70020
70239
  return { state: "draft" };
70021
70240
  }
@@ -70073,7 +70292,7 @@ function structureBody(input) {
70073
70292
  }
70074
70293
  function parseAlignPayload(value) {
70075
70294
  const diagnostics = [];
70076
- if (!isRecord8(value)) {
70295
+ if (!isRecord9(value)) {
70077
70296
  return {
70078
70297
  diagnostics: [diagnostic("error", "schema.payload_object", "schema", "Payload must be a YAML/JSON object.", "schema")]
70079
70298
  };
@@ -70158,7 +70377,7 @@ function snapshotPath(projectRoot, structureDigest) {
70158
70377
  structure_digest: structureDigest
70159
70378
  });
70160
70379
  }
70161
- return join18(projectRoot, STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70380
+ return join19(projectRoot, STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70162
70381
  }
70163
70382
  function normalizedSnapshot(payload) {
70164
70383
  const { user_or_agent_hints: _hints, ...body } = payload;
@@ -70174,8 +70393,8 @@ function normalizedSnapshot(payload) {
70174
70393
  });
70175
70394
  }
70176
70395
  async function readSlots(projectRoot) {
70177
- const path3 = join18(projectRoot, STRUCTURE_SLOT_FILE);
70178
- if (!existsSync9(path3))
70396
+ const path3 = join19(projectRoot, STRUCTURE_SLOT_FILE);
70397
+ if (!existsSync10(path3))
70179
70398
  return [];
70180
70399
  const parsed = import_yaml9.default.parse(await readFile16(path3, "utf8"));
70181
70400
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -70223,8 +70442,8 @@ async function updateSlots(projectRoot, payload) {
70223
70442
  ...current2.filter((slot) => !replacements.has(`${slot.source}\x00${slot.collection}`)),
70224
70443
  ...replacements.values()
70225
70444
  ].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 });
70445
+ const path3 = join19(projectRoot, STRUCTURE_SLOT_FILE);
70446
+ await mkdir12(dirname17(path3), { recursive: true });
70228
70447
  await writeFile8(path3, import_yaml9.default.stringify({ schema_version: STRUCTURE_SLOT_SCHEMA_VERSION, slots }), "utf8");
70229
70448
  }
70230
70449
  async function writeStructureSnapshot(projectRoot, payload) {
@@ -70239,7 +70458,7 @@ async function writeStructureSnapshot(projectRoot, payload) {
70239
70458
  });
70240
70459
  }
70241
70460
  const content3 = import_yaml9.default.stringify(normalized);
70242
- if (existsSync9(path3)) {
70461
+ if (existsSync10(path3)) {
70243
70462
  const current2 = await readFile16(path3, "utf8");
70244
70463
  const existing = parseAlignPayload(import_yaml9.default.parse(current2)).payload;
70245
70464
  if (existing?.structure_digest !== payload.structure_digest) {
@@ -70255,14 +70474,14 @@ async function writeStructureSnapshot(projectRoot, payload) {
70255
70474
  await updateSlots(projectRoot, payload);
70256
70475
  return path3;
70257
70476
  }
70258
- await mkdir12(dirname16(path3), { recursive: true });
70477
+ await mkdir12(dirname17(path3), { recursive: true });
70259
70478
  await writeFile8(path3, content3, "utf8");
70260
70479
  await updateSlots(projectRoot, payload);
70261
70480
  return path3;
70262
70481
  }
70263
70482
  async function readStructureSnapshot(projectRoot, structureDigest) {
70264
70483
  const path3 = snapshotPath(projectRoot, structureDigest);
70265
- if (!existsSync9(path3))
70484
+ if (!existsSync10(path3))
70266
70485
  return null;
70267
70486
  try {
70268
70487
  return import_yaml9.default.parse(await readFile16(path3, "utf8"));
@@ -70290,8 +70509,8 @@ async function readStructureSnapshotPayload(projectRoot, structureDigest) {
70290
70509
  return { ...record, structure_digest: structureDigest };
70291
70510
  }
70292
70511
  async function archiveActiveStructure(projectRoot) {
70293
- const path3 = join18(projectRoot, LIFECYCLE_STRUCTURE_FILE);
70294
- if (!existsSync9(path3))
70512
+ const path3 = join19(projectRoot, LIFECYCLE_STRUCTURE_FILE);
70513
+ if (!existsSync10(path3))
70295
70514
  return null;
70296
70515
  let parsed;
70297
70516
  try {
@@ -70319,7 +70538,7 @@ function structureSnapshotRelativePath(structureDigest) {
70319
70538
  const match = STRUCTURE_DIGEST_PATTERN.exec(structureDigest);
70320
70539
  if (match?.[1] === undefined)
70321
70540
  return STRUCTURE_SNAPSHOT_ROOT;
70322
- return join18(STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70541
+ return join19(STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70323
70542
  }
70324
70543
  async function currentStructureSlotDigest(projectRoot, source2, collection) {
70325
70544
  return (await readSlots(projectRoot)).find((slot) => slot.source === source2 && slot.collection === collection)?.structure_digest;
@@ -70334,9 +70553,9 @@ async function activeStructureSlots(projectRoot, collection) {
70334
70553
 
70335
70554
  // src/project/approvedStructureEdges.ts
70336
70555
  var KNOWLEDGE_ROOT = "knowledge";
70337
- var APPROVED_STRUCTURE_PATH = join19(KNOWLEDGE_ROOT, "structure.yaml");
70556
+ var APPROVED_STRUCTURE_PATH = join20(KNOWLEDGE_ROOT, "structure.yaml");
70338
70557
  var STRUCTURE_EDGE_CONFIDENCE_SET = new Set(STRUCTURE_EDGE_CONFIDENCES);
70339
- function isRecord9(value) {
70558
+ function isRecord10(value) {
70340
70559
  return value !== null && typeof value === "object" && !Array.isArray(value);
70341
70560
  }
70342
70561
  function readEdgeArray(structure) {
@@ -70346,7 +70565,7 @@ function normalizeApprovedEdges(input) {
70346
70565
  const allowed = new Set(STRUCTURE_EDGE_TYPES);
70347
70566
  const edges = [];
70348
70567
  for (const [index2, rawEdge] of input.rawEdges.entries()) {
70349
- if (!isRecord9(rawEdge)) {
70568
+ if (!isRecord10(rawEdge)) {
70350
70569
  throw new ContextError(ExitCode.WorkspaceStateError, "structure edge must be an object", {
70351
70570
  category: ErrorCategory.WorkspaceStateInvalid,
70352
70571
  path: input.path,
@@ -70437,20 +70656,20 @@ function structureEndpointRefs(structure) {
70437
70656
  const refs = [];
70438
70657
  if (Array.isArray(structure.nodes)) {
70439
70658
  for (const node3 of structure.nodes) {
70440
- if (isRecord9(node3) && typeof node3.node_ref === "string")
70659
+ if (isRecord10(node3) && typeof node3.node_ref === "string")
70441
70660
  refs.push(node3.node_ref);
70442
70661
  }
70443
70662
  }
70444
70663
  if (Array.isArray(structure.views)) {
70445
70664
  for (const view of structure.views) {
70446
- if (!isRecord9(view))
70665
+ if (!isRecord10(view))
70447
70666
  continue;
70448
70667
  if (typeof view.view_ref === "string")
70449
70668
  refs.push(view.view_ref);
70450
70669
  if (!Array.isArray(view.sections))
70451
70670
  continue;
70452
70671
  for (const section of view.sections) {
70453
- if (isRecord9(section) && typeof section.section_ref === "string")
70672
+ if (isRecord10(section) && typeof section.section_ref === "string")
70454
70673
  refs.push(section.section_ref);
70455
70674
  }
70456
70675
  }
@@ -70458,12 +70677,12 @@ function structureEndpointRefs(structure) {
70458
70677
  return refs;
70459
70678
  }
70460
70679
  async function readYamlRecord(projectRoot, relPath) {
70461
- const absPath = join19(projectRoot, relPath);
70462
- if (!existsSync10(absPath))
70680
+ const absPath = join20(projectRoot, relPath);
70681
+ if (!existsSync11(absPath))
70463
70682
  return null;
70464
70683
  try {
70465
70684
  const parsed = import_yaml10.default.parse(await readFile17(absPath, "utf8"));
70466
- return isRecord9(parsed) ? parsed : null;
70685
+ return isRecord10(parsed) ? parsed : null;
70467
70686
  } catch (error) {
70468
70687
  throw new ContextError(ExitCode.WorkspaceStateError, `${relPath} is invalid YAML`, {
70469
70688
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -70502,7 +70721,7 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70502
70721
  const snapshotEdges = [];
70503
70722
  for (const structureDigest of [...new Set(slots.map((slot) => slot.structureDigest))].sort()) {
70504
70723
  const structure2 = await readStructureSnapshot(projectRoot, structureDigest);
70505
- if (!isRecord9(structure2)) {
70724
+ if (!isRecord10(structure2)) {
70506
70725
  throw new ContextError(ExitCode.WorkspaceStateError, "active structure snapshot is missing", {
70507
70726
  category: ErrorCategory.WorkspaceStateInvalid,
70508
70727
  structure_digest: structureDigest,
@@ -70543,7 +70762,7 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70543
70762
  }
70544
70763
  if (structure === null)
70545
70764
  return null;
70546
- const lifecycle = isRecord9(structure.lifecycle) ? structure.lifecycle : {};
70765
+ const lifecycle = isRecord10(structure.lifecycle) ? structure.lifecycle : {};
70547
70766
  if (lifecycle.state !== "confirmed" && lifecycle.state !== "frozen")
70548
70767
  return null;
70549
70768
  return normalizeApprovedEdges({
@@ -70559,15 +70778,15 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70559
70778
  init_cliFeedback();
70560
70779
  init_errors();
70561
70780
  init_exitCode();
70562
- import { existsSync as existsSync17 } from "node:fs";
70781
+ import { existsSync as existsSync18 } from "node:fs";
70563
70782
  import { readFile as readFile23 } from "node:fs/promises";
70564
- import { join as join27 } from "node:path";
70783
+ import { join as join28 } from "node:path";
70565
70784
 
70566
70785
  // src/project/verifyApprovedStructure.ts
70567
70786
  var import_yaml12 = __toESM(require_dist3(), 1);
70568
- import { existsSync as existsSync13 } from "node:fs";
70787
+ import { existsSync as existsSync14 } from "node:fs";
70569
70788
  import { readFile as readFile19 } from "node:fs/promises";
70570
- import { join as join23 } from "node:path";
70789
+ import { join as join24 } from "node:path";
70571
70790
 
70572
70791
  // src/project/approvedStructureInputHash.ts
70573
70792
  import { createHash as createHash11 } from "node:crypto";
@@ -70608,11 +70827,11 @@ function approvedStructureInputHash(input) {
70608
70827
  }
70609
70828
 
70610
70829
  // src/project/verifyApprovedStructureEdges.ts
70611
- import { join as join21 } from "node:path";
70830
+ import { join as join22 } from "node:path";
70612
70831
 
70613
70832
  // src/project/verifyCanonicalSourceRefs.ts
70614
- import { existsSync as existsSync11 } from "node:fs";
70615
- import { join as join20 } from "node:path";
70833
+ import { existsSync as existsSync12 } from "node:fs";
70834
+ import { join as join21 } from "node:path";
70616
70835
  var CANONICAL_SOURCE_REF = /^repo:([^#]+)#symbol:(.+):([^:@]+):([^:@]+)@([a-f0-9]+)$/iu;
70617
70836
  function validateCanonicalSourceRef(input) {
70618
70837
  const path3 = input.path ?? ".tmp/context-runtime/lifecycle/candidates.jsonl";
@@ -70668,7 +70887,7 @@ async function validateCanonicalEvidenceSourceRef(input) {
70668
70887
  const registryEntry = input.sourceRegistry.loaded ? registeredDocumentSource(input.sourceRegistry, locator.sourceType, locator.sourceName) : undefined;
70669
70888
  const materializedAt = registryEntry?.materializedAt ?? defaultDocumentMaterializedAt(locator.sourceType, locator.sourceName);
70670
70889
  const manifestPath = registryEntry?.snapshot?.manifest ?? defaultDocumentManifest(materializedAt);
70671
- if (!existsSync11(join20(input.projectRoot, manifestPath)) && !snapshotRootExists(input.projectRoot, materializedAt)) {
70890
+ if (!existsSync12(join21(input.projectRoot, manifestPath)) && !snapshotRootExists(input.projectRoot, materializedAt)) {
70672
70891
  input.issues.push({
70673
70892
  severity: unresolvedSeverity,
70674
70893
  code: "approved-evidence-unavailable",
@@ -70741,7 +70960,7 @@ async function validateCanonicalEvidenceSourceRef(input) {
70741
70960
  }
70742
70961
 
70743
70962
  // src/project/verifyApprovedStructureEdges.ts
70744
- var APPROVED_STRUCTURE_PATH2 = join21("knowledge", "structure.yaml");
70963
+ var APPROVED_STRUCTURE_PATH2 = join22("knowledge", "structure.yaml");
70745
70964
  function approvedStructureEdgeRecords(parsed, issues) {
70746
70965
  if (parsed.edges === undefined)
70747
70966
  return [];
@@ -70874,7 +71093,7 @@ async function validateApprovedStructureEdgeRecords(input) {
70874
71093
  init_cliFeedback();
70875
71094
  init_errors();
70876
71095
  init_exitCode();
70877
- function isRecord10(value) {
71096
+ function isRecord11(value) {
70878
71097
  return value !== null && typeof value === "object" && !Array.isArray(value);
70879
71098
  }
70880
71099
  function codegraphEdgesFromFrontmatter(frontmatter, path3) {
@@ -70887,7 +71106,7 @@ function codegraphEdgesFromFrontmatter(frontmatter, path3) {
70887
71106
  });
70888
71107
  }
70889
71108
  return frontmatter.code_edges.map((rawEdge, index2) => {
70890
- if (!isRecord10(rawEdge)) {
71109
+ if (!isRecord11(rawEdge)) {
70891
71110
  throw new ContextError(ExitCode.WorkspaceStateError, "approved code edge must be an object", {
70892
71111
  category: ErrorCategory.WorkspaceStateInvalid,
70893
71112
  path: path3,
@@ -70947,17 +71166,17 @@ function codegraphRelationshipCoverage(input) {
70947
71166
  }
70948
71167
 
70949
71168
  // src/project/approvedStructureInputs.ts
70950
- import { existsSync as existsSync12 } from "node:fs";
71169
+ import { existsSync as existsSync13 } from "node:fs";
70951
71170
  import { readFile as readFile18 } from "node:fs/promises";
70952
- import { join as join22 } from "node:path";
71171
+ import { join as join23 } from "node:path";
70953
71172
  init_cliFeedback();
70954
71173
  init_errors();
70955
71174
  init_exitCode();
70956
71175
  var import_yaml11 = __toESM(require_dist3(), 1);
70957
- var APPROVED_STRUCTURE_FILE = join22("knowledge", "structure.yaml");
71176
+ var APPROVED_STRUCTURE_FILE = join23("knowledge", "structure.yaml");
70958
71177
  var COLLECTIONS = new Set(KNOWLEDGE_COLLECTIONS);
70959
71178
  var SNAPSHOT_HASH_PATTERN = /^sha256:[a-f0-9]{64}$/u;
70960
- function isRecord11(value) {
71179
+ function isRecord12(value) {
70961
71180
  return value !== null && typeof value === "object" && !Array.isArray(value);
70962
71181
  }
70963
71182
  function invalidSourceInputs(reason) {
@@ -70976,14 +71195,14 @@ function sortedSourceInputs(values2) {
70976
71195
  function parseApprovedStructureSourceInputs(structure) {
70977
71196
  if (structure.source_inputs === undefined)
70978
71197
  return [];
70979
- if (!isRecord11(structure.source_inputs)) {
71198
+ if (!isRecord12(structure.source_inputs)) {
70980
71199
  throw invalidSourceInputs("source_inputs must be an object when present");
70981
71200
  }
70982
71201
  const inputs = new Map;
70983
71202
  for (const [source2, collections] of Object.entries(structure.source_inputs)) {
70984
71203
  if (source2.trim().length === 0)
70985
71204
  throw invalidSourceInputs("source_inputs source key must not be empty");
70986
- if (!isRecord11(collections)) {
71205
+ if (!isRecord12(collections)) {
70987
71206
  throw invalidSourceInputs(`source_inputs.${source2} must be an object`);
70988
71207
  }
70989
71208
  for (const [collection, snapshotHash] of Object.entries(collections)) {
@@ -71008,8 +71227,8 @@ function approvedStructureSourceInputsRecord(inputs) {
71008
71227
  return result;
71009
71228
  }
71010
71229
  async function readApprovedStructureSourceInputs(projectRoot) {
71011
- const path3 = join22(projectRoot, APPROVED_STRUCTURE_FILE);
71012
- if (!existsSync12(path3))
71230
+ const path3 = join23(projectRoot, APPROVED_STRUCTURE_FILE);
71231
+ if (!existsSync13(path3))
71013
71232
  return [];
71014
71233
  let parsed;
71015
71234
  try {
@@ -71017,7 +71236,7 @@ async function readApprovedStructureSourceInputs(projectRoot) {
71017
71236
  } catch {
71018
71237
  return [];
71019
71238
  }
71020
- if (!isRecord11(parsed))
71239
+ if (!isRecord12(parsed))
71021
71240
  return [];
71022
71241
  return parseApprovedStructureSourceInputs(parsed);
71023
71242
  }
@@ -71046,14 +71265,14 @@ function approvedStructureSourceInputKey(input) {
71046
71265
  }
71047
71266
 
71048
71267
  // src/project/verifyApprovedStructure.ts
71049
- var APPROVED_STRUCTURE_PATH3 = join23("knowledge", "structure.yaml");
71268
+ var APPROVED_STRUCTURE_PATH3 = join24("knowledge", "structure.yaml");
71050
71269
  var APPROVED_STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
71051
71270
  var LOCAL_REF = /^src-(\d+)(#(?:span|symbol):.+)$/u;
71052
71271
  async function readApprovedStructureForVerify(input) {
71053
71272
  if (input.structureOverride !== undefined)
71054
71273
  return input.structureOverride;
71055
- const structurePath = join23(input.projectRoot, APPROVED_STRUCTURE_PATH3);
71056
- if (!existsSync13(structurePath))
71274
+ const structurePath = join24(input.projectRoot, APPROVED_STRUCTURE_PATH3);
71275
+ if (!existsSync14(structurePath))
71057
71276
  return;
71058
71277
  let rawParsed;
71059
71278
  try {
@@ -71278,7 +71497,7 @@ async function approvedStructureProjection(projectRoot) {
71278
71497
  const views = [];
71279
71498
  const parentIndexes = [];
71280
71499
  const codeEdges = [];
71281
- for (const file of await walkMarkdown(join23(projectRoot, "knowledge"))) {
71500
+ for (const file of await walkMarkdown(join24(projectRoot, "knowledge"))) {
71282
71501
  if (isKnowledgeAssetPath(file.relPath))
71283
71502
  continue;
71284
71503
  const content3 = await readFile19(file.absPath, "utf8");
@@ -71692,13 +71911,13 @@ async function validateApprovedStructureEdges(input) {
71692
71911
  init_workspace();
71693
71912
 
71694
71913
  // src/project/reviewDecisions.ts
71695
- import { existsSync as existsSync16 } from "node:fs";
71914
+ import { existsSync as existsSync17 } from "node:fs";
71696
71915
  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";
71916
+ import { dirname as dirname20, join as join27 } from "node:path";
71698
71917
  init_cliFeedback();
71699
71918
  init_errors();
71700
71919
  init_exitCode();
71701
- var REVIEW_DECISIONS_FILE = join26("knowledge", "decisions.json");
71920
+ var REVIEW_DECISIONS_FILE = join27("knowledge", "decisions.json");
71702
71921
  var FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/u;
71703
71922
  var COLLECTIONS2 = new Set(KNOWLEDGE_COLLECTIONS);
71704
71923
  function isCandidateId(value) {
@@ -71713,8 +71932,8 @@ function invalidDecisions(reason) {
71713
71932
  });
71714
71933
  }
71715
71934
  async function readRejectedDecisions(projectRoot) {
71716
- const path3 = join26(projectRoot, REVIEW_DECISIONS_FILE);
71717
- if (!existsSync16(path3))
71935
+ const path3 = join27(projectRoot, REVIEW_DECISIONS_FILE);
71936
+ if (!existsSync17(path3))
71718
71937
  return new Map;
71719
71938
  let parsed;
71720
71939
  try {
@@ -71738,14 +71957,14 @@ async function readRejectedDecisions(projectRoot) {
71738
71957
  return decisions;
71739
71958
  }
71740
71959
  async function writeRejectedDecisions(projectRoot, decisions) {
71741
- const path3 = join26(projectRoot, REVIEW_DECISIONS_FILE);
71960
+ const path3 = join27(projectRoot, REVIEW_DECISIONS_FILE);
71742
71961
  if (decisions.size === 0) {
71743
71962
  await rm8(path3, { force: true });
71744
71963
  return;
71745
71964
  }
71746
71965
  const rejected = Object.fromEntries([...decisions.entries()].sort(([left], [right]) => left.localeCompare(right)));
71747
71966
  const tempPath = `${path3}.${process.pid}.tmp`;
71748
- await mkdir15(dirname19(path3), { recursive: true });
71967
+ await mkdir15(dirname20(path3), { recursive: true });
71749
71968
  await writeFile11(tempPath, `${JSON.stringify(rejected, null, 2)}
71750
71969
  `, "utf8");
71751
71970
  await rename3(tempPath, path3);
@@ -71922,7 +72141,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
71922
72141
  issues
71923
72142
  });
71924
72143
  const seenViewRefs = new Set;
71925
- for (const file of await walkMarkdown(join27(projectRoot, "knowledge"))) {
72144
+ for (const file of await walkMarkdown(join28(projectRoot, "knowledge"))) {
71926
72145
  if (isKnowledgeAssetPath(file.relPath))
71927
72146
  continue;
71928
72147
  const content3 = await readFile23(file.absPath, "utf8");
@@ -71945,7 +72164,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
71945
72164
  pageRelPath: `knowledge/${file.relPath}`,
71946
72165
  content: content3
71947
72166
  })) {
71948
- if (!existsSync17(join27(projectRoot, assetPath))) {
72167
+ if (!existsSync18(join28(projectRoot, assetPath))) {
71949
72168
  issues.push({
71950
72169
  severity: "error",
71951
72170
  code: "approved-resource-missing",
@@ -72131,9 +72350,9 @@ init_writeLock();
72131
72350
 
72132
72351
  // src/project/proseCompileBatch.ts
72133
72352
  var import_yaml13 = __toESM(require_dist3(), 1);
72134
- import { existsSync as existsSync19 } from "node:fs";
72353
+ import { existsSync as existsSync20 } from "node:fs";
72135
72354
  import { readFile as readFile25 } from "node:fs/promises";
72136
- import { join as join29 } from "node:path";
72355
+ import { join as join30 } from "node:path";
72137
72356
  init_cliFeedback();
72138
72357
  init_errors();
72139
72358
  init_exitCode();
@@ -72142,9 +72361,9 @@ init_exitCode();
72142
72361
  init_cliFeedback();
72143
72362
  init_errors();
72144
72363
  init_exitCode();
72145
- import { existsSync as existsSync18 } from "node:fs";
72364
+ import { existsSync as existsSync19 } from "node:fs";
72146
72365
  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";
72366
+ import { basename as basename6, join as join29, relative as relative12 } from "node:path";
72148
72367
  init_writeLock();
72149
72368
  function candidateSourceKey(record) {
72150
72369
  return record.source === undefined ? undefined : `${record.source.type}:${record.source.name}`;
@@ -72156,11 +72375,11 @@ function toPosixPath8(value) {
72156
72375
  return value.split(/[\\/]+/u).join("/");
72157
72376
  }
72158
72377
  async function approvedPageIdentities(projectRoot) {
72159
- const root = join28(projectRoot, "knowledge");
72378
+ const root = join29(projectRoot, "knowledge");
72160
72379
  const identities = [];
72161
72380
  const visit2 = async (directory) => {
72162
72381
  for (const entry of await readdir10(directory, { withFileTypes: true })) {
72163
- const absolutePath = join28(directory, entry.name);
72382
+ const absolutePath = join29(directory, entry.name);
72164
72383
  if (entry.isDirectory()) {
72165
72384
  await visit2(absolutePath);
72166
72385
  continue;
@@ -72178,7 +72397,7 @@ async function approvedPageIdentities(projectRoot) {
72178
72397
  });
72179
72398
  }
72180
72399
  };
72181
- if (existsSync18(root))
72400
+ if (existsSync19(root))
72182
72401
  await visit2(root);
72183
72402
  return {
72184
72403
  byPath: new Map(identities.map((identity) => [identity.path, identity])),
@@ -72407,7 +72626,7 @@ async function preserveApprovedPathIdentities(input) {
72407
72626
  }
72408
72627
 
72409
72628
  // src/project/proseCompileBatch.ts
72410
- function isRecord13(value) {
72629
+ function isRecord14(value) {
72411
72630
  return value !== null && typeof value === "object" && !Array.isArray(value);
72412
72631
  }
72413
72632
  function stringField2(value, field) {
@@ -72415,11 +72634,11 @@ function stringField2(value, field) {
72415
72634
  return typeof candidate === "string" && candidate.trim().length > 0 ? candidate.trim() : undefined;
72416
72635
  }
72417
72636
  async function readConfirmedStructure(projectRoot) {
72418
- const path3 = join29(projectRoot, LIFECYCLE_STRUCTURE_FILE);
72419
- if (!existsSync19(path3))
72637
+ const path3 = join30(projectRoot, LIFECYCLE_STRUCTURE_FILE);
72638
+ if (!existsSync20(path3))
72420
72639
  return;
72421
72640
  const parsed = import_yaml13.default.parse(await readFile25(path3, "utf8"));
72422
- if (!isRecord13(parsed) || !isRecord13(parsed.lifecycle))
72641
+ if (!isRecord14(parsed) || !isRecord14(parsed.lifecycle))
72423
72642
  return;
72424
72643
  if (parsed.lifecycle.state !== "confirmed" && parsed.lifecycle.state !== "frozen")
72425
72644
  return;
@@ -72434,7 +72653,7 @@ async function readCurrentSnapshotHashes(projectRoot) {
72434
72653
  }
72435
72654
  async function approvedViewRefs(projectRoot, planned) {
72436
72655
  const approved = [];
72437
- for (const file of await walkMarkdown(join29(projectRoot, "knowledge"))) {
72656
+ for (const file of await walkMarkdown(join30(projectRoot, "knowledge"))) {
72438
72657
  if (isKnowledgeAssetPath(file.relPath))
72439
72658
  continue;
72440
72659
  const content3 = await readFile25(file.absPath, "utf8");
@@ -72702,7 +72921,7 @@ function proseCompileBatchNextAction(input) {
72702
72921
 
72703
72922
  // src/project/lifecycleCleanup.ts
72704
72923
  import { rm as rm9 } from "node:fs/promises";
72705
- import { join as join30 } from "node:path";
72924
+ import { join as join31 } from "node:path";
72706
72925
  var COMPLETED_RUNTIME_PATHS = [
72707
72926
  LIFECYCLE_ROOT,
72708
72927
  REVIEW_RUNTIME_ROOT,
@@ -72711,13 +72930,13 @@ var COMPLETED_RUNTIME_PATHS = [
72711
72930
  CANDIDATE_SNAPSHOT_ROOT
72712
72931
  ];
72713
72932
  async function clearCompletedLifecycle(projectRoot) {
72714
- await Promise.all(COMPLETED_RUNTIME_PATHS.map((path3) => rm9(join30(projectRoot, path3), { recursive: true, force: true })));
72933
+ await Promise.all(COMPLETED_RUNTIME_PATHS.map((path3) => rm9(join31(projectRoot, path3), { recursive: true, force: true })));
72715
72934
  }
72716
72935
 
72717
72936
  // src/project/knowledgeAssetRepair.ts
72718
- import { existsSync as existsSync20 } from "node:fs";
72937
+ import { existsSync as existsSync21 } from "node:fs";
72719
72938
  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";
72939
+ import { dirname as dirname21, join as join32 } from "node:path";
72721
72940
  init_cliFeedback();
72722
72941
  init_errors();
72723
72942
  init_exitCode();
@@ -72728,14 +72947,14 @@ function sourceLocators(frontmatter) {
72728
72947
  ])];
72729
72948
  }
72730
72949
  async function bytesEqual(path3, expected) {
72731
- if (!existsSync20(path3))
72950
+ if (!existsSync21(path3))
72732
72951
  return false;
72733
72952
  const actual = await readFile26(path3);
72734
72953
  return actual.length === expected.length && actual.equals(Buffer.from(expected));
72735
72954
  }
72736
72955
  async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72737
72956
  const affected = [];
72738
- for (const file of await walkMarkdown(join31(projectRoot, "knowledge"))) {
72957
+ for (const file of await walkMarkdown(join32(projectRoot, "knowledge"))) {
72739
72958
  if (isKnowledgeAssetPath(file.relPath))
72740
72959
  continue;
72741
72960
  const content3 = await readFile26(file.absPath, "utf8");
@@ -72809,7 +73028,7 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72809
73028
  for (const asset of assets.values()) {
72810
73029
  if (await bytesEqual(asset.absPath, asset.bytes))
72811
73030
  continue;
72812
- await mkdir16(dirname20(asset.absPath), { recursive: true });
73031
+ await mkdir16(dirname21(asset.absPath), { recursive: true });
72813
73032
  await writeFile12(asset.absPath, asset.bytes);
72814
73033
  writtenAssets.push(asset.relPath);
72815
73034
  }
@@ -72825,7 +73044,7 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72825
73044
 
72826
73045
  // src/project/close.ts
72827
73046
  var KNOWLEDGE_ROOT2 = "knowledge";
72828
- var STRUCTURE_PATH = join32(KNOWLEDGE_ROOT2, "structure.yaml");
73047
+ var STRUCTURE_PATH = join33(KNOWLEDGE_ROOT2, "structure.yaml");
72829
73048
  var STRUCTURE_SCHEMA_VERSION2 = "context.approved-structure.v1";
72830
73049
  var LOCAL_REF2 = /^src-(\d+)(#(?:span|symbol):.+)$/u;
72831
73050
  var APPROVED_NODE_TYPES2 = new Set(["entity", "domain", "action"]);
@@ -72855,13 +73074,13 @@ function requiredFrontmatterString(frontmatter, field, relPath) {
72855
73074
  });
72856
73075
  }
72857
73076
  async function walkFiles2(root) {
72858
- if (!existsSync21(root))
73077
+ if (!existsSync22(root))
72859
73078
  return [];
72860
73079
  const files = [];
72861
73080
  const visit2 = async (dir) => {
72862
73081
  const entries = await readdir11(dir, { withFileTypes: true });
72863
73082
  for (const entry of entries) {
72864
- const absPath = join32(dir, entry.name);
73083
+ const absPath = join33(dir, entry.name);
72865
73084
  if (entry.isDirectory()) {
72866
73085
  await visit2(absPath);
72867
73086
  continue;
@@ -72886,7 +73105,7 @@ function isDeprecated(content3) {
72886
73105
  return parseFrontmatter3(content3).deprecated === true;
72887
73106
  }
72888
73107
  async function approvedKnowledgeFiles(projectRoot) {
72889
- const files = await walkFiles2(join32(projectRoot, KNOWLEDGE_ROOT2));
73108
+ const files = await walkFiles2(join33(projectRoot, KNOWLEDGE_ROOT2));
72890
73109
  const markdown = await Promise.all(files.filter((file) => file.relPath.endsWith(".md") && !isKnowledgeAssetPath(file.relPath)).map(async (file) => ({
72891
73110
  ...file,
72892
73111
  content: await readFile27(file.absPath, "utf8")
@@ -73156,11 +73375,11 @@ function referencesReceipt() {
73156
73375
  }
73157
73376
  async function readProjectCloseStatus(projectRoot) {
73158
73377
  const approved = await approvedKnowledgeFiles(projectRoot);
73159
- const structurePath = join32(projectRoot, STRUCTURE_PATH);
73160
- if (approved.length === 0 && !existsSync21(structurePath))
73378
+ const structurePath = join33(projectRoot, STRUCTURE_PATH);
73379
+ if (approved.length === 0 && !existsSync22(structurePath))
73161
73380
  return { state: "missing", diagnostics: [] };
73162
73381
  const inputHash = await approvedKnowledgeInputHash(projectRoot);
73163
- if (!existsSync21(structurePath))
73382
+ if (!existsSync22(structurePath))
73164
73383
  return { state: "missing", inputHash, diagnostics: [`close structure is missing: ${STRUCTURE_PATH}`] };
73165
73384
  try {
73166
73385
  const parsed = import_yaml14.default.parse(await readFile27(structurePath, "utf8"));
@@ -73229,8 +73448,8 @@ async function closeProjectWorkspace(projectRoot) {
73229
73448
  next: "Fix context verify errors, then rerun context close --format json."
73230
73449
  });
73231
73450
  }
73232
- const outputPath = join32(projectRoot, STRUCTURE_PATH);
73233
- await mkdir17(dirname21(outputPath), { recursive: true });
73451
+ const outputPath = join33(projectRoot, STRUCTURE_PATH);
73452
+ await mkdir17(dirname22(outputPath), { recursive: true });
73234
73453
  await writeFile13(outputPath, `${import_yaml14.default.stringify(structure)}`, "utf8");
73235
73454
  await clearCompletedLifecycle(projectRoot);
73236
73455
  return {
@@ -73279,22 +73498,33 @@ async function runProjectCloseCommand(input) {
73279
73498
  ].join(`
73280
73499
  `));
73281
73500
  }
73501
+ queueContextRuntimeEvent({
73502
+ cwd: result.projectRoot,
73503
+ kind: "knowledge.closed",
73504
+ properties: {
73505
+ node_count: result.nodes,
73506
+ view_count: result.views,
73507
+ edge_count: result.edges,
73508
+ verify_warning_count: result.verifyWarnings,
73509
+ relationship_coverage: result.relationshipCoverage.state
73510
+ }
73511
+ });
73282
73512
  return true;
73283
73513
  }
73284
73514
 
73285
73515
  // src/project/reviewApply.ts
73286
- import { existsSync as existsSync26 } from "node:fs";
73516
+ import { existsSync as existsSync27 } from "node:fs";
73287
73517
  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";
73518
+ import { dirname as dirname27, join as join42 } from "node:path";
73289
73519
  init_cliFeedback();
73290
73520
  init_errors();
73291
73521
  init_exitCode();
73292
73522
 
73293
73523
  // src/project/proseCompileStructure.ts
73294
73524
  import { createHash as createHash15 } from "node:crypto";
73295
- import { existsSync as existsSync24 } from "node:fs";
73525
+ import { existsSync as existsSync25 } from "node:fs";
73296
73526
  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";
73527
+ import { dirname as dirname25, join as join40 } from "node:path";
73298
73528
  init_cliFeedback();
73299
73529
  init_errors();
73300
73530
  init_exitCode();
@@ -73303,7 +73533,7 @@ var import_yaml20 = __toESM(require_dist3(), 1);
73303
73533
  // src/project/proseAlignEvidence.ts
73304
73534
  import { createHash as createHash13 } from "node:crypto";
73305
73535
  import { readFile as readFile28 } from "node:fs/promises";
73306
- import { join as join33 } from "node:path";
73536
+ import { join as join34 } from "node:path";
73307
73537
 
73308
73538
  // src/incremental/rawBlocks.ts
73309
73539
  var import_yaml15 = __toESM(require_dist3(), 1);
@@ -77198,7 +77428,7 @@ async function loadProseEvidence(input) {
77198
77428
  const documents = [];
77199
77429
  const chunks = [];
77200
77430
  for (const [documentIndex, document4] of indexResult.index.documents.entries()) {
77201
- const markdown = await readFile28(join33(input.projectRoot, indexResult.index.materialized_at, document4.path), "utf8");
77431
+ const markdown = await readFile28(join34(input.projectRoot, indexResult.index.materialized_at, document4.path), "utf8");
77202
77432
  const locator = locatorFor({
77203
77433
  sourceType: resolved.sourceType,
77204
77434
  sourceName: resolved.sourceName,
@@ -77673,19 +77903,19 @@ function repairHints(diagnostics, phaseId) {
77673
77903
 
77674
77904
  // src/project/proseAlignStructureSummary.ts
77675
77905
  import { mkdir as mkdir18, writeFile as writeFile14 } from "node:fs/promises";
77676
- import { dirname as dirname22, join as join36 } from "node:path";
77906
+ import { dirname as dirname23, join as join37 } from "node:path";
77677
77907
 
77678
77908
  // src/project/proseAlignExistingApprovedStructure.ts
77679
77909
  var import_yaml16 = __toESM(require_dist3(), 1);
77680
- import { existsSync as existsSync22 } from "node:fs";
77910
+ import { existsSync as existsSync23 } from "node:fs";
77681
77911
  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");
77912
+ import { basename as basename7, join as join35, relative as relative14 } from "node:path";
77913
+ var APPROVED_STRUCTURE_PATH4 = join35("knowledge", "structure.yaml");
77684
77914
  var KNOWLEDGE_ROOT3 = "knowledge";
77685
77915
  function uniqueRefs(refs) {
77686
77916
  return [...new Set(refs)].sort();
77687
77917
  }
77688
- function isRecord14(value) {
77918
+ function isRecord15(value) {
77689
77919
  return value !== null && typeof value === "object" && !Array.isArray(value);
77690
77920
  }
77691
77921
  function stringField3(record, key) {
@@ -77702,14 +77932,14 @@ function toPosixPath10(path4) {
77702
77932
  return path4.split(/[\\/]+/u).join("/");
77703
77933
  }
77704
77934
  async function approvedMarkdownFiles(projectRoot) {
77705
- const root2 = join34(projectRoot, KNOWLEDGE_ROOT3);
77706
- if (!existsSync22(root2))
77935
+ const root2 = join35(projectRoot, KNOWLEDGE_ROOT3);
77936
+ if (!existsSync23(root2))
77707
77937
  return [];
77708
77938
  const files = [];
77709
77939
  const visit3 = async (directory) => {
77710
77940
  const entries = await readdir12(directory, { withFileTypes: true });
77711
77941
  for (const entry of entries) {
77712
- const absolutePath = join34(directory, entry.name);
77942
+ const absolutePath = join35(directory, entry.name);
77713
77943
  if (entry.isDirectory()) {
77714
77944
  await visit3(absolutePath);
77715
77945
  continue;
@@ -77726,7 +77956,7 @@ function frontmatterRecord(markdown) {
77726
77956
  if (match === null)
77727
77957
  return;
77728
77958
  const parsed = import_yaml16.default.parse(match[1] ?? "");
77729
- return isRecord14(parsed) ? parsed : undefined;
77959
+ return isRecord15(parsed) ? parsed : undefined;
77730
77960
  }
77731
77961
  function isDeprecatedApprovedPage(markdown) {
77732
77962
  return /^deprecated:\s*true\s*$/mu.test(markdown);
@@ -77775,7 +78005,7 @@ async function parseExistingApprovedMarkdown(projectRoot) {
77775
78005
  node_type: existingNode?.node_type ?? nodeType,
77776
78006
  tags: uniqueRefs([...existingNode?.tags ?? [], ...nodeTags])
77777
78007
  });
77778
- const relPath = toPosixPath10(relative14(join34(projectRoot, KNOWLEDGE_ROOT3), filePath));
78008
+ const relPath = toPosixPath10(relative14(join35(projectRoot, KNOWLEDGE_ROOT3), filePath));
77779
78009
  const location = pathLocation(relPath);
77780
78010
  const collection = viewRef.split(":", 1)[0] ?? location.collection;
77781
78011
  views.set(viewRef, {
@@ -77804,8 +78034,8 @@ async function parseExistingApprovedMarkdown(projectRoot) {
77804
78034
  return { nodes, views, sections, edges: [], diagnostics: [] };
77805
78035
  }
77806
78036
  async function readFreshApprovedStructureEdges(projectRoot) {
77807
- const absolutePath = join34(projectRoot, APPROVED_STRUCTURE_PATH4);
77808
- if (!existsSync22(absolutePath))
78037
+ const absolutePath = join35(projectRoot, APPROVED_STRUCTURE_PATH4);
78038
+ if (!existsSync23(absolutePath))
77809
78039
  return { edges: [], diagnostics: [] };
77810
78040
  let raw;
77811
78041
  try {
@@ -77814,7 +78044,7 @@ async function readFreshApprovedStructureEdges(projectRoot) {
77814
78044
  const message = error instanceof Error ? error.message : String(error);
77815
78045
  return { edges: [], diagnostics: [`knowledge/structure.yaml could not be parsed: ${message}`] };
77816
78046
  }
77817
- if (!isRecord14(raw) || raw.schema_version !== "context.approved-structure.v1") {
78047
+ if (!isRecord15(raw) || raw.schema_version !== "context.approved-structure.v1") {
77818
78048
  return { edges: [], diagnostics: ["knowledge/structure.yaml schema is not current; approved summary uses Markdown projection only."] };
77819
78049
  }
77820
78050
  const expectedInputHash = await approvedKnowledgeInputHash(projectRoot).catch(() => {
@@ -77848,7 +78078,7 @@ function emptyExistingApprovedStructureSummary(diagnostics = []) {
77848
78078
  function parseApprovedEdges(raw) {
77849
78079
  const edges = [];
77850
78080
  for (const rawEdge of Array.isArray(raw.edges) ? raw.edges : []) {
77851
- if (!isRecord14(rawEdge))
78081
+ if (!isRecord15(rawEdge))
77852
78082
  continue;
77853
78083
  const type = stringField3(rawEdge, "type");
77854
78084
  const from = stringField3(rawEdge, "from");
@@ -77918,7 +78148,7 @@ async function readExistingApprovedStructureSummary(input) {
77918
78148
  const freshStructure = await readFreshApprovedStructureEdges(input.projectRoot);
77919
78149
  approved.edges = freshStructure.edges;
77920
78150
  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))) {
78151
+ if (approved.nodes.size === 0 && approved.views.size === 0 && approved.sections.size === 0 && !existsSync23(join35(input.projectRoot, APPROVED_STRUCTURE_PATH4))) {
77922
78152
  return emptyExistingApprovedStructureSummary();
77923
78153
  }
77924
78154
  const endpointRefs = new Set([
@@ -79026,12 +79256,12 @@ function renderStructureSummaryHtml(input) {
79026
79256
 
79027
79257
  // src/project/localHtmlReport.ts
79028
79258
  import { execFile as execFile3 } from "node:child_process";
79029
- import { isAbsolute as isAbsolute7, join as join35 } from "node:path";
79259
+ import { isAbsolute as isAbsolute7, join as join36 } from "node:path";
79030
79260
  import { pathToFileURL } from "node:url";
79031
79261
  import { promisify as promisify3 } from "node:util";
79032
79262
  var execFileAsync3 = promisify3(execFile3);
79033
79263
  function htmlReportReference(input) {
79034
- const absolutePath = isAbsolute7(input.path) ? input.path : join35(input.projectRoot, input.path);
79264
+ const absolutePath = isAbsolute7(input.path) ? input.path : join36(input.projectRoot, input.path);
79035
79265
  return {
79036
79266
  format: "html",
79037
79267
  path: input.path,
@@ -79377,9 +79607,9 @@ function buildStructureSummary(input) {
79377
79607
  async function writeStructureSummaryReport(input) {
79378
79608
  const summary = buildStructureSummary(input);
79379
79609
  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 });
79610
+ const reportPath = join37(".tmp", "context-runtime", "reports", `structure-summary-${shortDigest}.html`);
79611
+ const absolutePath = join37(input.projectRoot, reportPath);
79612
+ await mkdir18(dirname23(absolutePath), { recursive: true });
79383
79613
  await writeFile14(absolutePath, renderStructureSummaryHtml({ summary, diagnostics: input.diagnostics }), "utf8");
79384
79614
  return {
79385
79615
  summary,
@@ -79554,9 +79784,9 @@ function withStructureReviewArtifacts(input) {
79554
79784
  // src/project/proseCompileViews.ts
79555
79785
  var import_yaml17 = __toESM(require_dist3(), 1);
79556
79786
  import { createHash as createHash14 } from "node:crypto";
79557
- import { existsSync as existsSync23 } from "node:fs";
79787
+ import { existsSync as existsSync24 } from "node:fs";
79558
79788
  import { readFile as readFile30 } from "node:fs/promises";
79559
- import { join as join37 } from "node:path";
79789
+ import { join as join38 } from "node:path";
79560
79790
 
79561
79791
  // src/project/proseCompileSemanticRules.ts
79562
79792
  function compileSemanticRules(input) {
@@ -79959,8 +80189,8 @@ function canonicalizeApprovedSourceRef2(ref2, sources) {
79959
80189
  }
79960
80190
  async function existingApprovedNodeSections(input) {
79961
80191
  const relativePath = `knowledge/${input.node.path}`;
79962
- const absolutePath = join37(input.projectRoot, relativePath);
79963
- if (!existsSync23(absolutePath)) {
80192
+ const absolutePath = join38(input.projectRoot, relativePath);
80193
+ if (!existsSync24(absolutePath)) {
79964
80194
  return {
79965
80195
  path: relativePath,
79966
80196
  present: false,
@@ -80342,7 +80572,7 @@ function parsePayloadText(raw) {
80342
80572
  // src/project/proseAlignPayloadStage.ts
80343
80573
  var import_yaml19 = __toESM(require_dist3(), 1);
80344
80574
  import { mkdir as mkdir19, writeFile as writeFile15 } from "node:fs/promises";
80345
- import { dirname as dirname23, join as join38 } from "node:path";
80575
+ import { dirname as dirname24, join as join39 } from "node:path";
80346
80576
  init_writeLock();
80347
80577
  async function resolveStagedPayloadConfirmation(input) {
80348
80578
  await archiveActiveStructure(input.projectRoot);
@@ -80413,7 +80643,7 @@ async function stageAlignPayload(input) {
80413
80643
  next: readPlanCommand
80414
80644
  });
80415
80645
  }
80416
- const structurePath = join38(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
80646
+ const structurePath = join39(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
80417
80647
  const resolved = await resolveStagedPayloadConfirmation(input);
80418
80648
  const effectivePayload = {
80419
80649
  ...resolved.payload,
@@ -80425,7 +80655,7 @@ async function stageAlignPayload(input) {
80425
80655
  if (effectivePayload.lifecycle.state === "confirmed" || effectivePayload.lifecycle.state === "frozen") {
80426
80656
  await writeStructureSnapshot(input.projectRoot, effectivePayload);
80427
80657
  }
80428
- await mkdir19(dirname23(structurePath), { recursive: true });
80658
+ await mkdir19(dirname24(structurePath), { recursive: true });
80429
80659
  await writeFile15(structurePath, import_yaml19.default.stringify(normalizeAlignPayloadForWrite(effectivePayload)), "utf8");
80430
80660
  return {
80431
80661
  structureFile: LIFECYCLE_STRUCTURE_FILE,
@@ -80941,7 +81171,7 @@ function canonicalJson2(value) {
80941
81171
  function digest3(value) {
80942
81172
  return `sha256:${createHash15("sha256").update(canonicalJson2(value)).digest("hex")}`;
80943
81173
  }
80944
- function isRecord15(value) {
81174
+ function isRecord16(value) {
80945
81175
  return value !== null && typeof value === "object" && !Array.isArray(value);
80946
81176
  }
80947
81177
  function stringField4(record, field) {
@@ -80952,8 +81182,8 @@ function stringArray2(value) {
80952
81182
  return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
80953
81183
  }
80954
81184
  async function readStructureFile(projectRoot) {
80955
- const structurePath = join39(projectRoot, LIFECYCLE_STRUCTURE_FILE);
80956
- if (!existsSync24(structurePath)) {
81185
+ const structurePath = join40(projectRoot, LIFECYCLE_STRUCTURE_FILE);
81186
+ if (!existsSync25(structurePath)) {
80957
81187
  return null;
80958
81188
  }
80959
81189
  let raw;
@@ -80978,8 +81208,8 @@ async function readStructureFile(projectRoot) {
80978
81208
  }
80979
81209
  }
80980
81210
  async function readApprovedStructureFile(projectRoot) {
80981
- const structurePath = join39(projectRoot, APPROVED_STRUCTURE_FILE2);
80982
- if (!existsSync24(structurePath))
81211
+ const structurePath = join40(projectRoot, APPROVED_STRUCTURE_FILE2);
81212
+ if (!existsSync25(structurePath))
80983
81213
  return null;
80984
81214
  try {
80985
81215
  return import_yaml20.default.parse(await readFile32(structurePath, "utf8"));
@@ -80994,13 +81224,13 @@ async function readApprovedStructureFile(projectRoot) {
80994
81224
  async function compileStructureSlotDigest(input) {
80995
81225
  const slotDigest = await currentStructureSlotDigest(input.projectRoot, input.sourceKey, input.collection);
80996
81226
  const current2 = await readStructureFile(input.projectRoot);
80997
- if (current2 === null || !isRecord15(current2) || !Array.isArray(current2.sources) || !Array.isArray(current2.views)) {
81227
+ if (current2 === null || !isRecord16(current2) || !Array.isArray(current2.sources) || !Array.isArray(current2.views)) {
80998
81228
  return slotDigest;
80999
81229
  }
81000
- const currentOwnsTarget = current2.sources.includes(input.sourceKey) && current2.views.some((view) => isRecord15(view) && view.collection === input.collection);
81230
+ const currentOwnsTarget = current2.sources.includes(input.sourceKey) && current2.views.some((view) => isRecord16(view) && view.collection === input.collection);
81001
81231
  if (!currentOwnsTarget)
81002
81232
  return slotDigest;
81003
- const lifecycle = isRecord15(current2.lifecycle) ? current2.lifecycle : undefined;
81233
+ const lifecycle = isRecord16(current2.lifecycle) ? current2.lifecycle : undefined;
81004
81234
  const currentDigest = lifecycle === undefined ? undefined : stringField4(lifecycle, "structure_digest");
81005
81235
  return slotDigest !== undefined && slotDigest !== currentDigest ? slotDigest : undefined;
81006
81236
  }
@@ -81009,7 +81239,7 @@ function parseApprovedSections(value, viewRef) {
81009
81239
  return [];
81010
81240
  const sections = [];
81011
81241
  for (const rawSection of value) {
81012
- if (!isRecord15(rawSection))
81242
+ if (!isRecord16(rawSection))
81013
81243
  continue;
81014
81244
  const id2 = stringField4(rawSection, "id");
81015
81245
  const kind = stringField4(rawSection, "kind");
@@ -81032,7 +81262,7 @@ function parseApprovedNodes(value) {
81032
81262
  return [];
81033
81263
  const nodes = [];
81034
81264
  for (const rawNode of value) {
81035
- if (!isRecord15(rawNode))
81265
+ if (!isRecord16(rawNode))
81036
81266
  continue;
81037
81267
  const nodeRef = stringField4(rawNode, "node_ref");
81038
81268
  const title = stringField4(rawNode, "title");
@@ -81056,7 +81286,7 @@ function parseApprovedViews(value, nodes) {
81056
81286
  const nodeByRef = new Map(nodes.map((node3) => [node3.node_ref, node3]));
81057
81287
  const views = [];
81058
81288
  for (const rawView of value) {
81059
- if (!isRecord15(rawView))
81289
+ if (!isRecord16(rawView))
81060
81290
  continue;
81061
81291
  const viewRef = stringField4(rawView, "view_ref");
81062
81292
  const nodeRef = stringField4(rawView, "node_ref");
@@ -81094,7 +81324,7 @@ function parseApprovedEdges2(value) {
81094
81324
  return [];
81095
81325
  const edges = [];
81096
81326
  for (const rawEdge of value) {
81097
- if (!isRecord15(rawEdge))
81327
+ if (!isRecord16(rawEdge))
81098
81328
  continue;
81099
81329
  const type = stringField4(rawEdge, "type");
81100
81330
  const from = stringField4(rawEdge, "from");
@@ -81158,7 +81388,7 @@ function assertApprovedEdgeContract(value, endpointRefs) {
81158
81388
  });
81159
81389
  }
81160
81390
  for (const [index2, rawEdge] of value.entries()) {
81161
- if (!isRecord15(rawEdge)) {
81391
+ if (!isRecord16(rawEdge)) {
81162
81392
  throw workspaceError("knowledge/structure.yaml edge must be an object", {
81163
81393
  path: APPROVED_STRUCTURE_FILE2,
81164
81394
  edge_index: index2,
@@ -81298,7 +81528,7 @@ async function loadConfirmedStructure(input) {
81298
81528
  let rawStructure = input.structureDigest === undefined ? await readStructureFile(input.projectRoot) : await readStructureSnapshot(input.projectRoot, input.structureDigest);
81299
81529
  if (rawStructure === null && input.structureDigest !== undefined) {
81300
81530
  const active = await readStructureFile(input.projectRoot);
81301
- const activeDigest = isRecord15(active) && isRecord15(active.lifecycle) ? stringField4(active.lifecycle, "structure_digest") : undefined;
81531
+ const activeDigest = isRecord16(active) && isRecord16(active.lifecycle) ? stringField4(active.lifecycle, "structure_digest") : undefined;
81302
81532
  if (activeDigest === input.structureDigest) {
81303
81533
  rawStructure = active;
81304
81534
  } else if (input.readOnly !== true) {
@@ -81315,7 +81545,7 @@ async function loadConfirmedStructure(input) {
81315
81545
  });
81316
81546
  }
81317
81547
  const approvedStructure = await readApprovedStructureFile(input.projectRoot);
81318
- if (!isRecord15(approvedStructure)) {
81548
+ if (!isRecord16(approvedStructure)) {
81319
81549
  throw workspaceError("compileProse requires confirmed .tmp/context-runtime/lifecycle/structure.yaml or approved knowledge/structure.yaml", {
81320
81550
  path: LIFECYCLE_STRUCTURE_FILE,
81321
81551
  approved_structure: APPROVED_STRUCTURE_FILE2,
@@ -81411,8 +81641,8 @@ async function freezeStructureIfNeeded(input) {
81411
81641
  };
81412
81642
  await archiveActiveStructure(input.projectRoot);
81413
81643
  await writeStructureSnapshot(input.projectRoot, nextStructure);
81414
- const structurePath = join39(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
81415
- await mkdir20(dirname24(structurePath), { recursive: true });
81644
+ const structurePath = join40(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
81645
+ await mkdir20(dirname25(structurePath), { recursive: true });
81416
81646
  await writeFile16(structurePath, import_yaml20.default.stringify({
81417
81647
  schema_version: nextStructure.schema_version,
81418
81648
  sources: nextStructure.sources,
@@ -81495,9 +81725,9 @@ var import_yaml22 = __toESM(require_dist3(), 1);
81495
81725
 
81496
81726
  // src/project/reviewShared.ts
81497
81727
  import { createHash as createHash16 } from "node:crypto";
81498
- import { existsSync as existsSync25, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "node:fs";
81728
+ import { existsSync as existsSync26, readdirSync as readdirSync2, readFileSync as readFileSync7 } from "node:fs";
81499
81729
  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";
81730
+ import { dirname as dirname26, join as join41 } from "node:path";
81501
81731
  init_cliFeedback();
81502
81732
  init_errors();
81503
81733
  init_exitCode();
@@ -81527,10 +81757,10 @@ function proseCandidateMarkdown(input) {
81527
81757
 
81528
81758
  // src/project/reviewShared.ts
81529
81759
  init_workspace();
81530
- var SNAPSHOT_ROOT2 = join40(".tmp", "context-runtime", "extract", "candidates");
81531
- var REVIEW_ACTION_ROOT2 = join40(".tmp", "context-runtime", "review-actions");
81760
+ var SNAPSHOT_ROOT2 = join41(".tmp", "context-runtime", "extract", "candidates");
81761
+ var REVIEW_ACTION_ROOT2 = join41(".tmp", "context-runtime", "review-actions");
81532
81762
  var REVIEW_PAYLOAD_SCHEMA = "context.review.decisions.v1";
81533
- function isRecord16(value) {
81763
+ function isRecord17(value) {
81534
81764
  return value !== null && typeof value === "object" && !Array.isArray(value);
81535
81765
  }
81536
81766
  function assertCollection(value) {
@@ -81551,26 +81781,26 @@ function assertCollection(value) {
81551
81781
  }
81552
81782
  function snapshotPath2(projectRoot, candidateId) {
81553
81783
  assertSafeEntityId(candidateId);
81554
- return join40(projectRoot, SNAPSHOT_ROOT2, `${candidateId}.json`);
81784
+ return join41(projectRoot, SNAPSHOT_ROOT2, `${candidateId}.json`);
81555
81785
  }
81556
81786
  async function readCandidateSnapshot(projectRoot, candidateId) {
81557
81787
  const file = snapshotPath2(projectRoot, candidateId);
81558
- if (!existsSync25(file))
81788
+ if (!existsSync26(file))
81559
81789
  return;
81560
81790
  let parsed;
81561
81791
  try {
81562
81792
  parsed = JSON.parse(await readFile33(file, "utf8"));
81563
81793
  } catch (error) {
81564
81794
  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`)}`, {
81795
+ throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid JSON: ${join41(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81566
81796
  category: ErrorCategory.SchemaInvalid,
81567
81797
  candidate_id: candidateId,
81568
81798
  reason: message,
81569
81799
  next: "Rerun the extract phase before reviewing this candidate."
81570
81800
  });
81571
81801
  }
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`)}`, {
81802
+ if (!isRecord17(parsed) || typeof parsed.candidate_id !== "string" || typeof parsed.markdown !== "string") {
81803
+ throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid: ${join41(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81574
81804
  category: ErrorCategory.SchemaInvalid,
81575
81805
  candidate_id: candidateId,
81576
81806
  next: "Rerun the extract phase before reviewing this candidate."
@@ -81601,15 +81831,15 @@ async function extractCandidateSnapshotIsCurrent(projectRoot, snapshot) {
81601
81831
  async function removeCandidateSnapshot2(projectRoot, candidateId) {
81602
81832
  const file = snapshotPath2(projectRoot, candidateId);
81603
81833
  await rm10(file, { force: true });
81604
- const snapshotRoot = join40(projectRoot, SNAPSHOT_ROOT2);
81605
- let current2 = dirname25(file);
81834
+ const snapshotRoot = join41(projectRoot, SNAPSHOT_ROOT2);
81835
+ let current2 = dirname26(file);
81606
81836
  while (current2 !== snapshotRoot && current2.startsWith(snapshotRoot)) {
81607
81837
  try {
81608
81838
  await rmdir2(current2);
81609
81839
  } catch {
81610
81840
  break;
81611
81841
  }
81612
- current2 = dirname25(current2);
81842
+ current2 = dirname26(current2);
81613
81843
  }
81614
81844
  }
81615
81845
  function parseCanonicalSourceRef(ref2) {
@@ -81730,11 +81960,11 @@ function findApprovedPageForViewRef(projectRoot, viewRef) {
81730
81960
  }
81731
81961
  const nodeRef = viewRef.slice(separator + 1);
81732
81962
  assertSafeEntityId(nodeRef);
81733
- const collectionRoot = join40(projectRoot, "knowledge", collection);
81734
- if (existsSync25(collectionRoot)) {
81963
+ const collectionRoot = join41(projectRoot, "knowledge", collection);
81964
+ if (existsSync26(collectionRoot)) {
81735
81965
  const visit3 = (dir, relDir) => {
81736
81966
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
81737
- const absPath = join40(dir, entry.name);
81967
+ const absPath = join41(dir, entry.name);
81738
81968
  const rel = relDir.length === 0 ? entry.name : `${relDir}/${entry.name}`;
81739
81969
  if (entry.isDirectory()) {
81740
81970
  const found2 = visit3(absPath, rel);
@@ -81744,16 +81974,16 @@ function findApprovedPageForViewRef(projectRoot, viewRef) {
81744
81974
  }
81745
81975
  if (!entry.isFile() || !entry.name.endsWith(".md"))
81746
81976
  continue;
81747
- const block = frontmatterBlock(readFileSync6(absPath, "utf8"));
81977
+ const block = frontmatterBlock(readFileSync7(absPath, "utf8"));
81748
81978
  if (block === null)
81749
81979
  continue;
81750
81980
  const parsed = import_yaml21.default.parse(block.yaml);
81751
- if (!isRecord16(parsed) || parsed.view_ref !== viewRef)
81981
+ if (!isRecord17(parsed) || parsed.view_ref !== viewRef)
81752
81982
  continue;
81753
81983
  const approvedNodeRef = typeof parsed.node_ref === "string" && parsed.node_ref.trim().length > 0 ? parsed.node_ref.trim() : nodeRef;
81754
81984
  return {
81755
81985
  path: absPath,
81756
- relPath: join40("knowledge", collection, rel),
81986
+ relPath: join41("knowledge", collection, rel),
81757
81987
  nodeRef: approvedNodeRef
81758
81988
  };
81759
81989
  }
@@ -81794,7 +82024,7 @@ function updateFrontmatter(content3, mutate) {
81794
82024
  });
81795
82025
  }
81796
82026
  const parsed = import_yaml21.default.parse(block.yaml);
81797
- if (!isRecord16(parsed)) {
82027
+ if (!isRecord17(parsed)) {
81798
82028
  throw new ContextError(ExitCode.WorkspaceStateError, "approved page frontmatter must be a YAML object", {
81799
82029
  category: ErrorCategory.SchemaInvalid
81800
82030
  });
@@ -81809,16 +82039,16 @@ function parseApprovedSources(content3) {
81809
82039
  if (block === null)
81810
82040
  return [];
81811
82041
  const parsed = import_yaml21.default.parse(block.yaml);
81812
- if (!isRecord16(parsed))
82042
+ if (!isRecord17(parsed))
81813
82043
  return [];
81814
82044
  const sources = parsed.sources;
81815
82045
  return Array.isArray(sources) ? sources.filter((source2) => typeof source2 === "string") : [];
81816
82046
  }
81817
82047
  async function writeReviewActionLog(input) {
81818
82048
  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 });
82049
+ const relPath = join41(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
82050
+ const path4 = join41(input.projectRoot, relPath);
82051
+ await mkdir21(dirname26(path4), { recursive: true });
81822
82052
  await writeFile17(path4, `${JSON.stringify({
81823
82053
  action: input.action,
81824
82054
  id: input.id,
@@ -82313,7 +82543,7 @@ async function prepareApprovedPage(input) {
82313
82543
  if (input.record.candidate_type !== "prose-align") {
82314
82544
  assertSafeEntityId(input.record.node_ref);
82315
82545
  }
82316
- relPath = join41("knowledge", input.record.path);
82546
+ relPath = join42("knowledge", input.record.path);
82317
82547
  const existingView = findApprovedPageForViewRef(input.projectRoot, input.record.view_ref);
82318
82548
  if (existingView !== undefined && existingView.relPath !== relPath) {
82319
82549
  throw new ContextError(ExitCode.WorkspaceStateError, `approved page already exists for view_ref at a different path: ${input.record.view_ref}`, {
@@ -82325,8 +82555,8 @@ async function prepareApprovedPage(input) {
82325
82555
  next: "Resolve the approved page path migration explicitly before approving this candidate."
82326
82556
  });
82327
82557
  }
82328
- const absPath = join41(input.projectRoot, relPath);
82329
- const existing = existsSync26(absPath) ? await readFile34(absPath, "utf8") : undefined;
82558
+ const absPath = join42(input.projectRoot, relPath);
82559
+ const existing = existsSync27(absPath) ? await readFile34(absPath, "utf8") : undefined;
82330
82560
  if (existing !== undefined) {
82331
82561
  const frontmatter = parseFrontmatterLoose(existing);
82332
82562
  const existingViewRef = typeof frontmatter.view_ref === "string" ? frontmatter.view_ref : undefined;
@@ -82398,11 +82628,11 @@ async function prepareApprovedPage(input) {
82398
82628
  }
82399
82629
  async function writePreparedApprovedPage(page) {
82400
82630
  for (const asset of page.assets) {
82401
- await mkdir22(dirname26(asset.absPath), { recursive: true });
82631
+ await mkdir22(dirname27(asset.absPath), { recursive: true });
82402
82632
  await writeFile18(asset.absPath, asset.bytes);
82403
82633
  }
82404
82634
  if (page.changed) {
82405
- await mkdir22(dirname26(page.absPath), { recursive: true });
82635
+ await mkdir22(dirname27(page.absPath), { recursive: true });
82406
82636
  await writeFile18(page.absPath, page.content, "utf8");
82407
82637
  }
82408
82638
  }
@@ -82633,18 +82863,18 @@ init_errors();
82633
82863
  init_exitCode();
82634
82864
 
82635
82865
  // src/project/repoSources.ts
82636
- import { existsSync as existsSync29 } from "node:fs";
82866
+ import { existsSync as existsSync30 } from "node:fs";
82637
82867
  import { lstat, mkdir as mkdir23, readFile as readFile35, readlink, realpath as realpath2, rm as rm12, symlink } from "node:fs/promises";
82638
82868
  import { execFile as execFile4 } from "node:child_process";
82639
82869
  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";
82870
+ import { dirname as dirname28, isAbsolute as isAbsolute8, join as join45, relative as relative15, resolve as resolve17 } from "node:path";
82641
82871
  init_cliFeedback();
82642
82872
  init_errors();
82643
82873
  init_exitCode();
82644
82874
 
82645
82875
  // src/project/repoSourceModules.ts
82646
- import { existsSync as existsSync27 } from "node:fs";
82647
- import { join as join42, resolve as resolve16 } from "node:path";
82876
+ import { existsSync as existsSync28 } from "node:fs";
82877
+ import { join as join43, resolve as resolve16 } from "node:path";
82648
82878
  function normalizeSubpath(value) {
82649
82879
  if (value === undefined)
82650
82880
  return;
@@ -82671,8 +82901,8 @@ function suggestedModuleName(module) {
82671
82901
  return slug || "module";
82672
82902
  }
82673
82903
  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) : [];
82904
+ const inspectPath = input.scopedAbs !== null && existsSync28(input.scopedAbs) ? input.scopedAbs : join43(input.projectRoot, input.status.materializedAt);
82905
+ const modules = existsSync28(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
82676
82906
  const recommended_sources = modules.filter((module) => module.path !== "." || modules.length === 1).map((module) => {
82677
82907
  const local = sourceModuleLocalForDisplay({ source: input.source, status: input.status, module });
82678
82908
  return {
@@ -82703,8 +82933,8 @@ function resolveRepoSourceScopedPath(localAbs, subpath) {
82703
82933
 
82704
82934
  // src/project/repoSourceRegistry.ts
82705
82935
  var import_yaml24 = __toESM(require_dist3(), 1);
82706
- import { existsSync as existsSync28 } from "node:fs";
82707
- import { join as join43 } from "node:path";
82936
+ import { existsSync as existsSync29 } from "node:fs";
82937
+ import { join as join44 } from "node:path";
82708
82938
  init_cliFeedback();
82709
82939
  init_errors();
82710
82940
  init_exitCode();
@@ -82761,14 +82991,14 @@ function registryEntryToRecord(entry) {
82761
82991
  };
82762
82992
  }
82763
82993
  function registryPath(projectRoot) {
82764
- return join43(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
82994
+ return join44(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
82765
82995
  }
82766
82996
  function defaultRepoMaterializedAt(source2) {
82767
82997
  return `sources/repo/${source2.namespace}/${source2.module}`;
82768
82998
  }
82769
82999
  async function readRepoRegistry(projectRoot) {
82770
83000
  const path4 = registryPath(projectRoot);
82771
- if (!existsSync28(path4))
83001
+ if (!existsSync29(path4))
82772
83002
  return { repos: [] };
82773
83003
  const registry2 = await loadSourcesRegistry({ rootDir: projectRoot });
82774
83004
  return {
@@ -82844,13 +83074,13 @@ async function gitOutput(cwd, args) {
82844
83074
  }
82845
83075
  }
82846
83076
  async function readGitOriginRemote(cwd) {
82847
- const directConfigPath = join44(cwd, ".git", "config");
83077
+ const directConfigPath = join45(cwd, ".git", "config");
82848
83078
  let config = await readFile35(directConfigPath, "utf8").catch(() => "");
82849
83079
  if (config.length === 0) {
82850
83080
  const gitDir = await resolveGitDir(cwd);
82851
83081
  if (gitDir === null)
82852
83082
  return null;
82853
- config = await readFile35(join44(gitDir, "config"), "utf8").catch(() => "");
83083
+ config = await readFile35(join45(gitDir, "config"), "utf8").catch(() => "");
82854
83084
  }
82855
83085
  let inOriginBlock = false;
82856
83086
  for (const line of config.split(/\r?\n/u)) {
@@ -82870,17 +83100,17 @@ async function readGitOriginRemote(cwd) {
82870
83100
  async function resolveGitRoot(cwd) {
82871
83101
  let current2 = resolve17(cwd);
82872
83102
  while (true) {
82873
- if (existsSync29(join44(current2, ".git")))
83103
+ if (existsSync30(join45(current2, ".git")))
82874
83104
  return current2;
82875
- const parent = dirname27(current2);
83105
+ const parent = dirname28(current2);
82876
83106
  if (parent === current2)
82877
83107
  return null;
82878
83108
  current2 = parent;
82879
83109
  }
82880
83110
  }
82881
83111
  async function resolveGitDir(cwd) {
82882
- const dotGit = join44(cwd, ".git");
82883
- if (!existsSync29(dotGit))
83112
+ const dotGit = join45(cwd, ".git");
83113
+ if (!existsSync30(dotGit))
82884
83114
  return null;
82885
83115
  const stats = await lstat(dotGit);
82886
83116
  if (stats.isDirectory())
@@ -82897,17 +83127,17 @@ async function readGitHead(cwd) {
82897
83127
  const gitDir = await resolveGitDir(cwd);
82898
83128
  if (gitDir === null)
82899
83129
  return null;
82900
- const headRaw = (await readFile35(join44(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
83130
+ const headRaw = (await readFile35(join45(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
82901
83131
  if (/^[a-f0-9]{40}$/iu.test(headRaw))
82902
83132
  return headRaw.toLowerCase();
82903
83133
  const match = /^ref:\s*(.+)\s*$/iu.exec(headRaw);
82904
83134
  const refPath = match?.[1];
82905
83135
  if (refPath === undefined)
82906
83136
  return null;
82907
- const looseRef = (await readFile35(join44(gitDir, refPath), "utf8").catch(() => "")).trim();
83137
+ const looseRef = (await readFile35(join45(gitDir, refPath), "utf8").catch(() => "")).trim();
82908
83138
  if (/^[a-f0-9]{40}$/iu.test(looseRef))
82909
83139
  return looseRef.toLowerCase();
82910
- const packedRefs = await readFile35(join44(gitDir, "packed-refs"), "utf8").catch(() => "");
83140
+ const packedRefs = await readFile35(join45(gitDir, "packed-refs"), "utf8").catch(() => "");
82911
83141
  for (const line of packedRefs.split(/\r?\n/u)) {
82912
83142
  if (line.startsWith("#") || line.startsWith("^"))
82913
83143
  continue;
@@ -82918,27 +83148,27 @@ async function readGitHead(cwd) {
82918
83148
  return null;
82919
83149
  }
82920
83150
  async function ensureMaterializedSymlink(input) {
82921
- const linkPath = join44(input.projectRoot, input.materializedAt);
82922
- await mkdir23(dirname27(linkPath), { recursive: true });
82923
- if (existsSync29(linkPath)) {
83151
+ const linkPath = join45(input.projectRoot, input.materializedAt);
83152
+ await mkdir23(dirname28(linkPath), { recursive: true });
83153
+ if (existsSync30(linkPath)) {
82924
83154
  const stats = await lstat(linkPath);
82925
83155
  if (!stats.isSymbolicLink()) {
82926
83156
  input.diagnostics.push(`materialized path exists and is not a symlink: ${input.materializedAt}`);
82927
83157
  return false;
82928
83158
  }
82929
83159
  const current2 = await readlink(linkPath);
82930
- const currentAbs = resolve17(dirname27(linkPath), current2);
83160
+ const currentAbs = resolve17(dirname28(linkPath), current2);
82931
83161
  if (currentAbs === input.localAbs)
82932
83162
  return true;
82933
83163
  await rm12(linkPath);
82934
83164
  }
82935
- const relTarget = relative15(dirname27(linkPath), input.localAbs) || ".";
83165
+ const relTarget = relative15(dirname28(linkPath), input.localAbs) || ".";
82936
83166
  await symlink(relTarget, linkPath);
82937
83167
  return true;
82938
83168
  }
82939
83169
  async function diagnoseMaterializedSymlink(input) {
82940
- const linkPath = join44(input.projectRoot, input.materializedAt);
82941
- if (!existsSync29(linkPath)) {
83170
+ const linkPath = join45(input.projectRoot, input.materializedAt);
83171
+ if (!existsSync30(linkPath)) {
82942
83172
  input.diagnostics.push(`materialized path is missing: ${input.materializedAt}`);
82943
83173
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to materialize the local source link.`);
82944
83174
  return false;
@@ -82949,9 +83179,9 @@ async function diagnoseMaterializedSymlink(input) {
82949
83179
  return false;
82950
83180
  }
82951
83181
  const current2 = await readlink(linkPath);
82952
- const currentAbs = resolve17(dirname27(linkPath), current2);
83182
+ const currentAbs = resolve17(dirname28(linkPath), current2);
82953
83183
  if (currentAbs !== input.localAbs) {
82954
- input.diagnostics.push(`materialized path points to ${current2}, expected local checkout ${relative15(dirname27(linkPath), input.localAbs) || "."}`);
83184
+ input.diagnostics.push(`materialized path points to ${current2}, expected local checkout ${relative15(dirname28(linkPath), input.localAbs) || "."}`);
82955
83185
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to refresh the local source link.`);
82956
83186
  return false;
82957
83187
  }
@@ -82983,7 +83213,7 @@ async function normalizeInputRef(input) {
82983
83213
  next: "Pass --local <path> with a git checkout, or use a full 40-character commit sha."
82984
83214
  });
82985
83215
  }
82986
- if (!existsSync29(localAbs)) {
83216
+ if (!existsSync30(localAbs)) {
82987
83217
  throw new ContextError(ExitCode.UserError, `short repo source ref cannot be resolved because local path is missing: ${input.local}`, {
82988
83218
  category: ErrorCategory.UserInputInvalid,
82989
83219
  sourceName: input.sourceName,
@@ -83035,7 +83265,7 @@ async function normalizeAddInput(input, existing) {
83035
83265
  let gitRootAbs = null;
83036
83266
  if (originalLocal !== undefined) {
83037
83267
  const originalLocalAbs = resolveLocalPath(input.projectRoot, originalLocal);
83038
- if (originalLocalAbs !== null && existsSync29(originalLocalAbs)) {
83268
+ if (originalLocalAbs !== null && existsSync30(originalLocalAbs)) {
83039
83269
  gitRootAbs = await resolveGitRoot(originalLocalAbs);
83040
83270
  if (gitRootAbs !== null && input.local !== undefined) {
83041
83271
  const detectedSubpath = normalizeSubpath2(relative15(gitRootAbs, originalLocalAbs));
@@ -83131,11 +83361,11 @@ async function inspectRepoSource(input) {
83131
83361
  const diagnostics = [];
83132
83362
  const agent_hints = [];
83133
83363
  const localAbs = resolveLocalPath(input.projectRoot, source2.local);
83134
- const localExists = localAbs !== null && existsSync29(localAbs);
83364
+ const localExists = localAbs !== null && existsSync30(localAbs);
83135
83365
  const subpath = normalizeSubpath2(source2.subpath);
83136
83366
  const scopedAbs = localAbs === null ? null : scopedLocalPath(localAbs, subpath);
83137
- const scopeExists = scopedAbs !== null && existsSync29(scopedAbs);
83138
- let materialized = existsSync29(join44(input.projectRoot, materializedAt));
83367
+ const scopeExists = scopedAbs !== null && existsSync30(scopedAbs);
83368
+ let materialized = existsSync30(join45(input.projectRoot, materializedAt));
83139
83369
  const checkout = await inspectRepoCheckout({
83140
83370
  source: source2,
83141
83371
  localAbs,
@@ -83784,24 +84014,24 @@ The approved symbol is no longer present in the current code extraction.
83784
84014
  // src/project/packageBuilder.ts
83785
84015
  init_cliFeedback();
83786
84016
  init_errors();
83787
- init_exitCode();
83788
84017
  var import_yaml28 = __toESM(require_dist3(), 1);
83789
84018
  import { createHash as createHash20 } from "node:crypto";
83790
- import { existsSync as existsSync34 } from "node:fs";
84019
+ import { existsSync as existsSync35 } from "node:fs";
83791
84020
  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";
84021
+ import { dirname as dirname34, join as join52, resolve as resolve19 } from "node:path";
84022
+ init_exitCode();
83793
84023
 
83794
84024
  // src/project/packageBuildInventory.ts
83795
84025
  var import_yaml26 = __toESM(require_dist3(), 1);
83796
84026
  import { createHash as createHash17 } from "node:crypto";
83797
- import { existsSync as existsSync31 } from "node:fs";
84027
+ import { existsSync as existsSync32 } from "node:fs";
83798
84028
  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";
84029
+ import { dirname as dirname30, join as join47 } from "node:path";
83800
84030
 
83801
84031
  // src/project/packageIndexes.ts
83802
- import { existsSync as existsSync30, statSync } from "node:fs";
84032
+ import { existsSync as existsSync31, statSync } from "node:fs";
83803
84033
  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";
84034
+ import { dirname as dirname29, join as join46, posix as pathPosix, relative as relative16 } from "node:path";
83805
84035
  init_cliFeedback();
83806
84036
  init_errors();
83807
84037
  init_exitCode();
@@ -83955,7 +84185,7 @@ var PACKAGE_INVENTORY_FIELDS = [
83955
84185
  "candidate_fingerprint"
83956
84186
  ];
83957
84187
  var COMPILER_ONLY_TAGS = new Set(["docs", "prose", "parent-index"]);
83958
- function isRecord17(value) {
84188
+ function isRecord18(value) {
83959
84189
  return value !== null && typeof value === "object" && !Array.isArray(value);
83960
84190
  }
83961
84191
  function stringList2(value) {
@@ -83969,7 +84199,7 @@ function parseKnowledgeFrontmatter(content3) {
83969
84199
  return {};
83970
84200
  try {
83971
84201
  const parsed = import_yaml25.parse(match[1]);
83972
- return isRecord17(parsed) ? parsed : {};
84202
+ return isRecord18(parsed) ? parsed : {};
83973
84203
  } catch {
83974
84204
  return {};
83975
84205
  }
@@ -84064,13 +84294,13 @@ function packageKind(pkg) {
84064
84294
  return pkg.kind === "package.kb" ? "kb" : "llms";
84065
84295
  }
84066
84296
  async function walkFiles3(root2) {
84067
- if (!existsSync30(root2))
84297
+ if (!existsSync31(root2))
84068
84298
  return [];
84069
84299
  const files = [];
84070
84300
  const visit3 = async (dir) => {
84071
84301
  const entries = await readdir13(dir, { withFileTypes: true });
84072
84302
  for (const entry of entries) {
84073
- const absPath = join45(dir, entry.name);
84303
+ const absPath = join46(dir, entry.name);
84074
84304
  if (entry.isDirectory()) {
84075
84305
  await visit3(absPath);
84076
84306
  continue;
@@ -84362,10 +84592,10 @@ async function writeKnowledgeDirectoryIndexes(input) {
84362
84592
  let written = 0;
84363
84593
  for (const directory of collectKnowledgeDirectoryIndexes(input.pkg, input.selected)) {
84364
84594
  assertSafeRenderedPath(directory.relPath, "knowledge directory index path");
84365
- const outputPath = join45(input.projectRoot, input.pkg.outDir, directory.relPath);
84366
- if (existsSync30(outputPath))
84595
+ const outputPath = join46(input.projectRoot, input.pkg.outDir, directory.relPath);
84596
+ if (existsSync31(outputPath))
84367
84597
  continue;
84368
- await mkdir24(dirname28(outputPath), { recursive: true });
84598
+ await mkdir24(dirname29(outputPath), { recursive: true });
84369
84599
  await writeFile19(outputPath, renderKnowledgeDirectoryIndex({
84370
84600
  pkg: input.pkg,
84371
84601
  directory,
@@ -84411,23 +84641,23 @@ function packageLinkTargetExists(packageRoot, targetRelPath) {
84411
84641
  return false;
84412
84642
  }
84413
84643
  const normalized = targetRelPath.endsWith("/") ? `${targetRelPath}index.md` : targetRelPath;
84414
- const targetPath = join45(packageRoot, normalized);
84415
- if (existsSync30(targetPath)) {
84644
+ const targetPath = join46(packageRoot, normalized);
84645
+ if (existsSync31(targetPath)) {
84416
84646
  const stat6 = statSync(targetPath);
84417
84647
  if (stat6.isFile())
84418
84648
  return true;
84419
84649
  if (stat6.isDirectory())
84420
- return existsSync30(join45(targetPath, "index.md"));
84650
+ return existsSync31(join46(targetPath, "index.md"));
84421
84651
  return false;
84422
84652
  }
84423
- if (!pathPosix.extname(normalized) && existsSync30(join45(packageRoot, normalized, "index.md")))
84653
+ if (!pathPosix.extname(normalized) && existsSync31(join46(packageRoot, normalized, "index.md")))
84424
84654
  return true;
84425
84655
  return false;
84426
84656
  }
84427
84657
  async function validatePackageIndexLinks(input) {
84428
84658
  if (packageKind(input.pkg) !== "kb")
84429
84659
  return;
84430
- const packageRoot = join45(input.projectRoot, input.pkg.outDir);
84660
+ const packageRoot = join46(input.projectRoot, input.pkg.outDir);
84431
84661
  const files = await walkFiles3(packageRoot);
84432
84662
  for (const file of files) {
84433
84663
  if (file.relPath !== "index.md" && !file.relPath.endsWith("/index.md"))
@@ -84498,10 +84728,10 @@ function packageKind2(pkg) {
84498
84728
  // src/project/packageBuildInventory.ts
84499
84729
  var PACKAGE_BUILD_INVENTORY_PATH = "context-build-inventory.json";
84500
84730
  function knowledgeStructurePath(projectRoot) {
84501
- return join46(projectRoot, "knowledge", "structure.yaml");
84731
+ return join47(projectRoot, "knowledge", "structure.yaml");
84502
84732
  }
84503
84733
  async function readOptionalText(path4) {
84504
- if (!existsSync31(path4))
84734
+ if (!existsSync32(path4))
84505
84735
  return null;
84506
84736
  return readFile37(path4, "utf8");
84507
84737
  }
@@ -84880,8 +85110,8 @@ function packageBuildInventory(input) {
84880
85110
  };
84881
85111
  }
84882
85112
  async function writePackageBuildInventory(input) {
84883
- const outputPath = join46(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
84884
- await mkdir25(dirname29(outputPath), { recursive: true });
85113
+ const outputPath = join47(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
85114
+ await mkdir25(dirname30(outputPath), { recursive: true });
84885
85115
  await writeFile20(outputPath, `${JSON.stringify(input.inventory, null, 2)}
84886
85116
  `, "utf8");
84887
85117
  return 1;
@@ -84889,12 +85119,12 @@ async function writePackageBuildInventory(input) {
84889
85119
 
84890
85120
  // src/project/packageBuildReceipt.ts
84891
85121
  import { createHash as createHash18 } from "node:crypto";
84892
- import { existsSync as existsSync32 } from "node:fs";
85122
+ import { existsSync as existsSync33 } from "node:fs";
84893
85123
  import { readdir as readdir14, readFile as readFile38 } from "node:fs/promises";
84894
- import { join as join47, relative as relative17 } from "node:path";
85124
+ import { join as join48, relative as relative17 } from "node:path";
84895
85125
  var IGNORED_PACKAGE_FS_ENTRIES = new Set([".DS_Store"]);
84896
85126
  async function walkPackageFiles(root2) {
84897
- if (!existsSync32(root2))
85127
+ if (!existsSync33(root2))
84898
85128
  return [];
84899
85129
  const files = [];
84900
85130
  const visit3 = async (dir) => {
@@ -84902,7 +85132,7 @@ async function walkPackageFiles(root2) {
84902
85132
  for (const entry of entries) {
84903
85133
  if (IGNORED_PACKAGE_FS_ENTRIES.has(entry.name))
84904
85134
  continue;
84905
- const absPath = join47(dir, entry.name);
85135
+ const absPath = join48(dir, entry.name);
84906
85136
  if (entry.isDirectory()) {
84907
85137
  await visit3(absPath);
84908
85138
  continue;
@@ -84933,7 +85163,7 @@ function classifyOutputFile(path4, knowledgeGroups) {
84933
85163
  }
84934
85164
  async function packageOutputSnapshot(projectRoot, pkg, knowledgeGroups, previousOutputs = []) {
84935
85165
  const previousByPath = new Map(previousOutputs.map((file) => [file.path, file]));
84936
- return Promise.all((await walkPackageFiles(join47(projectRoot, pkg.outDir))).map(async (file) => {
85166
+ return Promise.all((await walkPackageFiles(join48(projectRoot, pkg.outDir))).map(async (file) => {
84937
85167
  const current2 = classifyOutputFile(file.relPath, knowledgeGroups);
84938
85168
  const previous3 = previousByPath.get(file.relPath);
84939
85169
  const classification = current2.kind === "file" && previous3 !== undefined ? { path: file.relPath, kind: previous3.kind, ...previous3.group === undefined ? {} : { group: previous3.group } } : current2;
@@ -84947,7 +85177,7 @@ async function packageOutputFingerprint(projectRoot, pkg) {
84947
85177
  const snapshot = await packageOutputSnapshot(projectRoot, pkg, new Map);
84948
85178
  return {
84949
85179
  fingerprint: createHash18("sha256").update(JSON.stringify({
84950
- outDirExists: existsSync32(join47(projectRoot, pkg.outDir)),
85180
+ outDirExists: existsSync33(join48(projectRoot, pkg.outDir)),
84951
85181
  files: snapshot.map(({ path: path4, sha256: sha2564 }) => ({ path: path4, sha256: sha2564 }))
84952
85182
  })).digest("hex"),
84953
85183
  files: snapshot.length
@@ -85021,16 +85251,16 @@ function formatPackageBuildSummary(pkg) {
85021
85251
  }
85022
85252
 
85023
85253
  // src/project/packageBuildContent.ts
85024
- import { existsSync as existsSync33 } from "node:fs";
85254
+ import { existsSync as existsSync34 } from "node:fs";
85025
85255
  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";
85256
+ import { dirname as dirname33, join as join51 } from "node:path";
85027
85257
 
85028
85258
  // src/project/packageAssets.ts
85029
85259
  init_errors();
85030
85260
  init_cliFeedback();
85031
85261
  init_exitCode();
85032
85262
  import { readFile as readFile39 } from "node:fs/promises";
85033
- import { dirname as dirname30, relative as relative18, sep as sep3 } from "node:path";
85263
+ import { dirname as dirname31, relative as relative18, sep as sep3 } from "node:path";
85034
85264
  function posixPath2(value) {
85035
85265
  return value.split(sep3).join("/");
85036
85266
  }
@@ -85052,7 +85282,7 @@ function packageAssetPath(projectRoot, absolute) {
85052
85282
  };
85053
85283
  }
85054
85284
  function packageMarkdownTarget(pageOutputPath, assetOutputPath) {
85055
- const target = posixPath2(relative18(dirname30(pageOutputPath), assetOutputPath));
85285
+ const target = posixPath2(relative18(dirname31(pageOutputPath), assetOutputPath));
85056
85286
  return target.startsWith(".") ? target : `./${target}`;
85057
85287
  }
85058
85288
  async function projectPackageKnowledgeAssets(input) {
@@ -85092,7 +85322,7 @@ init_errors();
85092
85322
  init_exitCode();
85093
85323
  import { execFile as execFile5 } from "node:child_process";
85094
85324
  import { realpath as realpath3 } from "node:fs/promises";
85095
- import { join as join49, relative as relative19, sep as sep4 } from "node:path";
85325
+ import { join as join50, relative as relative19, sep as sep4 } from "node:path";
85096
85326
  import { promisify as promisify5 } from "node:util";
85097
85327
 
85098
85328
  // src/project/packageAssetOptimization.ts
@@ -85101,7 +85331,7 @@ init_errors();
85101
85331
  init_exitCode();
85102
85332
  import { createHash as createHash19 } from "node:crypto";
85103
85333
  import { createRequire as createRequire4 } from "node:module";
85104
- import { dirname as dirname31, extname as extname10, join as join48 } from "node:path";
85334
+ import { dirname as dirname32, extname as extname10, join as join49 } from "node:path";
85105
85335
  import { pathToFileURL as pathToFileURL2 } from "node:url";
85106
85336
  var PACKAGE_ASSET_OPTIMIZATION_THRESHOLD_BYTES = 20 * 1024 * 1024;
85107
85337
  function isPng(bytes) {
@@ -85123,10 +85353,10 @@ function isWebp(bytes) {
85123
85353
  }
85124
85354
  function contentAddressedWebpPath(asset, bytes) {
85125
85355
  const digest4 = createHash19("sha256").update(bytes).digest("hex");
85126
- return `${dirname31(asset.packageRelPath)}/${digest4}.webp`;
85356
+ return `${dirname32(asset.packageRelPath)}/${digest4}.webp`;
85127
85357
  }
85128
85358
  async function loadSharpProcessor(projectRoot) {
85129
- const requireFromWorkspace = createRequire4(join48(projectRoot, "package.json"));
85359
+ const requireFromWorkspace = createRequire4(join49(projectRoot, "package.json"));
85130
85360
  let resolved;
85131
85361
  try {
85132
85362
  resolved = requireFromWorkspace.resolve("sharp");
@@ -85246,7 +85476,7 @@ async function git(projectRoot, args) {
85246
85476
  }
85247
85477
  }
85248
85478
  function repositoryPath(repoRoot, projectRoot, asset) {
85249
- const path4 = relative19(repoRoot, join49(projectRoot, asset.knowledgeRelPath)).split(sep4).join("/");
85479
+ const path4 = relative19(repoRoot, join50(projectRoot, asset.knowledgeRelPath)).split(sep4).join("/");
85250
85480
  if (path4 === ".." || path4.startsWith("../") || path4.startsWith("/")) {
85251
85481
  throw new ContextError(ExitCode.WorkspaceStateError, "knowledge asset is outside the current Git repository", {
85252
85482
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -85553,8 +85783,8 @@ async function writeRenderedPackageTemplate(input) {
85553
85783
  templateRelPath: renderedRelPath,
85554
85784
  logicalTemplateRelPath: renderedLogicalRelPath
85555
85785
  });
85556
- const outputPath = join50(input.projectRoot, input.pkg.outDir, renderedRelPath);
85557
- await mkdir26(dirname32(outputPath), { recursive: true });
85786
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, renderedRelPath);
85787
+ await mkdir26(dirname33(outputPath), { recursive: true });
85558
85788
  await writeFile21(outputPath, renderTemplateText(file.content, contentVars), "utf8");
85559
85789
  written++;
85560
85790
  }
@@ -85580,7 +85810,7 @@ async function writeSelectedPackageKnowledge(input) {
85580
85810
  const { projectedPages, delivered } = input.prepared ?? await prepareSelectedPackageKnowledge(input);
85581
85811
  for (const projected of projectedPages) {
85582
85812
  assertSafeRenderedPath2(projected.pageOutputPath, "knowledge path");
85583
- const outputPath = join50(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
85813
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
85584
85814
  const rewritten = replaceMarkdownInlineLinkTargets(projected.content, (link2) => {
85585
85815
  for (const [inputPath, outputPath2] of delivered.targetByOriginal) {
85586
85816
  if (link2.target === packageMarkdownTarget(projected.pageOutputPath, inputPath)) {
@@ -85589,14 +85819,14 @@ async function writeSelectedPackageKnowledge(input) {
85589
85819
  }
85590
85820
  return;
85591
85821
  });
85592
- await mkdir26(dirname32(outputPath), { recursive: true });
85822
+ await mkdir26(dirname33(outputPath), { recursive: true });
85593
85823
  await writeFile21(outputPath, projectPackageKnowledgeMarkdown(rewritten), "utf8");
85594
85824
  }
85595
85825
  const deliveredAssets = new Map(delivered.assets.map((asset) => [asset.packageRelPath, asset]));
85596
85826
  for (const asset of deliveredAssets.values()) {
85597
85827
  assertSafeRenderedPath2(asset.packageRelPath, "package resource path");
85598
- const outputPath = join50(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
85599
- await mkdir26(dirname32(outputPath), { recursive: true });
85828
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
85829
+ await mkdir26(dirname33(outputPath), { recursive: true });
85600
85830
  await writeFile21(outputPath, asset.bytes);
85601
85831
  }
85602
85832
  return {
@@ -85609,8 +85839,8 @@ async function writeSelectedPackageKnowledge(input) {
85609
85839
  async function appendLlmsKnowledge(input) {
85610
85840
  if (packageKind2(input.pkg) !== "llms" || input.templateConsumesKnowledge || input.knowledgeCount === 0)
85611
85841
  return 0;
85612
- const outputPath = join50(input.projectRoot, input.pkg.outDir, "llms.txt");
85613
- const existed = existsSync33(outputPath);
85842
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, "llms.txt");
85843
+ const existed = existsSync34(outputPath);
85614
85844
  const existing = existed ? await readFile40(outputPath, "utf8") : "";
85615
85845
  const content3 = existing.trim().length > 0 ? `${existing.trimEnd()}
85616
85846
 
@@ -85619,7 +85849,7 @@ async function appendLlmsKnowledge(input) {
85619
85849
  ${input.bundle}
85620
85850
  ` : `${input.bundle}
85621
85851
  `;
85622
- await mkdir26(dirname32(outputPath), { recursive: true });
85852
+ await mkdir26(dirname33(outputPath), { recursive: true });
85623
85853
  await writeFile21(outputPath, content3, "utf8");
85624
85854
  return existed ? 0 : 1;
85625
85855
  }
@@ -85805,7 +86035,7 @@ function validateRenderedSkillDefinition(input) {
85805
86035
  init_workspace();
85806
86036
  init_packageTemplateReview();
85807
86037
  var KNOWLEDGE_ROOT4 = "knowledge";
85808
- var PACKAGE_FINGERPRINT_ROOT = join51(".tmp", "context-runtime", "packages");
86038
+ var PACKAGE_FINGERPRINT_ROOT = join52(".tmp", "context-runtime", "packages");
85809
86039
  var PACKAGE_BUILDER_PROTOCOL_VERSION = "v14-git-asset-identity";
85810
86040
  function packageAssetDeliverySummary(value) {
85811
86041
  if (value === null || typeof value !== "object" || Array.isArray(value))
@@ -85828,10 +86058,10 @@ function assertPackageOutputDir(pkg) {
85828
86058
  }
85829
86059
  function packageFingerprintPath(projectRoot, pkg) {
85830
86060
  assertSafeRenderedPath2(`${pkg.name}.json`, "package fingerprint path");
85831
- return join51(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
86061
+ return join52(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
85832
86062
  }
85833
86063
  async function listApprovedKnowledge(projectRoot) {
85834
- const files = await walkPackageFiles(join51(projectRoot, KNOWLEDGE_ROOT4));
86064
+ const files = await walkPackageFiles(join52(projectRoot, KNOWLEDGE_ROOT4));
85835
86065
  const knowledge = await Promise.all(files.filter((file) => file.relPath.endsWith(".md") && !file.relPath.startsWith("assets/")).map(async (file) => ({
85836
86066
  ...file,
85837
86067
  content: await readFile41(file.absPath, "utf8")
@@ -85852,7 +86082,7 @@ function isDeprecatedKnowledge(content3) {
85852
86082
  async function listTemplateFiles(projectRoot, templatePath) {
85853
86083
  assertSafeRenderedPath2(templatePath, "package template path");
85854
86084
  const templateRoot = resolve19(projectRoot, templatePath);
85855
- if (!existsSync34(templateRoot)) {
86085
+ if (!existsSync35(templateRoot)) {
85856
86086
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${templatePath}`, {
85857
86087
  category: ErrorCategory.WorkspaceStateInvalid,
85858
86088
  path: templatePath,
@@ -85914,7 +86144,7 @@ async function packageInputFingerprint(input) {
85914
86144
  }
85915
86145
  async function readPackageManifest(projectRoot, pkg) {
85916
86146
  const filePath = packageFingerprintPath(projectRoot, pkg);
85917
- if (!existsSync34(filePath))
86147
+ if (!existsSync35(filePath))
85918
86148
  return null;
85919
86149
  try {
85920
86150
  const parsed = JSON.parse(await readFile41(filePath, "utf8"));
@@ -85947,7 +86177,7 @@ async function readPackageManifest(projectRoot, pkg) {
85947
86177
  }
85948
86178
  async function writePackageFingerprint(input) {
85949
86179
  const filePath = packageFingerprintPath(input.projectRoot, input.pkg);
85950
- await mkdir27(dirname33(filePath), { recursive: true });
86180
+ await mkdir27(dirname34(filePath), { recursive: true });
85951
86181
  await writeFile22(filePath, `${JSON.stringify({
85952
86182
  package: input.pkg.name,
85953
86183
  kind: packageKind2(input.pkg),
@@ -85962,12 +86192,12 @@ async function writePackageFingerprint(input) {
85962
86192
  `, "utf8");
85963
86193
  }
85964
86194
  async function removeOrphanPackageDirs(projectRoot, packages) {
85965
- const distRoot = join51(projectRoot, "dist");
85966
- if (!existsSync34(distRoot))
86195
+ const distRoot = join52(projectRoot, "dist");
86196
+ if (!existsSync35(distRoot))
85967
86197
  return;
85968
86198
  const declaredNames = new Set(packages.map((pkg) => pkg.name));
85969
86199
  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 })));
86200
+ 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
86201
  }
85972
86202
  async function collectPackageFreshness(projectRoot, packages) {
85973
86203
  const approved = await listApprovedKnowledge(projectRoot);
@@ -85975,8 +86205,8 @@ async function collectPackageFreshness(projectRoot, packages) {
85975
86205
  assertPackageOutputDir(pkg);
85976
86206
  const selected = selectPackageKnowledge(approved, pkg);
85977
86207
  assertSafeRenderedPath2(pkg.template.path, "package template path");
85978
- const templateRoot = join51(projectRoot, pkg.template.path);
85979
- const templateExists = existsSync34(templateRoot);
86208
+ const templateRoot = join52(projectRoot, pkg.template.path);
86209
+ const templateExists = existsSync35(templateRoot);
85980
86210
  if (!templateExists) {
85981
86211
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${pkg.template.path}`, {
85982
86212
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -86110,8 +86340,8 @@ async function buildProjectPackages(projectRoot) {
86110
86340
  files: selected,
86111
86341
  ...assetProcessor === undefined ? {} : { assetProcessor }
86112
86342
  });
86113
- await rm13(join51(projectRoot, pkg.outDir), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
86114
- await mkdir27(join51(projectRoot, pkg.outDir), { recursive: true });
86343
+ await rm13(join52(projectRoot, pkg.outDir), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
86344
+ await mkdir27(join52(projectRoot, pkg.outDir), { recursive: true });
86115
86345
  const rendered = await writeRenderedPackageTemplate({
86116
86346
  projectRoot,
86117
86347
  pkg,
@@ -86249,20 +86479,32 @@ async function runProjectBuildCommand(input) {
86249
86479
  return false;
86250
86480
  const result = await buildProjectPackages(found.projectRoot);
86251
86481
  process.stdout.write(formatProjectBuildResult(result, input.format ?? "text", input.verbose === true));
86482
+ queueContextRuntimeEvent({
86483
+ cwd: result.projectRoot,
86484
+ kind: "package.build.completed",
86485
+ properties: {
86486
+ package_count: result.packages.length,
86487
+ created_count: result.packages.filter((pkg) => pkg.state === "created").length,
86488
+ updated_count: result.packages.filter((pkg) => pkg.state === "updated").length,
86489
+ unchanged_count: result.packages.filter((pkg) => pkg.state === "unchanged").length,
86490
+ output_file_count: result.packages.reduce((total, pkg) => total + pkg.files, 0),
86491
+ resource_file_count: result.packages.reduce((total, pkg) => total + pkg.resources.files, 0)
86492
+ }
86493
+ });
86252
86494
  return true;
86253
86495
  }
86254
86496
 
86255
86497
  // src/project/statusReaders.ts
86256
86498
  init_workspace();
86257
86499
  async function countFiles(root2, predicate) {
86258
- if (!existsSync35(root2))
86500
+ if (!existsSync36(root2))
86259
86501
  return 0;
86260
86502
  let count = 0;
86261
86503
  const visit3 = async (dir, prefix = "") => {
86262
86504
  const entries = await readdir16(dir, { withFileTypes: true });
86263
86505
  for (const entry of entries) {
86264
86506
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
86265
- const abs = join52(dir, entry.name);
86507
+ const abs = join53(dir, entry.name);
86266
86508
  if (entry.isDirectory())
86267
86509
  await visit3(abs, rel);
86268
86510
  else if (entry.isFile() && predicate(rel))
@@ -86304,14 +86546,14 @@ async function readDraftCandidateStatus(projectRoot) {
86304
86546
  throw error;
86305
86547
  }
86306
86548
  }
86307
- function isRecord18(value) {
86549
+ function isRecord19(value) {
86308
86550
  return value !== null && typeof value === "object" && !Array.isArray(value);
86309
86551
  }
86310
86552
  function stagedStructureCounts(parsed) {
86311
86553
  const views = Array.isArray(parsed.views) ? parsed.views : [];
86312
- const sections = views.flatMap((view) => isRecord18(view) && Array.isArray(view.sections) ? view.sections : []);
86554
+ const sections = views.flatMap((view) => isRecord19(view) && Array.isArray(view.sections) ? view.sections : []);
86313
86555
  const sourceRefs = new Set(sections.flatMap((section) => {
86314
- if (!isRecord18(section))
86556
+ if (!isRecord19(section))
86315
86557
  return [];
86316
86558
  return [
86317
86559
  ...typeof section.source_ref === "string" ? [section.source_ref] : [],
@@ -86328,12 +86570,12 @@ function stagedStructureCounts(parsed) {
86328
86570
  };
86329
86571
  }
86330
86572
  function readStructureDraftStatus(projectRoot) {
86331
- const structurePath = join52(projectRoot, LIFECYCLE_STRUCTURE_FILE);
86332
- if (!existsSync35(structurePath))
86573
+ const structurePath = join53(projectRoot, LIFECYCLE_STRUCTURE_FILE);
86574
+ if (!existsSync36(structurePath))
86333
86575
  return { state: "missing", sourceKeys: [], collections: [], diagnostics: [] };
86334
86576
  try {
86335
- const parsed = import_yaml29.default.parse(readFileSync7(structurePath, "utf8"));
86336
- if (!isRecord18(parsed)) {
86577
+ const parsed = import_yaml29.default.parse(readFileSync8(structurePath, "utf8"));
86578
+ if (!isRecord19(parsed)) {
86337
86579
  return {
86338
86580
  state: "invalid",
86339
86581
  sourceKeys: [],
@@ -86341,7 +86583,7 @@ function readStructureDraftStatus(projectRoot) {
86341
86583
  diagnostics: [`${LIFECYCLE_STRUCTURE_FILE} must be a YAML object`]
86342
86584
  };
86343
86585
  }
86344
- const lifecycle = isRecord18(parsed.lifecycle) ? parsed.lifecycle : {};
86586
+ const lifecycle = isRecord19(parsed.lifecycle) ? parsed.lifecycle : {};
86345
86587
  const lifecycleState = lifecycle.state;
86346
86588
  if (lifecycleState === "draft" || lifecycleState === "confirmed" || lifecycleState === "frozen") {
86347
86589
  const structureDigest = typeof parsed.structure_digest === "string" ? parsed.structure_digest : typeof lifecycle.structure_digest === "string" ? lifecycle.structure_digest : undefined;
@@ -86351,7 +86593,7 @@ function readStructureDraftStatus(projectRoot) {
86351
86593
  lifecycleState,
86352
86594
  ...typeof lifecycle.phase_collection === "string" ? { phaseCollection: lifecycle.phase_collection } : {},
86353
86595
  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() : [],
86596
+ collections: Array.isArray(parsed.views) ? [...new Set(parsed.views.flatMap((view) => isRecord19(view) && typeof view.collection === "string" ? [view.collection] : []))].sort() : [],
86355
86597
  ...structureDigest === undefined ? {} : { structureDigest },
86356
86598
  ...evidenceSnapshotHash === undefined ? {} : { evidenceSnapshotHash },
86357
86599
  ...stagedStructureCounts(parsed),
@@ -86528,8 +86770,8 @@ async function documentSourceSiteHint(input) {
86528
86770
  });
86529
86771
  }
86530
86772
  function documentSnapshotReadiness(input) {
86531
- const manifestPath = join52(input.projectRoot, input.manifest);
86532
- if (!existsSync35(manifestPath)) {
86773
+ const manifestPath = join53(input.projectRoot, input.manifest);
86774
+ if (!existsSync36(manifestPath)) {
86533
86775
  return {
86534
86776
  ready: false,
86535
86777
  diagnostics: [`snapshot is missing: ${input.manifest}`],
@@ -86537,7 +86779,7 @@ function documentSnapshotReadiness(input) {
86537
86779
  };
86538
86780
  }
86539
86781
  try {
86540
- const manifest = findDocumentSnapshotForSource(JSON.parse(readFileSync7(manifestPath, "utf8")), input.sourceName);
86782
+ const manifest = findDocumentSnapshotForSource(JSON.parse(readFileSync8(manifestPath, "utf8")), input.sourceName);
86541
86783
  if (manifest === null) {
86542
86784
  return {
86543
86785
  ready: false,
@@ -86598,7 +86840,7 @@ function documentSnapshotReadiness(input) {
86598
86840
  const missingFiles = [
86599
86841
  ...manifest.files.map((file) => file.path),
86600
86842
  ...(manifest.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
86601
- ].filter((path4) => !existsSync35(join52(input.projectRoot, input.materializedAt, path4)));
86843
+ ].filter((path4) => !existsSync36(join53(input.projectRoot, input.materializedAt, path4)));
86602
86844
  if (missingFiles.length > 0) {
86603
86845
  return {
86604
86846
  ready: false,
@@ -86845,9 +87087,9 @@ async function readActiveStructuresStatus(projectRoot, currentSnapshotHashes) {
86845
87087
  init_packageTemplateReview();
86846
87088
 
86847
87089
  // 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";
87090
+ import { existsSync as existsSync37 } from "node:fs";
87091
+ import { dirname as dirname35, resolve as resolve20 } from "node:path";
87092
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
86851
87093
 
86852
87094
  // src/project/workflow/verifyFacts.ts
86853
87095
  var CLOSE_REPAIRABLE_APPROVED_STRUCTURE_CODES = new Set([
@@ -87419,7 +87661,7 @@ function planForResolvedCommandPlan(commandPlan, observation) {
87419
87661
 
87420
87662
  // src/project/workflow/workflowEvidenceResources.ts
87421
87663
  import { createHash as createHash21 } from "node:crypto";
87422
- import { join as join53 } from "node:path";
87664
+ import { join as join54 } from "node:path";
87423
87665
  function sourceKeysForRoute(node3, observation) {
87424
87666
  if (node3 === "classify-document") {
87425
87667
  return observation.unclassifiedDocumentTargets.map((target) => target.sourceKey);
@@ -87471,7 +87713,7 @@ async function currentSourceBodyResources(input) {
87471
87713
  kind: "context-view",
87472
87714
  media_type: "text/markdown",
87473
87715
  digest: document4.content_hash,
87474
- path: join53(input.observation.projectRoot, source2.materializedAt, document4.path),
87716
+ path: join54(input.observation.projectRoot, source2.materializedAt, document4.path),
87475
87717
  read_state: isCurrent(id2, document4.content_hash, input.receipts) ? "current" : "read-required"
87476
87718
  });
87477
87719
  }
@@ -87483,7 +87725,7 @@ async function currentSourceBodyResources(input) {
87483
87725
  // src/project/workflow/workflowProvider.ts
87484
87726
  var providerPromise;
87485
87727
  function providerCandidates() {
87486
- const moduleDir2 = dirname34(fileURLToPath6(import.meta.url));
87728
+ const moduleDir2 = dirname35(fileURLToPath7(import.meta.url));
87487
87729
  return [
87488
87730
  ...process.env.C4A_CONTEXT_WORKFLOW_PROVIDER ? [resolve20(process.env.C4A_CONTEXT_WORKFLOW_PROVIDER)] : [],
87489
87731
  resolve20(moduleDir2, "providers", "context", "manifest.json"),
@@ -87491,7 +87733,7 @@ function providerCandidates() {
87491
87733
  ];
87492
87734
  }
87493
87735
  function contextWorkflowProviderPath() {
87494
- const candidate = providerCandidates().find((path4) => existsSync36(path4));
87736
+ const candidate = providerCandidates().find((path4) => existsSync37(path4));
87495
87737
  if (candidate === undefined) {
87496
87738
  throw new Error("Context workflow Provider is missing. Rebuild @c4a/context-cli or reinstall the published package.");
87497
87739
  }
@@ -88505,13 +88747,13 @@ async function collectProjectStatusSnapshot(projectRoot, options = {}) {
88505
88747
  requestedCollections: [...new Set(alignTargets.map((target) => target.collection))],
88506
88748
  requestedGroups: alignGroups
88507
88749
  });
88508
- const approvedPages = await countFiles(join54(projectRoot, "knowledge"), (rel) => rel.endsWith(".md") && !rel.startsWith("assets/"));
88750
+ const approvedPages = await countFiles(join55(projectRoot, "knowledge"), (rel) => rel.endsWith(".md") && !rel.startsWith("assets/"));
88509
88751
  const approvedCollections = (await Promise.all(KNOWLEDGE_COLLECTIONS.map(async (collection) => ({
88510
88752
  collection,
88511
- count: await countFiles(join54(projectRoot, "knowledge", collection), (rel) => rel.endsWith(".md"))
88753
+ count: await countFiles(join55(projectRoot, "knowledge", collection), (rel) => rel.endsWith(".md"))
88512
88754
  })))).filter((item) => item.count > 0).map((item) => item.collection);
88513
88755
  const closeStatus = await readCloseStatus(projectRoot);
88514
- const distFiles = await countFiles(join54(projectRoot, "dist"), () => true);
88756
+ const distFiles = await countFiles(join55(projectRoot, "dist"), () => true);
88515
88757
  const sourceFreshness = phaseStatus.projectEntryValid ? await collectSourceFreshness({
88516
88758
  projectRoot,
88517
88759
  phases,
@@ -88875,6 +89117,7 @@ async function runProjectStatusCommand(input) {
88875
89117
  } else {
88876
89118
  process.stdout.write(formatProjectStatus(status));
88877
89119
  }
89120
+ input.onSuccess?.(status);
88878
89121
  return true;
88879
89122
  }
88880
89123
  async function assertProjectWorkflowRevision(input) {
@@ -88931,11 +89174,11 @@ function shellQuote6(value) {
88931
89174
  }
88932
89175
  function receiptSetPath(receipts) {
88933
89176
  const token = digestText(JSON.stringify(receipts)).slice("sha256:".length);
88934
- return join55(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
89177
+ return join56(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
88935
89178
  }
88936
89179
  async function writeReceiptContinuation(input) {
88937
89180
  const path4 = receiptSetPath(input.receipts);
88938
- await writeJsonAtomic(join55(input.projectRoot, path4), input.receipts);
89181
+ await writeJsonAtomic(join56(input.projectRoot, path4), input.receipts);
88939
89182
  const command2 = input.managed ? [
88940
89183
  "context",
88941
89184
  "--workflow-resource-receipts",
@@ -88996,7 +89239,7 @@ async function materializeContextWorkflowResource(input) {
88996
89239
  }
88997
89240
  const content3 = renderContextWorkflowResource(resourceId2, status);
88998
89241
  const location = await materializeResource(await loadContextWorkflowProvider(), resourceId2, {
88999
- cache: join55(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
89242
+ cache: join56(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
89000
89243
  workspace: found.projectRoot,
89001
89244
  revision: input.revision,
89002
89245
  input: {
@@ -89222,7 +89465,7 @@ function registerContextWorkflowResourceCommands(program2) {
89222
89465
  }
89223
89466
 
89224
89467
  // src/commands/runProject.ts
89225
- import { fileURLToPath as fileURLToPath7 } from "node:url";
89468
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
89226
89469
  init_cliFeedback();
89227
89470
  init_errors();
89228
89471
 
@@ -89233,11 +89476,11 @@ init_exitCode();
89233
89476
 
89234
89477
  // src/project/documentCaptureLark.ts
89235
89478
  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";
89479
+ import { basename as basename8, extname as extname12, join as join59 } from "node:path";
89237
89480
 
89238
89481
  // src/lib/atomicFileBatch.ts
89239
89482
  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";
89483
+ import { dirname as dirname36, join as join57, resolve as resolve22 } from "node:path";
89241
89484
  async function existingFileKind(path4) {
89242
89485
  try {
89243
89486
  const stats = await lstat2(path4);
@@ -89267,9 +89510,9 @@ async function applyAtomicFileBatch(input) {
89267
89510
  for (const path4 of writesByPath.keys())
89268
89511
  removalPaths.delete(path4);
89269
89512
  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");
89513
+ const transactionDir = await mkdtemp(join57(input.transactionRoot, "batch-"));
89514
+ const stagedRoot = join57(transactionDir, "staged");
89515
+ const backupRoot = join57(transactionDir, "backup");
89273
89516
  const writes = [...writesByPath.values()].sort((left, right) => left.path.localeCompare(right.path));
89274
89517
  const affectedPaths = [...new Set([...writesByPath.keys(), ...removalPaths])].sort();
89275
89518
  const staged = new Map;
@@ -89279,20 +89522,20 @@ async function applyAtomicFileBatch(input) {
89279
89522
  try {
89280
89523
  await mkdir28(stagedRoot, { recursive: true });
89281
89524
  for (const [index2, write] of writes.entries()) {
89282
- const path4 = join56(stagedRoot, String(index2));
89525
+ const path4 = join57(stagedRoot, String(index2));
89283
89526
  await writeFile23(path4, write.bytes);
89284
89527
  staged.set(write.path, path4);
89285
89528
  }
89286
89529
  for (const [index2, path4] of affectedPaths.entries()) {
89287
89530
  if (await existingFileKind(path4) === "missing")
89288
89531
  continue;
89289
- const backupPath = join56(backupRoot, String(index2));
89290
- await mkdir28(dirname35(backupPath), { recursive: true });
89532
+ const backupPath = join57(backupRoot, String(index2));
89533
+ await mkdir28(dirname36(backupPath), { recursive: true });
89291
89534
  await rename4(path4, backupPath);
89292
89535
  backups.set(path4, backupPath);
89293
89536
  }
89294
89537
  for (const write of writes) {
89295
- await mkdir28(dirname35(write.path), { recursive: true });
89538
+ await mkdir28(dirname36(write.path), { recursive: true });
89296
89539
  await rename4(staged.get(write.path), write.path);
89297
89540
  installed.push(write.path);
89298
89541
  }
@@ -89304,7 +89547,7 @@ async function applyAtomicFileBatch(input) {
89304
89547
  });
89305
89548
  }
89306
89549
  for (const [path4, backupPath] of [...backups.entries()].reverse()) {
89307
- await mkdir28(dirname35(path4), { recursive: true });
89550
+ await mkdir28(dirname36(path4), { recursive: true });
89308
89551
  await rename4(backupPath, path4).catch((rollbackError) => {
89309
89552
  rollbackFailures.push(`restore ${path4}: ${String(rollbackError)}`);
89310
89553
  });
@@ -89341,7 +89584,7 @@ function detectExternalEnvironmentIssue(value) {
89341
89584
  }
89342
89585
 
89343
89586
  // src/lib/feishu.ts
89344
- import { spawn as spawn2 } from "node:child_process";
89587
+ import { spawn as spawn3 } from "node:child_process";
89345
89588
 
89346
89589
  // src/lib/larkDocxXml.ts
89347
89590
  import { createHash as createHash23 } from "node:crypto";
@@ -93626,7 +93869,7 @@ function projectLarkDocxXmlBlock(input) {
93626
93869
  // src/lib/larkResourceMaterialization.ts
93627
93870
  import { createHash as createHash24 } from "node:crypto";
93628
93871
  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";
93872
+ import { extname as extname11, join as join58 } from "node:path";
93630
93873
  import { tmpdir } from "node:os";
93631
93874
 
93632
93875
  // src/lib/larkResourceCommand.ts
@@ -93825,7 +94068,7 @@ function findBooleanField(value, name2) {
93825
94068
  return;
93826
94069
  }
93827
94070
  async function downloadedFile(input) {
93828
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-resource-"));
94071
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-resource-"));
93829
94072
  try {
93830
94073
  await runLarkResourceCommand(input.runner, [
93831
94074
  "docs",
@@ -93846,7 +94089,7 @@ async function downloadedFile(input) {
93846
94089
  if (entries.length !== 1)
93847
94090
  throw new Error(`media download produced ${entries.length} files, expected exactly one`);
93848
94091
  const path4 = entries[0]?.name ?? "resource.bin";
93849
- const bytes = await readFile43(join57(tempRoot, path4));
94092
+ const bytes = await readFile43(join58(tempRoot, path4));
93850
94093
  return { path: path4, bytes, mediaType: mediaTypeFor(path4, bytes) };
93851
94094
  } finally {
93852
94095
  await rm15(tempRoot, { recursive: true, force: true });
@@ -93937,9 +94180,9 @@ async function sheetMaterialization(resource, runner2) {
93937
94180
  const sheetId = resource.attributes["sheet-id"];
93938
94181
  if (token === undefined || sheetId === undefined)
93939
94182
  throw new Error("embedded Sheet requires token and sheet-id");
93940
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-sheet-"));
94183
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-sheet-"));
93941
94184
  try {
93942
- const outputPath = join57(tempRoot, "sheet.json");
94185
+ const outputPath = join58(tempRoot, "sheet.json");
93943
94186
  const stdout = await runLarkResourceCommand(runner2, [
93944
94187
  "sheets",
93945
94188
  "+csv-get",
@@ -94095,7 +94338,7 @@ async function whiteboardMaterialization(resource, runner2) {
94095
94338
  if (token === undefined)
94096
94339
  throw new Error(`${resource.kind} has no whiteboard token`);
94097
94340
  const preview = await downloadedFile({ runner: runner2, token, type: "whiteboard" });
94098
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-whiteboard-"));
94341
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-whiteboard-"));
94099
94342
  let rawPayload;
94100
94343
  try {
94101
94344
  await runLarkResourceCommand(runner2, [
@@ -94113,7 +94356,7 @@ async function whiteboardMaterialization(resource, runner2) {
94113
94356
  "--format",
94114
94357
  "json"
94115
94358
  ], { cwd: tempRoot });
94116
- rawPayload = JSON.parse(await readFile43(join57(tempRoot, "raw.json"), "utf8"));
94359
+ rawPayload = JSON.parse(await readFile43(join58(tempRoot, "raw.json"), "utf8"));
94117
94360
  } finally {
94118
94361
  await rm15(tempRoot, { recursive: true, force: true });
94119
94362
  }
@@ -94386,7 +94629,7 @@ class LarkCliError extends Error {
94386
94629
  }
94387
94630
  }
94388
94631
  var defaultRunner = (args, options) => new Promise((resolve8, reject) => {
94389
- const child = spawn2(LARK_BIN, args, {
94632
+ const child = spawn3(LARK_BIN, args, {
94390
94633
  ...options?.cwd === undefined ? {} : { cwd: options.cwd },
94391
94634
  stdio: ["ignore", "pipe", "pipe"]
94392
94635
  });
@@ -94793,7 +95036,7 @@ async function fileContentMatches(path4, content3) {
94793
95036
  }
94794
95037
  }
94795
95038
  function sourceManifestPath2(entry) {
94796
- return entry.snapshot?.manifest ?? join58(entry.materializedAt, "manifest.json");
95039
+ return entry.snapshot?.manifest ?? join59(entry.materializedAt, "manifest.json");
94797
95040
  }
94798
95041
  function larkRuntimeError(message, detail) {
94799
95042
  return new ContextError(ExitCode.ExternalToolError, message, {
@@ -94919,7 +95162,7 @@ function assetManifestEntry(asset, assetRoot) {
94919
95162
  };
94920
95163
  }
94921
95164
  async function listSnapshotAssetFiles(root2, assetRoot) {
94922
- const assetsRoot = join58(root2, assetRoot);
95165
+ const assetsRoot = join59(root2, assetRoot);
94923
95166
  const files = [];
94924
95167
  const visit3 = async (dir, prefix = assetRoot) => {
94925
95168
  let entries;
@@ -94932,7 +95175,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
94932
95175
  }
94933
95176
  for (const entry of entries) {
94934
95177
  const relPath = `${prefix}/${entry.name}`;
94935
- const absolutePath = join58(dir, entry.name);
95178
+ const absolutePath = join59(dir, entry.name);
94936
95179
  if (entry.isDirectory()) {
94937
95180
  await visit3(absolutePath, relPath);
94938
95181
  continue;
@@ -94947,7 +95190,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
94947
95190
  }
94948
95191
  async function staleSnapshotAssetPaths(input) {
94949
95192
  const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
94950
- return existingPaths.filter((path4) => !input.currentPaths.has(path4)).map((path4) => join58(input.materializedAtAbsPath, path4));
95193
+ return existingPaths.filter((path4) => !input.currentPaths.has(path4)).map((path4) => join59(input.materializedAtAbsPath, path4));
94951
95194
  }
94952
95195
  function normalizeLarkError(error, sourceName) {
94953
95196
  if (error instanceof ContextError)
@@ -95021,9 +95264,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
95021
95264
  locator
95022
95265
  }];
95023
95266
  const manifestPath = sourceManifestPath2(entry);
95024
- const manifestAbsPath = join58(input.projectRoot, manifestPath);
95267
+ const manifestAbsPath = join59(input.projectRoot, manifestPath);
95025
95268
  const materializedAt = entry.materializedAt;
95026
- const materializedAtAbsPath = join58(input.projectRoot, materializedAt);
95269
+ const materializedAtAbsPath = join59(input.projectRoot, materializedAt);
95027
95270
  const manifest = createDocumentSnapshotManifest({
95028
95271
  sourceType: "lark",
95029
95272
  sourceName: resolved.sourceName,
@@ -95053,13 +95296,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
95053
95296
  }));
95054
95297
  try {
95055
95298
  const requestedWrites = [{
95056
- path: join58(materializedAtAbsPath, documentPath),
95299
+ path: join59(materializedAtAbsPath, documentPath),
95057
95300
  bytes: normalized
95058
95301
  }];
95059
95302
  for (const asset of assets) {
95060
95303
  if (asset.bytes !== undefined) {
95061
95304
  requestedWrites.push({
95062
- path: join58(materializedAtAbsPath, asset.entry.path),
95305
+ path: join59(materializedAtAbsPath, asset.entry.path),
95063
95306
  bytes: asset.bytes
95064
95307
  });
95065
95308
  }
@@ -95076,7 +95319,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
95076
95319
  currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
95077
95320
  });
95078
95321
  await applyAtomicFileBatch({
95079
- transactionRoot: join58(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
95322
+ transactionRoot: join59(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
95080
95323
  writes,
95081
95324
  removals
95082
95325
  });
@@ -97499,7 +97742,7 @@ function compileDiagnostic(severity, code3, family, message, field, extra = {})
97499
97742
  ...extra
97500
97743
  };
97501
97744
  }
97502
- function isRecord19(value) {
97745
+ function isRecord20(value) {
97503
97746
  return value !== null && typeof value === "object" && !Array.isArray(value);
97504
97747
  }
97505
97748
 
@@ -97894,7 +98137,7 @@ function compileActionFromFields(fields) {
97894
98137
  return action;
97895
98138
  }
97896
98139
  function parseCompileAction(raw, index2, diagnostics) {
97897
- if (!isRecord19(raw)) {
98140
+ if (!isRecord20(raw)) {
97898
98141
  diagnostics.push(compileDiagnostic("error", "schema.action_object", "schema", "Each action must be an object.", `actions[${index2}]`));
97899
98142
  return;
97900
98143
  }
@@ -97906,7 +98149,7 @@ function parseCompileAction(raw, index2, diagnostics) {
97906
98149
  }
97907
98150
  function parseCompilePayload(value) {
97908
98151
  const diagnostics = [];
97909
- if (!isRecord19(value)) {
98152
+ if (!isRecord20(value)) {
97910
98153
  return {
97911
98154
  diagnostics: [compileDiagnostic("error", "schema.payload_object", "schema", "Compile action payload must be an object.", "schema")]
97912
98155
  };
@@ -98869,9 +99112,9 @@ init_atomicWrite();
98869
99112
  init_cliFeedback();
98870
99113
  init_errors();
98871
99114
  init_exitCode();
98872
- import { existsSync as existsSync37 } from "node:fs";
99115
+ import { existsSync as existsSync38 } from "node:fs";
98873
99116
  import { readFile as readFile46 } from "node:fs/promises";
98874
- import { join as join59 } from "node:path";
99117
+ import { join as join60 } from "node:path";
98875
99118
  init_writeLock();
98876
99119
  var CUSTOM_PHASE_MANIFEST = ".tmp/context-runtime/extract/custom-phase-candidates.json";
98877
99120
  function customInputError(phaseId, message, detail = {}) {
@@ -99025,8 +99268,8 @@ function candidateFromCustom(input) {
99025
99268
  };
99026
99269
  }
99027
99270
  async function readManifest(projectRoot) {
99028
- const path4 = join59(projectRoot, CUSTOM_PHASE_MANIFEST);
99029
- if (!existsSync37(path4))
99271
+ const path4 = join60(projectRoot, CUSTOM_PHASE_MANIFEST);
99272
+ if (!existsSync38(path4))
99030
99273
  return { version: 2, phases: {} };
99031
99274
  try {
99032
99275
  const parsed = JSON.parse(await readFile46(path4, "utf8"));
@@ -99126,7 +99369,7 @@ async function runExtractCustomPhase(input) {
99126
99369
  symbols: built.flatMap((item) => item.symbols),
99127
99370
  removeSymbols: previousOwned?.symbols ?? []
99128
99371
  });
99129
- await atomicWriteFile(join59(input.projectRoot, CUSTOM_PHASE_MANIFEST), `${JSON.stringify({
99372
+ await atomicWriteFile(join60(input.projectRoot, CUSTOM_PHASE_MANIFEST), `${JSON.stringify({
99130
99373
  version: 2,
99131
99374
  phases: {
99132
99375
  ...manifest.phases,
@@ -99186,7 +99429,7 @@ async function runExtractCustomPhase(input) {
99186
99429
 
99187
99430
  // src/project/reviewHtml.ts
99188
99431
  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";
99432
+ import { dirname as dirname37, isAbsolute as isAbsolute9, join as join62, resolve as resolve23 } from "node:path";
99190
99433
  import { pathToFileURL as pathToFileURL3 } from "node:url";
99191
99434
 
99192
99435
  // src/project/reviewSourceExcerpts.ts
@@ -99296,9 +99539,9 @@ async function collectReviewSourceExcerpts(projectRoot, candidates) {
99296
99539
  }
99297
99540
 
99298
99541
  // src/project/reviewHtmlPresentation.ts
99299
- import { existsSync as existsSync38 } from "node:fs";
99542
+ import { existsSync as existsSync39 } from "node:fs";
99300
99543
  import { readFile as readFile47 } from "node:fs/promises";
99301
- import { join as join60 } from "node:path";
99544
+ import { join as join61 } from "node:path";
99302
99545
  var import_yaml31 = __toESM(require_dist3(), 1);
99303
99546
  function escapeHtml3(value) {
99304
99547
  return value.replace(/&/gu, "&amp;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;").replace(/"/gu, "&quot;");
@@ -99379,8 +99622,8 @@ function filterEdgePreviewForCandidate(record, edges) {
99379
99622
  return edges.filter((edge2) => endpoints.has(edge2.from) || endpoints.has(edge2.to));
99380
99623
  }
99381
99624
  async function readEdgePreview(projectRoot) {
99382
- const filePath = join60(projectRoot, LIFECYCLE_STRUCTURE_FILE);
99383
- if (!existsSync38(filePath))
99625
+ const filePath = join61(projectRoot, LIFECYCLE_STRUCTURE_FILE);
99626
+ if (!existsSync39(filePath))
99384
99627
  return [];
99385
99628
  try {
99386
99629
  const parsed = import_yaml31.default.parse(await readFile47(filePath, "utf8"));
@@ -99557,7 +99800,7 @@ var REVIEW_HTML_STYLES = `
99557
99800
  `;
99558
99801
 
99559
99802
  // src/project/reviewHtml.ts
99560
- var REVIEW_HTML_ROOT = join61(".tmp", "context-runtime", "review");
99803
+ var REVIEW_HTML_ROOT = join62(".tmp", "context-runtime", "review");
99561
99804
  function decodedLinkTarget(value) {
99562
99805
  try {
99563
99806
  return decodeURIComponent(value);
@@ -99571,7 +99814,7 @@ function linkedResourcePreviews(input) {
99571
99814
  const target = link2.target;
99572
99815
  if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("/"))
99573
99816
  continue;
99574
- const assetPath = join61(dirname36(input.documentPath), decodedLinkTarget(target)).split("\\").join("/");
99817
+ const assetPath = join62(dirname37(input.documentPath), decodedLinkTarget(target)).split("\\").join("/");
99575
99818
  const asset = input.assetsByPath.get(assetPath);
99576
99819
  if (asset?.content_hash === undefined || asset.role === "audit")
99577
99820
  continue;
@@ -99579,7 +99822,7 @@ function linkedResourcePreviews(input) {
99579
99822
  label: link2.label || "Resource",
99580
99823
  kind: asset.source?.kind ?? "resource",
99581
99824
  status: "materialized",
99582
- url: pathToFileURL3(join61(input.projectRoot, input.materializedAt, asset.path)).href,
99825
+ url: pathToFileURL3(join62(input.projectRoot, input.materializedAt, asset.path)).href,
99583
99826
  media_type: asset.media_type ?? "application/octet-stream",
99584
99827
  image: asset.media_type?.startsWith("image/") === true
99585
99828
  });
@@ -99588,7 +99831,7 @@ function linkedResourcePreviews(input) {
99588
99831
  }
99589
99832
  function materializationPreview(input) {
99590
99833
  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);
99834
+ const url = input.existing?.url ?? (linkedAsset?.content_hash === undefined ? undefined : pathToFileURL3(join62(input.projectRoot, input.materializedAt, linkedAsset.path)).href);
99592
99835
  return {
99593
99836
  key: linkedAsset?.path ?? input.item.locator,
99594
99837
  preview: {
@@ -100132,7 +100375,7 @@ function renderReviewHtml(candidates, reviewScope, edgePreview, sourceExcerpts,
100132
100375
  }
100133
100376
  function resolveOutputPath(projectRoot, outPath, reviewScope) {
100134
100377
  if (outPath === undefined)
100135
- return join61(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
100378
+ return join62(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
100136
100379
  return isAbsolute9(outPath) ? outPath : resolve23(projectRoot, outPath);
100137
100380
  }
100138
100381
  async function writeReviewHtml(input) {
@@ -100145,7 +100388,7 @@ async function writeReviewHtml(input) {
100145
100388
  const sourceExcerpts = await collectReviewSourceExcerpts(input.projectRoot, candidates);
100146
100389
  const resourcePreviews = await collectReviewResourcePreviews(input.projectRoot, candidates);
100147
100390
  const outPath = resolveOutputPath(input.projectRoot, input.out, reviewScope);
100148
- await mkdir29(dirname36(outPath), { recursive: true });
100391
+ await mkdir29(dirname37(outPath), { recursive: true });
100149
100392
  await writeFile24(outPath, renderReviewHtml(candidates, reviewScope, edgePreview, sourceExcerpts, resourcePreviews), "utf8");
100150
100393
  return {
100151
100394
  path: outPath,
@@ -100560,17 +100803,17 @@ function compactJsonResult(result, verbose) {
100560
100803
  }
100561
100804
 
100562
100805
  // src/project/runLog.ts
100563
- import { randomUUID as randomUUID2 } from "node:crypto";
100806
+ import { randomUUID as randomUUID3 } from "node:crypto";
100564
100807
  import { mkdir as mkdir30, writeFile as writeFile25 } from "node:fs/promises";
100565
- import { dirname as dirname37, join as join62 } from "node:path";
100808
+ import { dirname as dirname38, join as join63 } from "node:path";
100566
100809
  var createPhaseRunId = () => {
100567
100810
  const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
100568
- return `run_${timestamp}_${randomUUID2().slice(0, 8)}`;
100811
+ return `run_${timestamp}_${randomUUID3().slice(0, 8)}`;
100569
100812
  };
100570
100813
  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 });
100814
+ const relPath = join63(".tmp", "context-runtime", "runs", `${input.runId}.json`);
100815
+ const absPath = join63(input.projectRoot, relPath);
100816
+ await mkdir30(dirname38(absPath), { recursive: true });
100574
100817
  await writeFile25(absPath, `${JSON.stringify({
100575
100818
  run_id: input.runId,
100576
100819
  phase_id: input.phase.id,
@@ -101271,14 +101514,14 @@ init_exitCode();
101271
101514
  import { resolve as resolve24 } from "node:path";
101272
101515
  init_workspace();
101273
101516
  var PROSE_STRUCTURE_BATCH_SCHEMA = "context.prose.structure-batch.v1";
101274
- function isRecord20(value) {
101517
+ function isRecord21(value) {
101275
101518
  return value !== null && typeof value === "object" && !Array.isArray(value);
101276
101519
  }
101277
101520
  function shellQuote8(value) {
101278
101521
  return /^[A-Za-z0-9._/=-]+$/u.test(value) ? value : `'${value.replace(/'/gu, `'"'"'`)}'`;
101279
101522
  }
101280
101523
  function parseBatchPayload(value) {
101281
- if (!isRecord20(value) || value.schema !== PROSE_STRUCTURE_BATCH_SCHEMA || !Array.isArray(value.items)) {
101524
+ if (!isRecord21(value) || value.schema !== PROSE_STRUCTURE_BATCH_SCHEMA || !Array.isArray(value.items)) {
101282
101525
  throw new ContextError(ExitCode.UserError, `batch input must match ${PROSE_STRUCTURE_BATCH_SCHEMA}`, {
101283
101526
  category: ErrorCategory.UserInputInvalid,
101284
101527
  next: "Read the current Route action input_schema and provide one phase_id/input pair per pending structure slot."
@@ -101291,7 +101534,7 @@ function parseBatchPayload(value) {
101291
101534
  }
101292
101535
  const seen = new Set;
101293
101536
  return value.items.map((item, index2) => {
101294
- if (!isRecord20(item) || typeof item.phase_id !== "string" || typeof item.input !== "string") {
101537
+ if (!isRecord21(item) || typeof item.phase_id !== "string" || typeof item.input !== "string") {
101295
101538
  throw new ContextError(ExitCode.UserError, `structure batch items[${index2}] requires phase_id and input`, {
101296
101539
  category: ErrorCategory.UserInputInvalid
101297
101540
  });
@@ -101323,7 +101566,7 @@ function alignPhase(phases, phaseId) {
101323
101566
  return phase;
101324
101567
  }
101325
101568
  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;
101569
+ const counts2 = result.structure_summary_compact !== undefined && isRecord21(result.structure_summary_compact.counts) ? result.structure_summary_compact.counts : undefined;
101327
101570
  return {
101328
101571
  phase_id: phaseId,
101329
101572
  input,
@@ -101817,7 +102060,7 @@ init_debugTrace();
101817
102060
  // src/project/workflow/workflowExecutionRuntime.ts
101818
102061
  init_debugTrace();
101819
102062
  import { createHash as createHash26 } from "node:crypto";
101820
- import { spawn as spawn3 } from "node:child_process";
102063
+ import { spawn as spawn4 } from "node:child_process";
101821
102064
  function digestText2(value, includeTail) {
101822
102065
  const bytes = Buffer.byteLength(value);
101823
102066
  return {
@@ -101967,7 +102210,7 @@ execution scope cleanup failed`, true)
101967
102210
  try {
101968
102211
  receipt = await new Promise((resolve8, reject) => {
101969
102212
  let settled = false;
101970
- const child = spawn3(process.execPath, [this.cliEntryPath, ...args], {
102213
+ const child = spawn4(process.execPath, [this.cliEntryPath, ...args], {
101971
102214
  cwd: input.cwd,
101972
102215
  env: { ...process.env, ...debugChildEnvironment() },
101973
102216
  stdio: ["ignore", "pipe", "pipe"],
@@ -102332,7 +102575,7 @@ function requirePayloadHeaderField(value, field) {
102332
102575
  return value;
102333
102576
  }
102334
102577
  function parsePayloadLineDecision(value, index2) {
102335
- if (!isRecord16(value) || typeof value.candidate_id !== "string") {
102578
+ if (!isRecord17(value) || typeof value.candidate_id !== "string") {
102336
102579
  throw new ContextError(ExitCode.UserError, `review payload line ${index2} must contain candidate_id and status`, {
102337
102580
  category: ErrorCategory.UserInputInvalid
102338
102581
  });
@@ -102345,7 +102588,7 @@ function parsePayloadLineDecision(value, index2) {
102345
102588
  function parsePayloadScope(value) {
102346
102589
  if (value === undefined)
102347
102590
  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)) {
102591
+ 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
102592
  throw new ContextError(ExitCode.UserError, "review payload scope must contain count and ids_sha256", {
102350
102593
  category: ErrorCategory.UserInputInvalid
102351
102594
  });
@@ -102384,7 +102627,7 @@ function parsePayloadScope(value) {
102384
102627
  }
102385
102628
  function parsePayloadValues(parsed) {
102386
102629
  const first = parsed[0];
102387
- if (!isRecord16(first)) {
102630
+ if (!isRecord17(first)) {
102388
102631
  throw new ContextError(ExitCode.UserError, "review payload header must be a JSON object", {
102389
102632
  category: ErrorCategory.UserInputInvalid
102390
102633
  });
@@ -103296,7 +103539,7 @@ async function runManagedUntil(input) {
103296
103539
  const resourceReceipts = input.resourceReceiptsReference === undefined ? undefined : await parseWorkflowResourceReceipts(input.resourceReceiptsReference, found.projectRoot);
103297
103540
  const runtime = new WorkspaceExecutionRuntime({
103298
103541
  projectRoot: found.projectRoot,
103299
- cliEntryPath: fileURLToPath7(input.cliModuleUrl),
103542
+ cliEntryPath: fileURLToPath8(input.cliModuleUrl),
103300
103543
  inProcess: createWorkflowInProcessExecutor()
103301
103544
  });
103302
103545
  let result;
@@ -103441,10 +103684,10 @@ function registerDebugCommands(program2) {
103441
103684
 
103442
103685
  // src/commands/cleanClaudePluginCache.ts
103443
103686
  init_cliFeedback();
103444
- import { existsSync as existsSync39 } from "node:fs";
103687
+ import { existsSync as existsSync40 } from "node:fs";
103445
103688
  import { readdir as readdir19, rm as rm16 } from "node:fs/promises";
103446
103689
  import { homedir } from "node:os";
103447
- import { join as join63 } from "node:path";
103690
+ import { join as join64 } from "node:path";
103448
103691
  var ORPHAN_MARKER = ".orphaned_at";
103449
103692
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
103450
103693
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -103453,7 +103696,7 @@ async function cleanClaudePluginCache(opts = {}) {
103453
103696
  const lines = [];
103454
103697
  let removed = 0;
103455
103698
  let scanned = 0;
103456
- if (!existsSync39(cacheRoot)) {
103699
+ if (!existsSync40(cacheRoot)) {
103457
103700
  lines.push("· claude plugin cache: missing — nothing to clean");
103458
103701
  return { lines, removed, scanned };
103459
103702
  }
@@ -103461,20 +103704,20 @@ async function cleanClaudePluginCache(opts = {}) {
103461
103704
  for (const mp of marketplaces) {
103462
103705
  if (!mp.isDirectory())
103463
103706
  continue;
103464
- const mpDir = join63(cacheRoot, mp.name);
103707
+ const mpDir = join64(cacheRoot, mp.name);
103465
103708
  const plugins = await readdir19(mpDir, { withFileTypes: true });
103466
103709
  for (const pl of plugins) {
103467
103710
  if (!pl.isDirectory())
103468
103711
  continue;
103469
- const plDir = join63(mpDir, pl.name);
103712
+ const plDir = join64(mpDir, pl.name);
103470
103713
  const versions = await readdir19(plDir, { withFileTypes: true });
103471
103714
  for (const ver of versions) {
103472
103715
  if (!ver.isDirectory())
103473
103716
  continue;
103474
103717
  scanned += 1;
103475
- const verDir = join63(plDir, ver.name);
103476
- const markerPath = join63(verDir, ORPHAN_MARKER);
103477
- if (!existsSync39(markerPath))
103718
+ const verDir = join64(plDir, ver.name);
103719
+ const markerPath = join64(verDir, ORPHAN_MARKER);
103720
+ if (!existsSync40(markerPath))
103478
103721
  continue;
103479
103722
  const label3 = `${mp.name}/${pl.name}/${ver.name}`;
103480
103723
  if (opts.dryRun) {
@@ -103505,7 +103748,7 @@ function resolveClaudePluginCacheRoot(opts) {
103505
103748
  if (explicitRoot)
103506
103749
  return explicitRoot;
103507
103750
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
103508
- return join63(home, ".claude", "plugins", "cache");
103751
+ return join64(home, ".claude", "plugins", "cache");
103509
103752
  }
103510
103753
  async function isEmptyDir(dir) {
103511
103754
  try {
@@ -103531,17 +103774,17 @@ async function runDoctorCleanClaudePluginCache(opts = {}) {
103531
103774
  }
103532
103775
 
103533
103776
  // src/commands/cleanCache.ts
103534
- import { existsSync as existsSync41 } from "node:fs";
103777
+ import { existsSync as existsSync42 } from "node:fs";
103535
103778
  import { readdir as readdir20, rm as rm17 } from "node:fs/promises";
103536
- import { join as join67 } from "node:path";
103779
+ import { join as join68 } from "node:path";
103537
103780
 
103538
103781
  // src/incremental/cache.ts
103539
- import { basename as basename10, dirname as dirname39, isAbsolute as isAbsolute11, join as join66, resolve as resolve27 } from "node:path";
103782
+ import { basename as basename10, dirname as dirname40, isAbsolute as isAbsolute11, join as join67, resolve as resolve27 } from "node:path";
103540
103783
 
103541
103784
  // src/lib/workspaceLayout.ts
103542
103785
  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";
103786
+ import { existsSync as existsSync41, readFileSync as readFileSync9, statSync as statSync2 } from "node:fs";
103787
+ import { dirname as dirname39, join as join65, parse as parse7, resolve as resolve26 } from "node:path";
103545
103788
  function isDirectorySafe(path4) {
103546
103789
  try {
103547
103790
  return statSync2(path4).isDirectory();
@@ -103550,11 +103793,11 @@ function isDirectorySafe(path4) {
103550
103793
  }
103551
103794
  }
103552
103795
  function hasRootLayoutMarker(dir) {
103553
- const configPath = join64(dir, "config.yaml");
103554
- if (!existsSync40(configPath))
103796
+ const configPath = join65(dir, "config.yaml");
103797
+ if (!existsSync41(configPath))
103555
103798
  return false;
103556
103799
  try {
103557
- const parsed = import_yaml32.default.parse(readFileSync8(configPath, "utf8"));
103800
+ const parsed = import_yaml32.default.parse(readFileSync9(configPath, "utf8"));
103558
103801
  if (!parsed || typeof parsed !== "object")
103559
103802
  return false;
103560
103803
  const workspace = parsed.workspace;
@@ -103567,8 +103810,8 @@ function hasRootLayoutMarker(dir) {
103567
103810
  }
103568
103811
  function findWorkspaceAt(dir) {
103569
103812
  const root2 = resolve26(dir);
103570
- const embedded = join64(root2, ".context");
103571
- if (existsSync40(join64(embedded, "config.yaml")) && isDirectorySafe(embedded)) {
103813
+ const embedded = join65(root2, ".context");
103814
+ if (existsSync41(join65(embedded, "config.yaml")) && isDirectorySafe(embedded)) {
103572
103815
  return { ctxDir: embedded, workspaceRoot: root2, layout: "embedded" };
103573
103816
  }
103574
103817
  if (hasRootLayoutMarker(root2)) {
@@ -103585,7 +103828,7 @@ function findNearestWorkspace(startDir = process.cwd()) {
103585
103828
  return found;
103586
103829
  if (dir === root2)
103587
103830
  return null;
103588
- const parent = dirname38(dir);
103831
+ const parent = dirname39(dir);
103589
103832
  if (parent === dir)
103590
103833
  return null;
103591
103834
  dir = parent;
@@ -103593,9 +103836,9 @@ function findNearestWorkspace(startDir = process.cwd()) {
103593
103836
  }
103594
103837
 
103595
103838
  // src/lib/userCache.ts
103596
- import { basename as basename9, join as join65 } from "node:path";
103839
+ import { basename as basename9, join as join66 } from "node:path";
103597
103840
  function workspaceLocalUserCacheRoot(ctxDir) {
103598
- return join65(ctxDir, ".tmp", "context-cli");
103841
+ return join66(ctxDir, ".tmp", "context-cli");
103599
103842
  }
103600
103843
 
103601
103844
  // src/incremental/cache.ts
@@ -103605,7 +103848,7 @@ function resolveCachePath(value) {
103605
103848
  }
103606
103849
  function workspaceCacheHome(workspaceRoot) {
103607
103850
  const location = findWorkspaceAt(workspaceRoot);
103608
- return workspaceLocalUserCacheRoot(location?.ctxDir ?? join66(workspaceRoot, ".context"));
103851
+ return workspaceLocalUserCacheRoot(location?.ctxDir ?? join67(workspaceRoot, ".context"));
103609
103852
  }
103610
103853
  function resolveCacheHome(input = {}) {
103611
103854
  const explicit = input.cacheHome ?? process.env.C4A_CONTEXT_CACHE_HOME;
@@ -103614,24 +103857,24 @@ function resolveCacheHome(input = {}) {
103614
103857
  if (input.workspaceRoot !== undefined)
103615
103858
  return workspaceCacheHome(resolveCachePath(input.workspaceRoot));
103616
103859
  const nearest = findNearestWorkspace(process.cwd());
103617
- return workspaceLocalUserCacheRoot(nearest?.ctxDir ?? join66(process.cwd(), ".context"));
103860
+ return workspaceLocalUserCacheRoot(nearest?.ctxDir ?? join67(process.cwd(), ".context"));
103618
103861
  }
103619
103862
 
103620
103863
  // src/commands/cleanCache.ts
103621
103864
  async function countFiles2(dir) {
103622
- if (!existsSync41(dir))
103865
+ if (!existsSync42(dir))
103623
103866
  return 0;
103624
103867
  let count = 0;
103625
103868
  for (const entry of await readdir20(dir, { withFileTypes: true })) {
103626
- const full = join67(dir, entry.name);
103869
+ const full = join68(dir, entry.name);
103627
103870
  count += entry.isDirectory() ? await countFiles2(full) : 1;
103628
103871
  }
103629
103872
  return count;
103630
103873
  }
103631
103874
  async function inspectAllRetrievalCache() {
103632
103875
  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() : [];
103876
+ const cacheRoot = join68(cacheHome, "retrieval");
103877
+ const projectIds = existsSync42(cacheRoot) ? (await readdir20(cacheRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort() : [];
103635
103878
  const files = await countFiles2(cacheRoot);
103636
103879
  return { cacheRoot, projects: projectIds.length, files, projectIds };
103637
103880
  }
@@ -103649,8 +103892,6 @@ async function cleanAllRetrievalCache() {
103649
103892
  init_errors();
103650
103893
  init_cliFeedback();
103651
103894
  init_exitCode();
103652
- init_workspace();
103653
- init_packageTemplateReview();
103654
103895
 
103655
103896
  // src/project/sourceCommands.ts
103656
103897
  import { readFile as readFile54 } from "node:fs/promises";
@@ -103665,9 +103906,9 @@ init_cliFeedback();
103665
103906
  init_errors();
103666
103907
  init_exitCode();
103667
103908
  import { execFile as execFile6 } from "node:child_process";
103668
- import { existsSync as existsSync42 } from "node:fs";
103909
+ import { existsSync as existsSync43 } from "node:fs";
103669
103910
  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";
103911
+ import { basename as basename11, dirname as dirname41, isAbsolute as isAbsolute12, relative as relative20, resolve as resolve28 } from "node:path";
103671
103912
  import { promisify as promisify6 } from "node:util";
103672
103913
  init_writeLock();
103673
103914
  var execFileAsync6 = promisify6(execFile6);
@@ -103809,7 +104050,7 @@ async function git2(cwd, args) {
103809
104050
  }
103810
104051
  async function resolveGitRoot2(path4) {
103811
104052
  const root2 = await git2(path4, ["rev-parse", "--show-toplevel"]);
103812
- if (root2.length === 0 || !existsSync42(root2)) {
104053
+ if (root2.length === 0 || !existsSync43(root2)) {
103813
104054
  throw userInputError3(`local repository path is not a Git checkout: ${path4}`, { path: path4 });
103814
104055
  }
103815
104056
  return realpath4(root2);
@@ -103830,13 +104071,13 @@ async function verifyCheckout(input) {
103830
104071
  }
103831
104072
  async function cloneCheckout(input) {
103832
104073
  const target = resolve28(input.projectRoot, input.target ?? `.tmp/repo/${repositorySlug(input.remote)}-${input.ref.slice(0, 12)}`);
103833
- if (existsSync42(target)) {
104074
+ if (existsSync43(target)) {
103834
104075
  throw userInputError3(`clone target already exists: ${target}`, {
103835
104076
  target,
103836
104077
  next: `Use local mode with path ${JSON.stringify(target)} after inspecting the existing checkout.`
103837
104078
  });
103838
104079
  }
103839
- await mkdir31(dirname40(target), { recursive: true });
104080
+ await mkdir31(dirname41(target), { recursive: true });
103840
104081
  const cloneArgs = ["clone", "--no-checkout", "--depth=1", "--filter=blob:none", input.remote, target];
103841
104082
  try {
103842
104083
  await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
@@ -103885,7 +104126,7 @@ async function bindLocalAlias(input) {
103885
104126
  const stats = await lstat3(alias).catch(() => null);
103886
104127
  if (stats !== null) {
103887
104128
  if (stats.isSymbolicLink()) {
103888
- const actual = resolve28(dirname40(alias), await readlink2(alias));
104129
+ const actual = resolve28(dirname41(alias), await readlink2(alias));
103889
104130
  const actualReal = await realpath4(actual).catch(() => null);
103890
104131
  if (actualReal !== null && actualReal === await realpath4(input.checkout))
103891
104132
  return;
@@ -103901,8 +104142,8 @@ async function bindLocalAlias(input) {
103901
104142
  });
103902
104143
  }
103903
104144
  }
103904
- await mkdir31(dirname40(alias), { recursive: true });
103905
- await symlink2(relative20(dirname40(alias), input.checkout) || ".", alias);
104145
+ await mkdir31(dirname41(alias), { recursive: true });
104146
+ await symlink2(relative20(dirname41(alias), input.checkout) || ".", alias);
103906
104147
  }
103907
104148
  function selectPhysicalGroup(sources, selector) {
103908
104149
  const direct = selectRepoSources(sources, selector);
@@ -103989,13 +104230,13 @@ async function restoreRepositorySources(input) {
103989
104230
  }
103990
104231
 
103991
104232
  // src/project/sourceDocumentStatus.ts
103992
- import { existsSync as existsSync43 } from "node:fs";
104233
+ import { existsSync as existsSync44 } from "node:fs";
103993
104234
  import { readFile as readFile51 } from "node:fs/promises";
103994
- import { join as join69 } from "node:path";
104235
+ import { join as join70 } from "node:path";
103995
104236
 
103996
104237
  // src/project/sourceCommandViews.ts
103997
104238
  import { readFile as readFile50 } from "node:fs/promises";
103998
- import { join as join68 } from "node:path";
104239
+ import { join as join69 } from "node:path";
103999
104240
  init_workspace();
104000
104241
  function repoSourceAgentView(source2) {
104001
104242
  return {
@@ -104057,7 +104298,7 @@ async function fileSourceAgentViewWithNextAction(input) {
104057
104298
  };
104058
104299
  }
104059
104300
  function documentSourceManifestPath(source2) {
104060
- return source2.snapshot?.manifest ?? join68(source2.materializedAt, "manifest.json");
104301
+ return source2.snapshot?.manifest ?? join69(source2.materializedAt, "manifest.json");
104061
104302
  }
104062
104303
  async function fileSourceDocumentSiteHint(input) {
104063
104304
  const detection = await detectDocumentSiteFiles({
@@ -104067,7 +104308,7 @@ async function fileSourceDocumentSiteHint(input) {
104067
104308
  let snapshotConfigured = false;
104068
104309
  const manifest = documentSourceManifestPath(input.source);
104069
104310
  try {
104070
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile50(join68(input.projectRoot, manifest), "utf8")), input.source.name);
104311
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile50(join69(input.projectRoot, manifest), "utf8")), input.source.name);
104071
104312
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
104072
104313
  } catch {
104073
104314
  snapshotConfigured = false;
@@ -104098,12 +104339,12 @@ async function larkSourceAgentViewWithNextAction(input) {
104098
104339
 
104099
104340
  // src/project/sourceDocumentStatus.ts
104100
104341
  function documentSourceManifestPath2(source2) {
104101
- return source2.snapshot?.manifest ?? join69(source2.materializedAt, "manifest.json");
104342
+ return source2.snapshot?.manifest ?? join70(source2.materializedAt, "manifest.json");
104102
104343
  }
104103
104344
  async function documentSnapshotState(input) {
104104
104345
  const manifest = documentSourceManifestPath2(input.source);
104105
- const manifestPath = join69(input.projectRoot, manifest);
104106
- if (!existsSync43(manifestPath)) {
104346
+ const manifestPath = join70(input.projectRoot, manifest);
104347
+ if (!existsSync44(manifestPath)) {
104107
104348
  return {
104108
104349
  snapshotReady: false,
104109
104350
  state: "needs-capture",
@@ -104181,7 +104422,7 @@ async function documentSnapshotState(input) {
104181
104422
  const missing = [
104182
104423
  ...parsed.files.map((file) => file.path),
104183
104424
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
104184
- ].find((path4) => !existsSync43(join69(input.projectRoot, input.source.materializedAt, path4)));
104425
+ ].find((path4) => !existsSync44(join70(input.projectRoot, input.source.materializedAt, path4)));
104185
104426
  if (missing !== undefined) {
104186
104427
  return {
104187
104428
  snapshotReady: false,
@@ -104253,7 +104494,7 @@ async function inspectDocumentSources(input) {
104253
104494
  // src/project/documentSourceRegistration.ts
104254
104495
  import { createHash as createHash27 } from "node:crypto";
104255
104496
  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";
104497
+ import { basename as basename12, extname as extname13, isAbsolute as isAbsolute13, join as join71, relative as relative21, resolve as resolve29 } from "node:path";
104257
104498
  init_atomicWrite();
104258
104499
  init_cliFeedback();
104259
104500
  init_errors();
@@ -104354,7 +104595,7 @@ function assertSafeFileInclude(value) {
104354
104595
  }
104355
104596
  async function readRegistryDocument(projectRoot, registryPath2) {
104356
104597
  try {
104357
- const content3 = await readFile52(join70(projectRoot, registryPath2), "utf8");
104598
+ const content3 = await readFile52(join71(projectRoot, registryPath2), "utf8");
104358
104599
  return content3.trim().length === 0 ? { sources: [] } : import_yaml33.default.parse(content3);
104359
104600
  } catch (error) {
104360
104601
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -104472,7 +104713,7 @@ async function addFileSourceUnlocked(input) {
104472
104713
  const record2 = entry2;
104473
104714
  return record2.name !== input.name && record2.id !== input.name;
104474
104715
  }), nextEntry];
104475
- await atomicWriteFile(join70(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104716
+ await atomicWriteFile(join71(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104476
104717
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
104477
104718
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
104478
104719
  if (entry === undefined) {
@@ -104528,7 +104769,7 @@ async function addLarkSourceUnlocked(input) {
104528
104769
  const record2 = entry2;
104529
104770
  return record2.name !== input.name && record2.id !== input.name;
104530
104771
  }), nextEntry];
104531
- await atomicWriteFile(join70(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104772
+ await atomicWriteFile(join71(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104532
104773
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
104533
104774
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
104534
104775
  if (entry === undefined) {
@@ -104716,10 +104957,10 @@ async function registerSourceBatch(input) {
104716
104957
  }
104717
104958
 
104718
104959
  // src/project/sourceRemoval.ts
104719
- import { existsSync as existsSync44 } from "node:fs";
104960
+ import { existsSync as existsSync45 } from "node:fs";
104720
104961
  import { createHash as createHash28 } from "node:crypto";
104721
104962
  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";
104963
+ import { isAbsolute as isAbsolute14, join as join72, relative as relative22, resolve as resolve30, sep as sep6 } from "node:path";
104723
104964
  var import_yaml34 = __toESM(require_dist3(), 1);
104724
104965
  init_atomicWrite();
104725
104966
  init_cliFeedback();
@@ -104758,8 +104999,8 @@ function collectStrings(value, output) {
104758
104999
  }
104759
105000
  }
104760
105001
  async function yamlReferences(input) {
104761
- const absolutePath = join71(input.projectRoot, input.path);
104762
- if (!existsSync44(absolutePath))
105002
+ const absolutePath = join72(input.projectRoot, input.path);
105003
+ if (!existsSync45(absolutePath))
104763
105004
  return false;
104764
105005
  const parsed = import_yaml34.default.parse(await readFile53(absolutePath, "utf8"));
104765
105006
  const strings = [];
@@ -104866,8 +105107,8 @@ function removeDocumentEntry(document4, source2) {
104866
105107
  }
104867
105108
  async function registryRemovalWrite(projectRoot, source2) {
104868
105109
  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: [] };
105110
+ const absolutePath = join72(projectRoot, path4);
105111
+ const document4 = existsSync45(absolutePath) ? import_yaml34.default.parse(await readFile53(absolutePath, "utf8")) : { sources: [] };
104871
105112
  return {
104872
105113
  path: absolutePath,
104873
105114
  bytes: import_yaml34.default.stringify(removeDocumentEntry(document4, source2))
@@ -104885,7 +105126,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
104885
105126
  return absolute;
104886
105127
  }
104887
105128
  function safeManagedManifestPath(projectRoot, source2) {
104888
- const manifest = source2.manifest ?? join71(source2.materializedAt, "manifest.json");
105129
+ const manifest = source2.manifest ?? join72(source2.materializedAt, "manifest.json");
104889
105130
  if (isAbsolute14(manifest))
104890
105131
  throw unsafeOwnership(source2, manifest);
104891
105132
  const absolute = resolve30(projectRoot, manifest);
@@ -104991,7 +105232,7 @@ async function createRemovalPlan(projectRoot, selector) {
104991
105232
  }
104992
105233
  } else {
104993
105234
  const materializedPath = safeManagedMaterializedPath(projectRoot, source2);
104994
- if (materializedPath !== undefined && sharedMaterializedBy.length === 0 && existsSync44(materializedPath)) {
105235
+ if (materializedPath !== undefined && sharedMaterializedBy.length === 0 && existsSync45(materializedPath)) {
104995
105236
  absoluteRemovals.push(materializedPath);
104996
105237
  cleanup = {
104997
105238
  mode: "exclusive-materialization",
@@ -105037,9 +105278,9 @@ function publicRemovalResult(plan, action) {
105037
105278
  };
105038
105279
  }
105039
105280
  async function pruneExtractRuntime(projectRoot, source2) {
105040
- const fingerprintPath = join71(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
105281
+ const fingerprintPath = join72(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
105041
105282
  const removedPhaseIds = new Set;
105042
- if (existsSync44(fingerprintPath)) {
105283
+ if (existsSync45(fingerprintPath)) {
105043
105284
  const parsed = JSON.parse(await readFile53(fingerprintPath, "utf8"));
105044
105285
  const phases = parsed.phases ?? {};
105045
105286
  const next = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
@@ -105054,20 +105295,20 @@ async function pruneExtractRuntime(projectRoot, source2) {
105054
105295
  await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next }, null, 2)}
105055
105296
  `);
105056
105297
  }
105057
- const symbolPath = join71(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
105058
- if (existsSync44(symbolPath)) {
105298
+ const symbolPath = join72(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
105299
+ if (existsSync45(symbolPath)) {
105059
105300
  const parsed = JSON.parse(await readFile53(symbolPath, "utf8"));
105060
105301
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
105061
105302
  const phaseFingerprints = Object.fromEntries(Object.entries(parsed.phaseFingerprints ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
105062
105303
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
105063
105304
  `);
105064
105305
  }
105065
- const snapshotRoot = join71(projectRoot, ".tmp/context-runtime/extract/candidates");
105306
+ const snapshotRoot = join72(projectRoot, ".tmp/context-runtime/extract/candidates");
105066
105307
  const visit3 = async (directory) => {
105067
- if (!existsSync44(directory))
105308
+ if (!existsSync45(directory))
105068
105309
  return;
105069
105310
  for (const entry of await readdir21(directory, { withFileTypes: true })) {
105070
- const path4 = join71(directory, entry.name);
105311
+ const path4 = join72(directory, entry.name);
105071
105312
  if (entry.isDirectory()) {
105072
105313
  await visit3(path4);
105073
105314
  continue;
@@ -105117,7 +105358,7 @@ async function removeProjectSource(input) {
105117
105358
  });
105118
105359
  }
105119
105360
  await applyAtomicFileBatch({
105120
- transactionRoot: join71(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
105361
+ transactionRoot: join72(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
105121
105362
  writes: [plan.registryWrite, ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
105122
105363
  removals: plan.absoluteRemovals
105123
105364
  });
@@ -105515,16 +105756,147 @@ the CLI derives a lowercase path-safe module and rejects duplicate batch identit
105515
105756
  });
105516
105757
  }
105517
105758
 
105759
+ // src/cli.ts
105760
+ init_debugTrace();
105761
+
105762
+ // src/registerProjectLifecycleCommands.ts
105763
+ init_cliFeedback();
105764
+ init_errors();
105765
+ init_workspace();
105766
+ init_exitCode();
105767
+ function registerProjectInitCommand(program2) {
105768
+ 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) => {
105769
+ const targetRoot = resolveContextProjectInitTarget(process.cwd(), projectDir);
105770
+ const wasContextWorkspace = isContextProjectRoot(targetRoot);
105771
+ const result = await initContextProject({
105772
+ cwd: process.cwd(),
105773
+ ...projectDir !== undefined ? { projectDir } : {},
105774
+ ...typeof options.name === "string" ? { name: options.name } : {},
105775
+ ...typeof options.language === "string" ? { language: projectLanguage(options.language) } : {},
105776
+ ...options.dev === true ? { dev: true } : {},
105777
+ ...options.debug === true ? { debug: true } : {},
105778
+ ...options.allowNonempty === true ? { allowNonempty: true } : {}
105779
+ });
105780
+ process.stdout.write(formatProjectInitResult(result));
105781
+ if (!wasContextWorkspace) {
105782
+ queueContextRuntimeEvent({
105783
+ cwd: result.projectRoot,
105784
+ kind: "workspace.initialized",
105785
+ properties: {
105786
+ init_mode: result.kept.length > 0 ? "nonempty_existing" : "new",
105787
+ language: result.language,
105788
+ created_file_count: result.created.length
105789
+ }
105790
+ });
105791
+ }
105792
+ });
105793
+ }
105794
+ function registerProjectStatusCommand(program2) {
105795
+ 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) => {
105796
+ const rootOptions = program2.opts();
105797
+ const resourceReceiptsReference = typeof options.resourceReceipts === "string" ? options.resourceReceipts : typeof rootOptions.workflowResourceReceipts === "string" ? rootOptions.workflowResourceReceipts : undefined;
105798
+ const resourceReceipts = resourceReceiptsReference !== undefined ? await parseWorkflowResourceReceipts(resourceReceiptsReference, process.cwd()) : undefined;
105799
+ if (await runProjectStatusCommand({
105800
+ cwd: process.cwd(),
105801
+ format: options.format === "json" ? "json" : "table",
105802
+ view: options.view === "full" ? "full" : "summary",
105803
+ managed: options.managed === true,
105804
+ authorities: workflowAuthorities(options.authority),
105805
+ ...resourceReceipts === undefined ? {} : { resourceReceipts },
105806
+ ...resourceReceiptsReference === undefined ? {} : { resourceReceiptsReference },
105807
+ onSuccess: (status) => {
105808
+ queueContextRuntimeEvent({
105809
+ cwd: status.projectRoot,
105810
+ kind: "workspace.active",
105811
+ properties: { workflow_status: status.workflow.status }
105812
+ });
105813
+ }
105814
+ })) {
105815
+ return;
105816
+ }
105817
+ throw new ContextError(ExitCode.WorkspaceStateError, "status requires a context project workspace", {
105818
+ category: ErrorCategory.WorkspaceNotFound
105819
+ });
105820
+ });
105821
+ }
105822
+ function registerProjectCloseAndBuildCommands(program2) {
105823
+ 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) => {
105824
+ if (options.format !== "text" && options.format !== "json") {
105825
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
105826
+ category: ErrorCategory.UserInputInvalid
105827
+ });
105828
+ }
105829
+ if (await runProjectCloseCommand({
105830
+ cwd: process.cwd(),
105831
+ format: options.format === "json" ? "json" : "text"
105832
+ })) {
105833
+ return;
105834
+ }
105835
+ throw new ContextError(ExitCode.WorkspaceStateError, "close requires a context project workspace", {
105836
+ category: ErrorCategory.WorkspaceNotFound
105837
+ });
105838
+ });
105839
+ 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) => {
105840
+ if (options.format !== "text" && options.format !== "json") {
105841
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
105842
+ category: ErrorCategory.UserInputInvalid
105843
+ });
105844
+ }
105845
+ if (await runProjectBuildCommand({
105846
+ cwd: process.cwd(),
105847
+ format: options.format === "json" ? "json" : "text",
105848
+ verbose: options.verbose === true
105849
+ })) {
105850
+ return;
105851
+ }
105852
+ throw new ContextError(ExitCode.WorkspaceStateError, "build requires a context project workspace", {
105853
+ category: ErrorCategory.WorkspaceNotFound
105854
+ });
105855
+ });
105856
+ }
105857
+ function registerProjectVerifyCommand(program2) {
105858
+ 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) => {
105859
+ if (options.format !== "table" && options.format !== "json") {
105860
+ throw new ContextError(ExitCode.UserError, "--format must be table or json", {
105861
+ category: ErrorCategory.UserInputInvalid
105862
+ });
105863
+ }
105864
+ if (options.view !== undefined && options.view !== "diagnostics") {
105865
+ throw new ContextError(ExitCode.UserError, "--view must be diagnostics", {
105866
+ category: ErrorCategory.UserInputInvalid
105867
+ });
105868
+ }
105869
+ if (options.view === "diagnostics" && options.format !== "json") {
105870
+ throw new ContextError(ExitCode.UserError, "--view diagnostics requires --format json", {
105871
+ category: ErrorCategory.UserInputInvalid
105872
+ });
105873
+ }
105874
+ if (await runProjectVerifyCommand({
105875
+ cwd: process.cwd(),
105876
+ format: options.format === "json" ? "json" : "table",
105877
+ ...options.compact === true ? { compact: true } : {},
105878
+ ...options.view === "diagnostics" ? { view: "diagnostics" } : {},
105879
+ ...typeof options.pageSize === "string" ? { pageSize: options.pageSize } : {},
105880
+ ...typeof options.pageToken === "string" ? { pageToken: options.pageToken } : {}
105881
+ })) {
105882
+ return;
105883
+ }
105884
+ throw new ContextError(ExitCode.WorkspaceStateError, "verify requires a context project workspace", {
105885
+ category: ErrorCategory.WorkspaceNotFound
105886
+ });
105887
+ });
105888
+ }
105889
+
105518
105890
  // src/project/pluginInstall.ts
105519
105891
  init_cliFeedback();
105520
105892
  init_errors();
105521
105893
  init_exitCode();
105522
- import { existsSync as existsSync45 } from "node:fs";
105894
+ import { existsSync as existsSync46 } from "node:fs";
105523
105895
  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
105896
  import { execFile as execFile7 } from "node:child_process";
105525
105897
  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";
105898
+ import { dirname as dirname42, join as join73, resolve as resolve32 } from "node:path";
105899
+ import { fileURLToPath as fileURLToPath9 } from "node:url";
105528
105900
  import { promisify as promisify7 } from "node:util";
105529
105901
  var execFileAsync7 = promisify7(execFile7);
105530
105902
  var MARKETPLACE_NAME = "c4a";
@@ -105563,10 +105935,10 @@ function pluginAgentOption(value) {
105563
105935
  }
105564
105936
  function packageCandidateDirs() {
105565
105937
  const dirs = [];
105566
- let dir = dirname41(fileURLToPath8(import.meta.url));
105938
+ let dir = dirname42(fileURLToPath9(import.meta.url));
105567
105939
  for (let index2 = 0;index2 < 8; index2++) {
105568
105940
  dirs.push(dir);
105569
- const parent = dirname41(dir);
105941
+ const parent = dirname42(dir);
105570
105942
  if (parent === dir)
105571
105943
  break;
105572
105944
  dir = parent;
@@ -105579,13 +105951,13 @@ function pluginRootCandidates() {
105579
105951
  return [resolve32(envRoot)];
105580
105952
  const candidates = [];
105581
105953
  for (const dir of packageCandidateDirs()) {
105582
- candidates.push(join72(dir, "plugins"));
105583
- candidates.push(join72(dir, "dist", "plugins"));
105954
+ candidates.push(join73(dir, "plugins"));
105955
+ candidates.push(join73(dir, "dist", "plugins"));
105584
105956
  }
105585
105957
  return [...new Set(candidates)];
105586
105958
  }
105587
105959
  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"));
105960
+ 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
105961
  }
105590
105962
  function resolveBundledPluginsRoot() {
105591
105963
  const candidates = pluginRootCandidates();
@@ -105650,14 +106022,14 @@ function failedAgentResult(agent, error) {
105650
106022
  };
105651
106023
  }
105652
106024
  function codexHome() {
105653
- return process.env.CODEX_HOME?.trim() || join72(homedir2(), ".codex");
106025
+ return process.env.CODEX_HOME?.trim() || join73(homedir2(), ".codex");
105654
106026
  }
105655
106027
  function claudePluginCacheRoot() {
105656
106028
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
105657
106029
  if (explicitRoot)
105658
106030
  return explicitRoot;
105659
106031
  const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
105660
- return join72(home, ".claude", "plugins", "cache");
106032
+ return join73(home, ".claude", "plugins", "cache");
105661
106033
  }
105662
106034
  function blockHeader(line) {
105663
106035
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -105708,7 +106080,7 @@ function pruneLegacyCodexConfigContent(content3) {
105708
106080
  `), removed };
105709
106081
  }
105710
106082
  async function pruneLegacyCodexConfig(dryRun, steps) {
105711
- const configPath = join72(codexHome(), "config.toml");
106083
+ const configPath = join73(codexHome(), "config.toml");
105712
106084
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105713
106085
  if (!current2)
105714
106086
  return;
@@ -105725,8 +106097,8 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
105725
106097
  }
105726
106098
  }
105727
106099
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
105728
- const cacheRoot = join72(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
105729
- if (!existsSync45(cacheRoot))
106100
+ const cacheRoot = join73(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
106101
+ if (!existsSync46(cacheRoot))
105730
106102
  return;
105731
106103
  const versions = (await readdir22(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
105732
106104
  if (versions.length === 0)
@@ -105737,7 +106109,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
105737
106109
  status: dryRun ? "planned" : "ran"
105738
106110
  });
105739
106111
  if (!dryRun)
105740
- await Promise.all(versions.map((version3) => rm20(join72(cacheRoot, version3), { recursive: true, force: true })));
106112
+ await Promise.all(versions.map((version3) => rm20(join73(cacheRoot, version3), { recursive: true, force: true })));
105741
106113
  }
105742
106114
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
105743
106115
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -105754,22 +106126,22 @@ async function isEmptyDir2(dir) {
105754
106126
  }
105755
106127
  async function pruneClaudeOrphanContextCache(dryRun, steps) {
105756
106128
  const cacheRoot = claudePluginCacheRoot();
105757
- if (!existsSync45(cacheRoot))
106129
+ if (!existsSync46(cacheRoot))
105758
106130
  return;
105759
106131
  const removed = [];
105760
106132
  const marketplaces = await readdir22(cacheRoot, { withFileTypes: true }).catch(() => []);
105761
106133
  for (const marketplace of marketplaces) {
105762
106134
  if (!marketplace.isDirectory())
105763
106135
  continue;
105764
- const pluginDir = join72(cacheRoot, marketplace.name, PLUGIN_NAME);
105765
- if (!existsSync45(pluginDir))
106136
+ const pluginDir = join73(cacheRoot, marketplace.name, PLUGIN_NAME);
106137
+ if (!existsSync46(pluginDir))
105766
106138
  continue;
105767
106139
  const versions = await readdir22(pluginDir, { withFileTypes: true }).catch(() => []);
105768
106140
  for (const version3 of versions) {
105769
106141
  if (!version3.isDirectory())
105770
106142
  continue;
105771
- const versionDir = join72(pluginDir, version3.name);
105772
- if (!existsSync45(join72(versionDir, ORPHAN_MARKER2)))
106143
+ const versionDir = join73(pluginDir, version3.name);
106144
+ if (!existsSync46(join73(versionDir, ORPHAN_MARKER2)))
105773
106145
  continue;
105774
106146
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
105775
106147
  if (!dryRun) {
@@ -105779,7 +106151,7 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
105779
106151
  if (!dryRun && await isEmptyDir2(pluginDir)) {
105780
106152
  await rm20(pluginDir, { recursive: true, force: true });
105781
106153
  }
105782
- const marketplaceDir = join72(cacheRoot, marketplace.name);
106154
+ const marketplaceDir = join73(cacheRoot, marketplace.name);
105783
106155
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
105784
106156
  await rm20(marketplaceDir, { recursive: true, force: true });
105785
106157
  }
@@ -105796,12 +106168,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
105796
106168
  if (LEGACY_PLUGIN_NAMES.length === 0)
105797
106169
  return;
105798
106170
  const cacheRoot = claudePluginCacheRoot();
105799
- if (!existsSync45(cacheRoot))
106171
+ if (!existsSync46(cacheRoot))
105800
106172
  return;
105801
106173
  const removed = [];
105802
106174
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
105803
- const pluginDir = join72(cacheRoot, MARKETPLACE_NAME, pluginName);
105804
- if (!existsSync45(pluginDir))
106175
+ const pluginDir = join73(cacheRoot, MARKETPLACE_NAME, pluginName);
106176
+ if (!existsSync46(pluginDir))
105805
106177
  continue;
105806
106178
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
105807
106179
  if (!dryRun) {
@@ -105817,11 +106189,11 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
105817
106189
  }
105818
106190
  }
105819
106191
  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);
106192
+ const manifest = await readFile55(join73(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
105821
106193
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
105822
106194
  if (!currentVersion)
105823
106195
  return;
105824
- const pluginDir = join72(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
106196
+ const pluginDir = join73(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
105825
106197
  const staleVersions = (await readdir22(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
105826
106198
  if (staleVersions.length === 0)
105827
106199
  return;
@@ -105831,7 +106203,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
105831
106203
  status: dryRun ? "planned" : "ran"
105832
106204
  });
105833
106205
  if (!dryRun) {
105834
- await Promise.all(staleVersions.map((version3) => rm20(join72(pluginDir, version3), { recursive: true, force: true })));
106206
+ await Promise.all(staleVersions.map((version3) => rm20(join73(pluginDir, version3), { recursive: true, force: true })));
105835
106207
  }
105836
106208
  }
105837
106209
  function enableCodexPluginConfig(content3) {
@@ -105895,8 +106267,8 @@ source = ${JSON.stringify(root2)}
105895
106267
  `;
105896
106268
  }
105897
106269
  async function ensureCodexPluginEnabled() {
105898
- const configPath = join72(codexHome(), "config.toml");
105899
- await mkdir32(dirname41(configPath), { recursive: true });
106270
+ const configPath = join73(codexHome(), "config.toml");
106271
+ await mkdir32(dirname42(configPath), { recursive: true });
105900
106272
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105901
106273
  const next = enableCodexPluginConfig(current2);
105902
106274
  if (next !== current2) {
@@ -105904,8 +106276,8 @@ async function ensureCodexPluginEnabled() {
105904
106276
  }
105905
106277
  }
105906
106278
  async function ensureCodexLocalMarketplace(root2) {
105907
- const configPath = join72(codexHome(), "config.toml");
105908
- await mkdir32(dirname41(configPath), { recursive: true });
106279
+ const configPath = join73(codexHome(), "config.toml");
106280
+ await mkdir32(dirname42(configPath), { recursive: true });
105909
106281
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105910
106282
  const next = upsertCodexLocalMarketplaceConfig(current2, root2);
105911
106283
  if (next !== current2) {
@@ -105913,7 +106285,7 @@ async function ensureCodexLocalMarketplace(root2) {
105913
106285
  }
105914
106286
  }
105915
106287
  async function codexPluginVersion(root2) {
105916
- const manifestPath = join72(root2, "codex", ".codex-plugin", "plugin.json");
106288
+ const manifestPath = join73(root2, "codex", ".codex-plugin", "plugin.json");
105917
106289
  const manifest = JSON.parse(await readFile55(manifestPath, "utf8"));
105918
106290
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
105919
106291
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
@@ -105921,10 +106293,10 @@ async function codexPluginVersion(root2) {
105921
106293
  return manifest.version;
105922
106294
  }
105923
106295
  function codexPluginCacheDir(version3) {
105924
- return join72(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
106296
+ return join73(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
105925
106297
  }
105926
106298
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105927
- const source2 = join72(root2, "codex");
106299
+ const source2 = join73(root2, "codex");
105928
106300
  const target = codexPluginCacheDir(version3);
105929
106301
  steps.push({
105930
106302
  agent: "codex",
@@ -105933,12 +106305,12 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105933
106305
  });
105934
106306
  if (dryRun)
105935
106307
  return;
105936
- await mkdir32(dirname41(target), { recursive: true });
106308
+ await mkdir32(dirname42(target), { recursive: true });
105937
106309
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
105938
106310
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
105939
106311
  await rm20(temporary, { recursive: true, force: true });
105940
106312
  await cp(source2, temporary, { recursive: true, force: true });
105941
- const hadPrevious = existsSync45(target);
106313
+ const hadPrevious = existsSync46(target);
105942
106314
  try {
105943
106315
  if (hadPrevious)
105944
106316
  await rename5(target, previous3);
@@ -105947,7 +106319,7 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105947
106319
  await rm20(previous3, { recursive: true, force: true });
105948
106320
  } catch (error) {
105949
106321
  await rm20(temporary, { recursive: true, force: true });
105950
- if (hadPrevious && !existsSync45(target) && existsSync45(previous3))
106322
+ if (hadPrevious && !existsSync46(target) && existsSync46(previous3))
105951
106323
  await rename5(previous3, target);
105952
106324
  throw error;
105953
106325
  }
@@ -105982,12 +106354,12 @@ async function installCodex(root2, dryRun, steps) {
105982
106354
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
105983
106355
  steps.push({
105984
106356
  agent: "codex",
105985
- command: `ensure ${shellQuote9(join72(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
106357
+ command: `ensure ${shellQuote9(join73(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
105986
106358
  status: dryRun ? "planned" : "ran"
105987
106359
  });
105988
106360
  steps.push({
105989
106361
  agent: "codex",
105990
- command: `ensure ${shellQuote9(join72(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
106362
+ command: `ensure ${shellQuote9(join73(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
105991
106363
  status: dryRun ? "planned" : "ran"
105992
106364
  });
105993
106365
  if (dryRun) {
@@ -106098,8 +106470,75 @@ function formatPluginInstallResult(result) {
106098
106470
  });
106099
106471
  }
106100
106472
 
106473
+ // src/registerPluginCommands.ts
106474
+ function registerPluginCommands(program2) {
106475
+ const plugin = program2.command("plugin").description("Install or inspect global Context agent plugins");
106476
+ plugin.command("path").description("Print the bundled plugin marketplace root used by `context plugin install`").action(async () => {
106477
+ process.stdout.write(formatPluginPathResult(await runPluginPathCommand()));
106478
+ });
106479
+ 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) => {
106480
+ const agent = pluginAgentOption(options.agent);
106481
+ process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
106482
+ });
106483
+ 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) => {
106484
+ const agent = pluginAgentOption(options.agent);
106485
+ const result = await runPluginInstallCommand({
106486
+ agent,
106487
+ dryRun: options.dryRun === true
106488
+ });
106489
+ process.stdout.write(formatPluginInstallResult(result));
106490
+ });
106491
+ }
106492
+
106493
+ // src/registerPackageCommands.ts
106494
+ init_cliFeedback();
106495
+ init_errors();
106496
+ init_packageTemplateReview();
106497
+ init_workspace();
106498
+ init_exitCode();
106499
+ function registerPackageCommands(program2) {
106500
+ const packageCommand = program2.command("package").description("Inspect or resolve package output configuration");
106501
+ const packageTemplate = packageCommand.command("template").description("Manage package template review state");
106502
+ 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) => {
106503
+ if (packageName === undefined === (options.all !== true)) {
106504
+ throw new ContextError(ExitCode.UserError, "provide one package name or --all", { category: ErrorCategory.UserInputInvalid });
106505
+ }
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
+ const found = findContextProjectRoot(process.cwd());
106512
+ if (!found) {
106513
+ throw new ContextError(ExitCode.WorkspaceStateError, "package template acceptance requires a context project workspace", { category: ErrorCategory.WorkspaceNotFound });
106514
+ }
106515
+ const result = await acceptStarterPackageTemplates({
106516
+ projectRoot: found.projectRoot,
106517
+ ...packageName === undefined ? {} : { packageNames: [packageName] }
106518
+ });
106519
+ if (options.format === "json") {
106520
+ process.stdout.write(`${JSON.stringify({
106521
+ action: "package-template-accepted",
106522
+ ...result,
106523
+ next_action: {
106524
+ kind: "reevaluate-workspace",
106525
+ command: "context status --format json"
106526
+ }
106527
+ }, null, 2)}
106528
+ `);
106529
+ } else {
106530
+ process.stdout.write(formatFeedback({
106531
+ symbol: "✓",
106532
+ action: "accepted",
106533
+ subject: result.accepted.join(", ") || "package templates",
106534
+ headline: "starter package template",
106535
+ body: result.alreadyResolved.length === 0 ? [] : [`already resolved: ${result.alreadyResolved.join(", ")}`]
106536
+ }));
106537
+ }
106538
+ });
106539
+ }
106540
+
106101
106541
  // src/cli.ts
106102
- init_debugTrace();
106103
106542
  var TOP_LEVEL_COMMANDS = new Set([
106104
106543
  "init",
106105
106544
  "plugin",
@@ -106135,14 +106574,14 @@ function inferErrorCategory(message) {
106135
106574
  }
106136
106575
  function readPackageVersion() {
106137
106576
  try {
106138
- let dir = dirname42(fileURLToPath9(import.meta.url));
106577
+ let dir = dirname43(fileURLToPath10(import.meta.url));
106139
106578
  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"));
106579
+ const pkg = join74(dir, "package.json");
106580
+ if (existsSync47(pkg)) {
106581
+ const parsed = JSON.parse(readFileSync10(pkg, "utf8"));
106143
106582
  return parsed.version ?? "unknown";
106144
106583
  }
106145
- const parent = dirname42(dir);
106584
+ const parent = dirname43(dir);
106146
106585
  if (parent === dir)
106147
106586
  break;
106148
106587
  dir = parent;
@@ -106152,21 +106591,21 @@ function readPackageVersion() {
106152
106591
  }
106153
106592
  function readQuickstartPath() {
106154
106593
  try {
106155
- let dir = dirname42(fileURLToPath9(import.meta.url));
106594
+ let dir = dirname43(fileURLToPath10(import.meta.url));
106156
106595
  for (let i2 = 0;i2 < 8; i2++) {
106157
- const candidate = join73(dir, "docs", "quickstart.md");
106158
- if (existsSync46(candidate))
106596
+ const candidate = join74(dir, "docs", "quickstart.md");
106597
+ if (existsSync47(candidate))
106159
106598
  return candidate;
106160
- const pkg = join73(dir, "package.json");
106161
- if (existsSync46(pkg))
106599
+ const pkg = join74(dir, "package.json");
106600
+ if (existsSync47(pkg))
106162
106601
  return candidate;
106163
- const parent = dirname42(dir);
106602
+ const parent = dirname43(dir);
106164
106603
  if (parent === dir)
106165
106604
  break;
106166
106605
  dir = parent;
106167
106606
  }
106168
106607
  } catch {}
106169
- return join73(dirname42(fileURLToPath9(import.meta.url)), "docs", "quickstart.md");
106608
+ return join74(dirname43(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
106170
106609
  }
106171
106610
  var GREEN = "\x1B[32m";
106172
106611
  var RESET = "\x1B[0m";
@@ -106251,94 +106690,12 @@ function createCliProgram() {
106251
106690
  });
106252
106691
  const baseHelpInformation = program2.helpInformation.bind(program2);
106253
106692
  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");
106693
+ registerProjectInitCommand(program2);
106694
+ registerPluginCommands(program2);
106267
106695
  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
106696
  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
- });
106697
+ registerPackageCommands(program2);
106698
+ registerProjectStatusCommand(program2);
106342
106699
  registerProjectRunCommand(program2, import.meta.url);
106343
106700
  const review = program2.command("review").description("Review draft project candidates and apply approval decisions");
106344
106701
  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 +106843,9 @@ function createCliProgram() {
106486
106843
  format: options.format === "json" ? "json" : "text"
106487
106844
  });
106488
106845
  });
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
- });
106846
+ registerProjectCloseAndBuildCommands(program2);
106522
106847
  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
- });
106848
+ registerProjectVerifyCommand(program2);
106553
106849
  const cleanCacheAction = async (options) => {
106554
106850
  const dryRun = options.dryRun === true;
106555
106851
  await runDoctorCleanClaudePluginCache({ dryRun });
@@ -106581,10 +106877,12 @@ function createCliProgram() {
106581
106877
  return program2;
106582
106878
  }
106583
106879
  async function cli_main(argv = process.argv) {
106584
- await withDebugCliInvocation(argv, async () => {
106585
- assertKnownTopLevelCommand(argv);
106586
- const program2 = createCliProgram();
106587
- await program2.parseAsync(argv);
106880
+ await withContextRuntimeEventDelivery(async () => {
106881
+ await withDebugCliInvocation(argv, async () => {
106882
+ assertKnownTopLevelCommand(argv);
106883
+ const program2 = createCliProgram();
106884
+ await program2.parseAsync(argv);
106885
+ });
106588
106886
  });
106589
106887
  }
106590
106888
  function isDirectCliInvocation(metaUrl, argv1) {