@c4a/context-cli 0.6.4 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -17720,17 +17720,17 @@ var init_writeLock = __esm(() => {
17720
17720
 
17721
17721
  // src/project/packageTemplateReview.ts
17722
17722
  import { createHash as createHash12 } from "node:crypto";
17723
- import { existsSync as existsSync14 } from "node:fs";
17723
+ import { existsSync as existsSync15 } from "node:fs";
17724
17724
  import { mkdir as mkdir13, readFile as readFile20, readdir as readdir8, writeFile as writeFile9 } from "node:fs/promises";
17725
- import { dirname as dirname17, join as join24, relative as relative10, resolve as resolve14 } from "node:path";
17725
+ import { dirname as dirname18, join as join25, relative as relative10, resolve as resolve14 } from "node:path";
17726
17726
  async function templateFiles(root) {
17727
- if (!existsSync14(root))
17727
+ if (!existsSync15(root))
17728
17728
  return [];
17729
17729
  const files = [];
17730
17730
  const visit2 = async (dir) => {
17731
17731
  const entries = await readdir8(dir, { withFileTypes: true });
17732
17732
  for (const entry of entries) {
17733
- const absolutePath = join24(dir, entry.name);
17733
+ const absolutePath = join25(dir, entry.name);
17734
17734
  if (entry.isDirectory()) {
17735
17735
  await visit2(absolutePath);
17736
17736
  continue;
@@ -17757,8 +17757,8 @@ function isMarker(value) {
17757
17757
  return marker.schema === PACKAGE_TEMPLATE_REVIEW_SCHEMA && /^sha256:[a-f0-9]{64}$/u.test(marker.starter_digest ?? "") && (marker.disposition === "review-required" || marker.disposition === "starter-accepted");
17758
17758
  }
17759
17759
  async function readMarker(templateRoot) {
17760
- const markerPath = join24(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17761
- if (!existsSync14(markerPath))
17760
+ const markerPath = join25(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17761
+ if (!existsSync15(markerPath))
17762
17762
  return null;
17763
17763
  try {
17764
17764
  const parsed = JSON.parse(await readFile20(markerPath, "utf8"));
@@ -17768,15 +17768,15 @@ async function readMarker(templateRoot) {
17768
17768
  }
17769
17769
  }
17770
17770
  async function writeStarterTemplateReviewMarker(templateRoot) {
17771
- const markerPath = join24(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17772
- if (existsSync14(markerPath))
17771
+ const markerPath = join25(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
17772
+ if (existsSync15(markerPath))
17773
17773
  return false;
17774
17774
  const marker = {
17775
17775
  schema: PACKAGE_TEMPLATE_REVIEW_SCHEMA,
17776
17776
  starter_digest: await templateDigest(templateRoot),
17777
17777
  disposition: "review-required"
17778
17778
  };
17779
- await mkdir13(dirname17(markerPath), { recursive: true });
17779
+ await mkdir13(dirname18(markerPath), { recursive: true });
17780
17780
  await writeFile9(markerPath, `${JSON.stringify(marker, null, 2)}
17781
17781
  `, "utf8");
17782
17782
  return true;
@@ -17796,7 +17796,7 @@ async function inspectPackageTemplateReview(projectRoot, pkg) {
17796
17796
  packageName: pkg.name,
17797
17797
  templatePath: pkg.template.path,
17798
17798
  state: "invalid",
17799
- diagnostic: `${join24(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
17799
+ diagnostic: `${join25(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
17800
17800
  };
17801
17801
  }
17802
17802
  const currentDigest = await templateDigest(templateRoot);
@@ -17837,8 +17837,8 @@ async function acceptStarterPackageTemplates(input) {
17837
17837
  alreadyResolved.push(pkg.name);
17838
17838
  continue;
17839
17839
  }
17840
- const markerPath = join24(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
17841
- const marker = await readMarker(join24(input.projectRoot, pkg.template.path));
17840
+ const markerPath = join25(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
17841
+ const marker = await readMarker(join25(input.projectRoot, pkg.template.path));
17842
17842
  if (marker === null || marker === "invalid") {
17843
17843
  throw new ContextError(ExitCode.WorkspaceStateError, "package template review marker changed before acceptance", {
17844
17844
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -17866,6 +17866,7 @@ var init_packageTemplateReview = __esm(() => {
17866
17866
  // src/project/workspace.ts
17867
17867
  var exports_workspace = {};
17868
17868
  __export(exports_workspace, {
17869
+ resolveContextProjectInitTarget: () => resolveContextProjectInitTarget,
17869
17870
  projectLanguage: () => projectLanguage,
17870
17871
  loadContextProjectModule: () => loadContextProjectModule,
17871
17872
  isContextProjectRoot: () => isContextProjectRoot,
@@ -17876,30 +17877,30 @@ __export(exports_workspace, {
17876
17877
  assertContextStatusWorkspaceAllowed: () => assertContextStatusWorkspaceAllowed,
17877
17878
  PROJECT_LANGUAGES: () => PROJECT_LANGUAGES
17878
17879
  });
17879
- import { existsSync as existsSync15, readFileSync as readFileSync5 } from "node:fs";
17880
+ import { existsSync as existsSync16, readFileSync as readFileSync6 } from "node:fs";
17880
17881
  import { mkdir as mkdir14, readFile as readFile21, readdir as readdir9, writeFile as writeFile10 } from "node:fs/promises";
17881
17882
  import { createRequire as createRequire3 } from "node:module";
17882
- import { basename as basename5, dirname as dirname18, isAbsolute as isAbsolute6, join as join25, parse as parse6, relative as relative11, resolve as resolve15 } from "node:path";
17883
- import { fileURLToPath as fileURLToPath5 } from "node:url";
17883
+ import { basename as basename5, dirname as dirname19, isAbsolute as isAbsolute6, join as join26, parse as parse6, relative as relative11, resolve as resolve15 } from "node:path";
17884
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
17884
17885
  import { createJiti } from "jiti";
17885
- function isRecord12(value) {
17886
+ function isRecord13(value) {
17886
17887
  return value !== null && typeof value === "object" && !Array.isArray(value);
17887
17888
  }
17888
17889
  function readPackageJson(root) {
17889
- const packagePath = join25(root, "package.json");
17890
- if (!existsSync15(packagePath))
17890
+ const packagePath = join26(root, "package.json");
17891
+ if (!existsSync16(packagePath))
17891
17892
  return null;
17892
17893
  try {
17893
- const parsed = JSON.parse(readFileSync5(packagePath, "utf8"));
17894
- return isRecord12(parsed) ? parsed : null;
17894
+ const parsed = JSON.parse(readFileSync6(packagePath, "utf8"));
17895
+ return isRecord13(parsed) ? parsed : null;
17895
17896
  } catch {
17896
17897
  return null;
17897
17898
  }
17898
17899
  }
17899
17900
  function readPackageJsonFile(packageJsonPath) {
17900
17901
  try {
17901
- const parsed = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
17902
- return isRecord12(parsed) ? parsed : null;
17902
+ const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
17903
+ return isRecord13(parsed) ? parsed : null;
17903
17904
  } catch {
17904
17905
  return null;
17905
17906
  }
@@ -17910,22 +17911,22 @@ function resolveExportImportTarget(packageJsonPath) {
17910
17911
  return null;
17911
17912
  const exportsField = parsed.exports;
17912
17913
  if (typeof exportsField === "string") {
17913
- return join25(dirname18(packageJsonPath), exportsField);
17914
+ return join26(dirname19(packageJsonPath), exportsField);
17914
17915
  }
17915
- if (isRecord12(exportsField)) {
17916
+ if (isRecord13(exportsField)) {
17916
17917
  const rootExport = exportsField["."];
17917
17918
  if (typeof rootExport === "string") {
17918
- return join25(dirname18(packageJsonPath), rootExport);
17919
+ return join26(dirname19(packageJsonPath), rootExport);
17919
17920
  }
17920
- if (isRecord12(rootExport) && typeof rootExport.import === "string") {
17921
- return join25(dirname18(packageJsonPath), rootExport.import);
17921
+ if (isRecord13(rootExport) && typeof rootExport.import === "string") {
17922
+ return join26(dirname19(packageJsonPath), rootExport.import);
17922
17923
  }
17923
17924
  }
17924
17925
  if (typeof parsed.module === "string") {
17925
- return join25(dirname18(packageJsonPath), parsed.module);
17926
+ return join26(dirname19(packageJsonPath), parsed.module);
17926
17927
  }
17927
17928
  if (typeof parsed.main === "string") {
17928
- return join25(dirname18(packageJsonPath), parsed.main);
17929
+ return join26(dirname19(packageJsonPath), parsed.main);
17929
17930
  }
17930
17931
  return null;
17931
17932
  }
@@ -17941,16 +17942,16 @@ function resolveContextSdkImportAlias(entryPath) {
17941
17942
  return "@c4a/context";
17942
17943
  }
17943
17944
  function readCurrentPackageVersion() {
17944
- let dir = dirname18(fileURLToPath5(import.meta.url));
17945
+ let dir = dirname19(fileURLToPath6(import.meta.url));
17945
17946
  for (let index2 = 0;index2 < 8; index2++) {
17946
- const packagePath = join25(dir, "package.json");
17947
- if (existsSync15(packagePath)) {
17947
+ const packagePath = join26(dir, "package.json");
17948
+ if (existsSync16(packagePath)) {
17948
17949
  const parsed = readPackageJson(dir);
17949
17950
  if (typeof parsed?.version === "string" && parsed.version.trim().length > 0) {
17950
17951
  return parsed.version;
17951
17952
  }
17952
17953
  }
17953
- const parent = dirname18(dir);
17954
+ const parent = dirname19(dir);
17954
17955
  if (parent === dir)
17955
17956
  break;
17956
17957
  dir = parent;
@@ -17959,7 +17960,7 @@ function readCurrentPackageVersion() {
17959
17960
  }
17960
17961
  function readContextProjectPackage(root) {
17961
17962
  const parsed = readPackageJson(root);
17962
- const context = isRecord12(parsed?.context) ? parsed.context : null;
17963
+ const context = isRecord13(parsed?.context) ? parsed.context : null;
17963
17964
  if (context?.project !== true || typeof context.entry !== "string" || context.entry.trim().length === 0) {
17964
17965
  return null;
17965
17966
  }
@@ -17970,7 +17971,7 @@ function readContextProjectPackage(root) {
17970
17971
  }
17971
17972
  function readContextWorkspaceDir(root) {
17972
17973
  const parsed = readPackageJson(root);
17973
- const context = isRecord12(parsed?.context) ? parsed.context : null;
17974
+ const context = isRecord13(parsed?.context) ? parsed.context : null;
17974
17975
  const workspaceDir = context?.workspaceDir;
17975
17976
  if (typeof workspaceDir !== "string" || workspaceDir.trim().length === 0)
17976
17977
  return null;
@@ -17978,7 +17979,7 @@ function readContextWorkspaceDir(root) {
17978
17979
  }
17979
17980
  function readContextProjectLanguage(root) {
17980
17981
  const parsed = readPackageJson(root);
17981
- const context = isRecord12(parsed?.context) ? parsed.context : null;
17982
+ const context = isRecord13(parsed?.context) ? parsed.context : null;
17982
17983
  return context?.language === "en" || context?.language === "zh-CN" ? context.language : undefined;
17983
17984
  }
17984
17985
  function isSameOrChildPath(path3, parent) {
@@ -17999,13 +18000,13 @@ function findContextWorkspaceExpectation(startDir = process.cwd()) {
17999
18000
  workspaceDir,
18000
18001
  workspaceRoot,
18001
18002
  cwd,
18002
- exists: existsSync15(workspaceRoot)
18003
+ exists: existsSync16(workspaceRoot)
18003
18004
  };
18004
18005
  }
18005
18006
  }
18006
18007
  if (dir === root)
18007
18008
  return null;
18008
- const parent = dirname18(dir);
18009
+ const parent = dirname19(dir);
18009
18010
  if (parent === dir)
18010
18011
  return null;
18011
18012
  dir = parent;
@@ -18039,7 +18040,7 @@ function findContextProjectRoot(startDir = process.cwd()) {
18039
18040
  return { projectRoot: dir };
18040
18041
  if (dir === root)
18041
18042
  return null;
18042
- const parent = dirname18(dir);
18043
+ const parent = dirname19(dir);
18043
18044
  if (parent === dir)
18044
18045
  return null;
18045
18046
  dir = parent;
@@ -18049,6 +18050,9 @@ function normalizeProjectDir(cwd, projectDir) {
18049
18050
  const raw = projectDir?.trim() || DEFAULT_PROJECT_DIR;
18050
18051
  return raw === "." ? resolve15(cwd) : resolve15(cwd, raw);
18051
18052
  }
18053
+ function resolveContextProjectInitTarget(cwd, projectDir) {
18054
+ return normalizeProjectDir(cwd, projectDir);
18055
+ }
18052
18056
  function slugifyName(value) {
18053
18057
  const slug = value.trim().toLowerCase().replace(/[^a-z0-9._-]+/gu, "-").replace(/^-+|-+$/gu, "");
18054
18058
  return slug.length > 0 ? slug : "context";
@@ -18078,7 +18082,7 @@ function initCommand(input, allowNonempty) {
18078
18082
  return args.map(shellQuote3).join(" ");
18079
18083
  }
18080
18084
  async function assertInitTargetAllowed(input, projectRoot) {
18081
- if (!existsSync15(projectRoot) || isContextProjectRoot(projectRoot) || input.allowNonempty === true)
18085
+ if (!existsSync16(projectRoot) || isContextProjectRoot(projectRoot) || input.allowNonempty === true)
18082
18086
  return;
18083
18087
  const entries = (await readdir9(projectRoot)).sort();
18084
18088
  if (entries.length === 0)
@@ -18102,11 +18106,11 @@ async function assertInitTargetAllowed(input, projectRoot) {
18102
18106
  });
18103
18107
  }
18104
18108
  async function writeIfMissing(path3, content3, result) {
18105
- if (existsSync15(path3)) {
18109
+ if (existsSync16(path3)) {
18106
18110
  result.kept.push(path3);
18107
18111
  return;
18108
18112
  }
18109
- await mkdir14(dirname18(path3), { recursive: true });
18113
+ await mkdir14(dirname19(path3), { recursive: true });
18110
18114
  await writeFile10(path3, content3, "utf8");
18111
18115
  result.created.push(path3);
18112
18116
  }
@@ -18114,7 +18118,7 @@ async function listStaticTemplateFiles(root, dir = root) {
18114
18118
  const entries = await readdir9(dir, { withFileTypes: true });
18115
18119
  const files = [];
18116
18120
  for (const entry of entries) {
18117
- const absolutePath = join25(dir, entry.name);
18121
+ const absolutePath = join26(dir, entry.name);
18118
18122
  if (entry.isDirectory()) {
18119
18123
  files.push(...await listStaticTemplateFiles(root, absolutePath));
18120
18124
  continue;
@@ -18131,8 +18135,8 @@ async function listStaticTemplateFiles(root, dir = root) {
18131
18135
  function resolveContextPackageTemplatesRoot() {
18132
18136
  try {
18133
18137
  const packageJsonPath = createRequire3(import.meta.url).resolve("@c4a/context/package.json");
18134
- const templateRoot = join25(dirname18(packageJsonPath), "templates", "package-templates");
18135
- if (existsSync15(templateRoot))
18138
+ const templateRoot = join26(dirname19(packageJsonPath), "templates", "package-templates");
18139
+ if (existsSync16(templateRoot))
18136
18140
  return templateRoot;
18137
18141
  } catch {}
18138
18142
  throw new ContextError(ExitCode.WorkspaceStateError, "missing @c4a/context package templates", {
@@ -18143,8 +18147,8 @@ function resolveContextPackageTemplatesRoot() {
18143
18147
  }
18144
18148
  async function writeDefaultPackageTemplates(projectRoot, result, language) {
18145
18149
  const defaultRoot = resolveContextPackageTemplatesRoot();
18146
- const templateRoot = language === "zh-CN" ? join25(dirname18(defaultRoot), "package-templates.zh-CN") : defaultRoot;
18147
- if (!existsSync15(templateRoot)) {
18150
+ const templateRoot = language === "zh-CN" ? join26(dirname19(defaultRoot), "package-templates.zh-CN") : defaultRoot;
18151
+ if (!existsSync16(templateRoot)) {
18148
18152
  throw new ContextError(ExitCode.WorkspaceStateError, `missing ${language} @c4a/context package templates`, {
18149
18153
  category: ErrorCategory.WorkspaceStateInvalid,
18150
18154
  path: templateRoot,
@@ -18153,21 +18157,21 @@ async function writeDefaultPackageTemplates(projectRoot, result, language) {
18153
18157
  }
18154
18158
  const files = await listStaticTemplateFiles(templateRoot);
18155
18159
  for (const file of files) {
18156
- await writeIfMissing(join25(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile21(file.absolutePath, "utf8"), result);
18160
+ await writeIfMissing(join26(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile21(file.absolutePath, "utf8"), result);
18157
18161
  }
18158
18162
  const templateKinds = [...new Set(files.map((file) => file.relativePath.split("/")[0]).filter((value) => value !== undefined && value.length > 0))];
18159
18163
  for (const templateKind of templateKinds) {
18160
- const root = join25(projectRoot, "src", "package-templates", templateKind);
18164
+ const root = join26(projectRoot, "src", "package-templates", templateKind);
18161
18165
  if (await writeStarterTemplateReviewMarker(root)) {
18162
- result.created.push(join25(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18166
+ result.created.push(join26(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18163
18167
  } else {
18164
- result.kept.push(join25(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18168
+ result.kept.push(join26(root, PACKAGE_TEMPLATE_REVIEW_FILE));
18165
18169
  }
18166
18170
  }
18167
18171
  }
18168
18172
  function resolveLocalSdkDependency() {
18169
18173
  const packageJsonPath = createRequire3(import.meta.url).resolve("@c4a/context/package.json");
18170
- return `file:${dirname18(packageJsonPath)}`;
18174
+ return `file:${dirname19(packageJsonPath)}`;
18171
18175
  }
18172
18176
  function resolveSdkDependency(dev, version3) {
18173
18177
  return dev === true ? resolveLocalSdkDependency() : version3;
@@ -18465,20 +18469,20 @@ async function initContextProject(input) {
18465
18469
  kept: []
18466
18470
  };
18467
18471
  for (const dir of PROJECT_DIRS) {
18468
- await mkdir14(join25(projectRoot, dir), { recursive: true });
18472
+ await mkdir14(join26(projectRoot, dir), { recursive: true });
18469
18473
  }
18470
- await mkdir14(join25(projectRoot, "sources", "repo"), { recursive: true });
18471
- await mkdir14(join25(projectRoot, "sources", "file"), { recursive: true });
18472
- await mkdir14(join25(projectRoot, "sources", "lark"), { recursive: true });
18473
- await writeIfMissing(join25(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
18474
- await writeIfMissing(join25(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
18474
+ await mkdir14(join26(projectRoot, "sources", "repo"), { recursive: true });
18475
+ await mkdir14(join26(projectRoot, "sources", "file"), { recursive: true });
18476
+ await mkdir14(join26(projectRoot, "sources", "lark"), { recursive: true });
18477
+ await writeIfMissing(join26(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
18478
+ await writeIfMissing(join26(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
18475
18479
  await writeDefaultPackageTemplates(projectRoot, result, language);
18476
- await writeIfMissing(join25(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
18477
- await writeIfMissing(join25(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
18478
- await writeIfMissing(join25(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
18479
- await writeIfMissing(join25(projectRoot, ".gitignore"), renderGitignore(), result);
18480
- await writeIfMissing(join25(projectRoot, "README.md"), renderReadme(projectName, language), result);
18481
- await writeIfMissing(join25(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
18480
+ await writeIfMissing(join26(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
18481
+ await writeIfMissing(join26(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
18482
+ await writeIfMissing(join26(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
18483
+ await writeIfMissing(join26(projectRoot, ".gitignore"), renderGitignore(), result);
18484
+ await writeIfMissing(join26(projectRoot, "README.md"), renderReadme(projectName, language), result);
18485
+ await writeIfMissing(join26(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
18482
18486
  if (input.debug === true)
18483
18487
  await enableContextDebug(projectRoot, "init");
18484
18488
  return result;
@@ -18492,7 +18496,7 @@ async function loadContextProjectModule(root) {
18492
18496
  next: "Ensure package.json declares context.project=true and context.entry points to src/index.ts, then rerun the command."
18493
18497
  });
18494
18498
  }
18495
- const entryPath = join25(root, projectConfig.entry);
18499
+ const entryPath = join26(root, projectConfig.entry);
18496
18500
  const jiti = createJiti(entryPath, {
18497
18501
  alias: {
18498
18502
  "@c4a/context": resolveContextSdkImportAlias(entryPath)
@@ -18502,7 +18506,7 @@ async function loadContextProjectModule(root) {
18502
18506
  moduleCache: false
18503
18507
  });
18504
18508
  const loadedProject = await jiti.import(entryPath, { default: true });
18505
- if (!isRecord12(loadedProject) || loadedProject.kind !== "context.project") {
18509
+ if (!isRecord13(loadedProject) || loadedProject.kind !== "context.project") {
18506
18510
  throw new ContextError(ExitCode.WorkspaceStateError, "src/index.ts default export must be a @c4a/context project module", {
18507
18511
  category: ErrorCategory.SchemaInvalid,
18508
18512
  path: projectConfig.entry,
@@ -21518,7 +21522,7 @@ var require_util2 = __commonJS((exports) => {
21518
21522
  return path4;
21519
21523
  }
21520
21524
  exports.normalize = normalize;
21521
- function join46(aRoot, aPath) {
21525
+ function join47(aRoot, aPath) {
21522
21526
  if (aRoot === "") {
21523
21527
  aRoot = ".";
21524
21528
  }
@@ -21550,7 +21554,7 @@ var require_util2 = __commonJS((exports) => {
21550
21554
  }
21551
21555
  return joined;
21552
21556
  }
21553
- exports.join = join46;
21557
+ exports.join = join47;
21554
21558
  exports.isAbsolute = function(aPath) {
21555
21559
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
21556
21560
  };
@@ -21723,7 +21727,7 @@ var require_util2 = __commonJS((exports) => {
21723
21727
  parsed.path = parsed.path.substring(0, index2 + 1);
21724
21728
  }
21725
21729
  }
21726
- sourceURL = join46(urlGenerate(parsed), sourceURL);
21730
+ sourceURL = join47(urlGenerate(parsed), sourceURL);
21727
21731
  }
21728
21732
  return normalize(sourceURL);
21729
21733
  }
@@ -24123,9 +24127,9 @@ var require_lib = __commonJS((exports, module) => {
24123
24127
  });
24124
24128
 
24125
24129
  // src/cli.ts
24126
- import { existsSync as existsSync46, readFileSync as readFileSync9, realpathSync } from "node:fs";
24127
- import { dirname as dirname42, join as join73 } from "node:path";
24128
- import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL4 } from "node:url";
24130
+ import { existsSync as existsSync47, readFileSync as readFileSync10, realpathSync } from "node:fs";
24131
+ import { dirname as dirname43, join as join74 } from "node:path";
24132
+ import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL4 } from "node:url";
24129
24133
 
24130
24134
  // ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
24131
24135
  var import__ = __toESM(require_commander(), 1);
@@ -24189,7 +24193,7 @@ function mergedWorkflowAuthorities(...values) {
24189
24193
  }
24190
24194
 
24191
24195
  // src/project/workflow/workflowResource.ts
24192
- import { join as join55 } from "node:path";
24196
+ import { join as join56 } from "node:path";
24193
24197
 
24194
24198
  // ../../node_modules/.bun/@c4a+agent-graph@0.2.5/node_modules/@c4a/agent-graph/dist/index.js
24195
24199
  import { createRequire as createRequire2 } from "node:module";
@@ -40402,7 +40406,7 @@ init_errors();
40402
40406
  init_exitCode();
40403
40407
 
40404
40408
  // src/project/status.ts
40405
- import { join as join54 } from "node:path";
40409
+ import { join as join55 } from "node:path";
40406
40410
 
40407
40411
  // ../context/src/contracts.ts
40408
40412
  var DEFAULT_PACKAGE_NAVIGATION = {
@@ -45289,9 +45293,9 @@ function resolveStructureCompileRoute(input) {
45289
45293
  // src/project/statusReaders.ts
45290
45294
  init_errors();
45291
45295
  var import_yaml29 = __toESM(require_dist3(), 1);
45292
- import { existsSync as existsSync35, readFileSync as readFileSync7 } from "node:fs";
45296
+ import { existsSync as existsSync36, readFileSync as readFileSync8 } from "node:fs";
45293
45297
  import { readdir as readdir16 } from "node:fs/promises";
45294
- import { join as join52 } from "node:path";
45298
+ import { join as join53 } from "node:path";
45295
45299
 
45296
45300
  // src/project/documentCapture.ts
45297
45301
  import { createHash as createHash4 } from "node:crypto";
@@ -47498,12 +47502,22 @@ var loadSourceInfo = async (modulePath, fs) => {
47498
47502
  content: { raw: await fs.readFile(GO_MOD) }
47499
47503
  });
47500
47504
  }
47505
+ const detectedLanguages = [
47506
+ ...manifests.some((manifest) => manifest.type === GO_MOD) ? ["go"] : [],
47507
+ ...manifests.some((manifest) => manifest.type === PACKAGE_JSON) ? ["typescript"] : []
47508
+ ];
47501
47509
  return {
47502
47510
  path: normalizeRelativePath(modulePath),
47503
47511
  manifests,
47504
- ...manifests.some((manifest) => manifest.type === GO_MOD) ? { language: "go" } : manifests.some((manifest) => manifest.type === PACKAGE_JSON) ? { language: "typescript" } : {}
47512
+ ...detectedLanguages.length === 1 ? { language: detectedLanguages[0] } : {}
47505
47513
  };
47506
47514
  };
47515
+ function manifestForPlugin(source2, plugin) {
47516
+ if (plugin.manifestTypes !== undefined) {
47517
+ return source2.manifests.find((manifest) => plugin.manifestTypes?.includes(manifest.type));
47518
+ }
47519
+ return source2.manifests.length === 1 ? source2.manifests[0] : undefined;
47520
+ }
47507
47521
  var prefixSymbolPaths = (symbol, modulePath) => ({
47508
47522
  ...symbol,
47509
47523
  ...symbol.file.trim() ? { file: resolveRepoRelativePath(modulePath, symbol.file) } : {},
@@ -47600,12 +47614,12 @@ var runRepositoryExtraction = async (input) => {
47600
47614
  });
47601
47615
  continue;
47602
47616
  }
47603
- const manifest = sourceInfo.manifests.find((candidate) => candidate.type === PACKAGE_JSON) ?? sourceInfo.manifests[0];
47617
+ const manifest = manifestForPlugin(sourceInfo, plugin);
47604
47618
  if (!manifest) {
47605
47619
  moduleErrors.push({
47606
47620
  module_name: module.name,
47607
47621
  module_path: module.path,
47608
- error: `Module "${module.name}" has no supported manifest for extraction`
47622
+ error: plugin.manifestTypes === undefined && sourceInfo.manifests.length > 1 ? `Extraction plugin "${plugin.id}" must declare manifestTypes for mixed-manifest module "${module.name}"` : `Module "${module.name}" has no manifest supported by extraction plugin "${plugin.id}"`
47609
47623
  });
47610
47624
  continue;
47611
47625
  }
@@ -65763,6 +65777,7 @@ class TypeScriptPlugin {
65763
65777
  id = "c4a-extract-ts";
65764
65778
  languages = ["typescript", "tsx"];
65765
65779
  packageManagers = ["npm"];
65780
+ manifestTypes = ["package.json"];
65766
65781
  #lastDetection = null;
65767
65782
  canHandle(source2) {
65768
65783
  return source2.manifests.some((manifest) => manifest.type === "package.json");
@@ -68933,20 +68948,156 @@ async function readApprovedCodegraphPages(input) {
68933
68948
  // src/project/close.ts
68934
68949
  init_cliFeedback();
68935
68950
  init_errors();
68936
- init_exitCode();
68937
68951
  var import_yaml14 = __toESM(require_dist3(), 1);
68938
- import { existsSync as existsSync21 } from "node:fs";
68952
+ import { existsSync as existsSync22 } from "node:fs";
68939
68953
  import { mkdir as mkdir17, readdir as readdir11, readFile as readFile27, writeFile as writeFile13 } from "node:fs/promises";
68940
- import { dirname as dirname21, join as join32, relative as relative13 } from "node:path";
68954
+ import { dirname as dirname22, join as join33, relative as relative13 } from "node:path";
68955
+
68956
+ // src/runtimeEvents.ts
68957
+ import { randomUUID as randomUUID2 } from "node:crypto";
68958
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
68959
+ import { spawn as spawn2 } from "node:child_process";
68960
+ import { dirname as dirname15, join as join17 } from "node:path";
68961
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
68962
+ var CONTEXT_RUNTIME_EVENT_BATCH_SCHEMA = "context.runtime-event-batch.v1";
68963
+ var CONTEXT_RUNTIME_EVENT_SINK_SCHEMA = "context.runtime-event-sink.v1";
68964
+ var activeScope;
68965
+ function isRecord8(value) {
68966
+ return value !== null && typeof value === "object" && !Array.isArray(value);
68967
+ }
68968
+ function parseContextRuntimeEventSink(value) {
68969
+ if (!isRecord8(value))
68970
+ return null;
68971
+ if (value.schema !== CONTEXT_RUNTIME_EVENT_SINK_SCHEMA || value.transport !== "command")
68972
+ return null;
68973
+ if (typeof value.command !== "string" || value.command.trim().length === 0)
68974
+ return null;
68975
+ if (!Array.isArray(value.args) || !value.args.every((arg) => typeof arg === "string"))
68976
+ return null;
68977
+ return {
68978
+ schema: CONTEXT_RUNTIME_EVENT_SINK_SCHEMA,
68979
+ transport: "command",
68980
+ command: value.command,
68981
+ args: [...value.args]
68982
+ };
68983
+ }
68984
+ function readRuntimePackageMetadata() {
68985
+ try {
68986
+ let dir = dirname15(fileURLToPath4(import.meta.url));
68987
+ for (let index2 = 0;index2 < 8; index2++) {
68988
+ const packagePath = join17(dir, "package.json");
68989
+ if (existsSync8(packagePath)) {
68990
+ const parsed = JSON.parse(readFileSync4(packagePath, "utf8"));
68991
+ if (isRecord8(parsed)) {
68992
+ return {
68993
+ contextVersion: typeof parsed.version === "string" ? parsed.version : "unknown",
68994
+ sink: parseContextRuntimeEventSink(parsed.contextRuntimeEventSink)
68995
+ };
68996
+ }
68997
+ }
68998
+ const parent = dirname15(dir);
68999
+ if (parent === dir)
69000
+ break;
69001
+ dir = parent;
69002
+ }
69003
+ } catch {}
69004
+ return { contextVersion: "unknown", sink: null };
69005
+ }
69006
+ function dispatchCommand(sink, batch, cwd) {
69007
+ return new Promise((resolve8) => {
69008
+ let settled = false;
69009
+ let timer;
69010
+ const finish = () => {
69011
+ if (settled)
69012
+ return;
69013
+ settled = true;
69014
+ if (timer !== undefined)
69015
+ clearTimeout(timer);
69016
+ resolve8();
69017
+ };
69018
+ try {
69019
+ const child = spawn2(sink.command, sink.args, {
69020
+ cwd,
69021
+ detached: true,
69022
+ env: process.env,
69023
+ shell: false,
69024
+ stdio: ["pipe", "ignore", "ignore"]
69025
+ });
69026
+ child.once("error", finish);
69027
+ child.stdin.once("error", finish);
69028
+ child.stdin.end(JSON.stringify(batch), finish);
69029
+ child.unref();
69030
+ timer = setTimeout(finish, 250);
69031
+ timer.unref();
69032
+ } catch {
69033
+ finish();
69034
+ }
69035
+ });
69036
+ }
69037
+ async function flushRuntimeEvents(scope) {
69038
+ const grouped = new Map;
69039
+ for (const queued of scope.events) {
69040
+ const events = grouped.get(queued.cwd) ?? [];
69041
+ events.push(queued.event);
69042
+ grouped.set(queued.cwd, events);
69043
+ }
69044
+ await Promise.all([...grouped.entries()].map(async ([cwd, events]) => {
69045
+ try {
69046
+ await scope.dispatch(scope.sink, {
69047
+ schema: CONTEXT_RUNTIME_EVENT_BATCH_SCHEMA,
69048
+ context_version: scope.contextVersion,
69049
+ events
69050
+ }, cwd);
69051
+ } catch {}
69052
+ }));
69053
+ }
69054
+ function queueContextRuntimeEvent(input) {
69055
+ if (activeScope === undefined)
69056
+ return;
69057
+ activeScope.events.push({
69058
+ cwd: input.cwd,
69059
+ event: {
69060
+ event_id: randomUUID2(),
69061
+ event_time: Date.now(),
69062
+ kind: input.kind,
69063
+ properties: input.properties ?? {}
69064
+ }
69065
+ });
69066
+ }
69067
+ async function withContextRuntimeEventDelivery(work, options = {}) {
69068
+ if (activeScope !== undefined || process.env.CONTEXT_RUNTIME_EVENTS_DISABLED === "1") {
69069
+ return work();
69070
+ }
69071
+ const metadata = readRuntimePackageMetadata();
69072
+ const sink = options.sink === undefined ? metadata.sink : options.sink;
69073
+ if (sink === null)
69074
+ return work();
69075
+ const scope = {
69076
+ contextVersion: options.contextVersion ?? metadata.contextVersion,
69077
+ dispatch: options.dispatch ?? dispatchCommand,
69078
+ events: [],
69079
+ sink
69080
+ };
69081
+ activeScope = scope;
69082
+ try {
69083
+ return await work();
69084
+ } finally {
69085
+ activeScope = undefined;
69086
+ await flushRuntimeEvents(scope);
69087
+ }
69088
+ }
69089
+
69090
+ // src/project/close.ts
69091
+ init_exitCode();
68941
69092
 
68942
69093
  // src/project/approvedStructureEdges.ts
68943
69094
  init_cliFeedback();
68944
69095
  init_errors();
68945
69096
  init_exitCode();
68946
69097
  var import_yaml10 = __toESM(require_dist3(), 1);
68947
- import { existsSync as existsSync10 } from "node:fs";
69098
+ import { existsSync as existsSync11 } from "node:fs";
68948
69099
  import { readFile as readFile17 } from "node:fs/promises";
68949
- import { join as join19 } from "node:path";
69100
+ import { join as join20 } from "node:path";
68950
69101
 
68951
69102
  // src/project/proseAlignTypes.ts
68952
69103
  import { createHash as createHash9 } from "node:crypto";
@@ -69003,21 +69154,21 @@ function slugify2(input, maxLen = 60) {
69003
69154
  // src/project/semanticRules.ts
69004
69155
  var import_yaml8 = __toESM(require_dist3(), 1);
69005
69156
  import { createHash as createHash8 } from "node:crypto";
69006
- import { existsSync as existsSync8, readFileSync as readFileSync4, readdirSync } from "node:fs";
69007
- import { basename as basename4, dirname as dirname15, join as join17 } from "node:path";
69008
- import { fileURLToPath as fileURLToPath4 } from "node:url";
69157
+ import { existsSync as existsSync9, readFileSync as readFileSync5, readdirSync } from "node:fs";
69158
+ import { basename as basename4, dirname as dirname16, join as join18 } from "node:path";
69159
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
69009
69160
  function sha256(value) {
69010
69161
  return `sha256:${createHash8("sha256").update(value).digest("hex")}`;
69011
69162
  }
69012
69163
  function workflowRootCandidates() {
69013
- const runtimeDir = dirname15(fileURLToPath4(import.meta.url));
69164
+ const runtimeDir = dirname16(fileURLToPath5(import.meta.url));
69014
69165
  return [
69015
- join17(runtimeDir, "providers", "context"),
69016
- join17(runtimeDir, "..", "..", "context-workflow")
69166
+ join18(runtimeDir, "providers", "context"),
69167
+ join18(runtimeDir, "..", "..", "context-workflow")
69017
69168
  ];
69018
69169
  }
69019
69170
  function semanticRuleMetadata(scope, filePath) {
69020
- const content3 = readFileSync4(filePath, "utf8").replaceAll(`\r
69171
+ const content3 = readFileSync5(filePath, "utf8").replaceAll(`\r
69021
69172
  `, `
69022
69173
  `);
69023
69174
  const end = content3.indexOf(`
@@ -69048,19 +69199,19 @@ function semanticRuleMetadata(scope, filePath) {
69048
69199
  }
69049
69200
  function semanticRuleDescriptors(scope) {
69050
69201
  for (const root of workflowRootCandidates()) {
69051
- const directory = join17(root, "resources", "semantic", scope);
69052
- if (!existsSync8(directory))
69202
+ const directory = join18(root, "resources", "semantic", scope);
69203
+ if (!existsSync9(directory))
69053
69204
  continue;
69054
- return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).sort((left, right) => left.name.localeCompare(right.name)).map((entry) => semanticRuleMetadata(scope, join17(directory, entry.name)));
69205
+ return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).sort((left, right) => left.name.localeCompare(right.name)).map((entry) => semanticRuleMetadata(scope, join18(directory, entry.name)));
69055
69206
  }
69056
69207
  throw new Error(`Context ${scope} semantic workflow resources are missing. Rebuild or reinstall @c4a/context-cli.`);
69057
69208
  }
69058
69209
  function ruleContent(rulePath) {
69059
69210
  for (const root of workflowRootCandidates()) {
69060
- const absolute = join17(root, rulePath);
69061
- if (existsSync8(absolute)) {
69211
+ const absolute = join18(root, rulePath);
69212
+ if (existsSync9(absolute)) {
69062
69213
  return {
69063
- content: readFileSync4(absolute, "utf8"),
69214
+ content: readFileSync5(absolute, "utf8"),
69064
69215
  available: true,
69065
69216
  filePath: absolute
69066
69217
  };
@@ -69473,15 +69624,15 @@ init_cliFeedback();
69473
69624
  init_errors();
69474
69625
  init_exitCode();
69475
69626
  var import_yaml9 = __toESM(require_dist3(), 1);
69476
- import { existsSync as existsSync9 } from "node:fs";
69627
+ import { existsSync as existsSync10 } from "node:fs";
69477
69628
  import { mkdir as mkdir12, readFile as readFile16, writeFile as writeFile8 } from "node:fs/promises";
69478
- import { dirname as dirname16, join as join18 } from "node:path";
69629
+ import { dirname as dirname17, join as join19 } from "node:path";
69479
69630
 
69480
69631
  // src/project/proseAlignPayloadParse.ts
69481
69632
  import { createHash as createHash10 } from "node:crypto";
69482
69633
 
69483
69634
  // src/project/proseAlignSchemaUtils.ts
69484
- function isRecord8(value) {
69635
+ function isRecord9(value) {
69485
69636
  return value !== null && typeof value === "object" && !Array.isArray(value);
69486
69637
  }
69487
69638
  function stringValue2(record, field) {
@@ -69548,7 +69699,7 @@ function parsePreferredNodes(value, diagnostics) {
69548
69699
  }
69549
69700
  const nodes = [];
69550
69701
  for (const [index2, rawNode] of value.entries()) {
69551
- if (!isRecord8(rawNode)) {
69702
+ if (!isRecord9(rawNode)) {
69552
69703
  diagnostics.push(diagnostic("error", "schema.preferred_node_object", "schema", "preferred_nodes item must be an object.", `user_or_agent_hints.preferred_nodes[${index2}]`));
69553
69704
  continue;
69554
69705
  }
@@ -69573,7 +69724,7 @@ function parsePreferredNodes(value, diagnostics) {
69573
69724
  function parseUserOrAgentHints(value, diagnostics) {
69574
69725
  if (value === undefined)
69575
69726
  return;
69576
- if (!isRecord8(value)) {
69727
+ if (!isRecord9(value)) {
69577
69728
  diagnostics.push(diagnostic("error", "schema.user_or_agent_hints_object", "schema", "user_or_agent_hints must be an object.", "user_or_agent_hints"));
69578
69729
  return;
69579
69730
  }
@@ -69776,7 +69927,7 @@ function parseNodes(value, diagnostics) {
69776
69927
  diagnostics.push(diagnostic("error", "schema.nodes_missing", "schema", "Payload must include at least one node.", "nodes"));
69777
69928
  const nodes = [];
69778
69929
  for (const [index2, rawNode] of value.entries()) {
69779
- if (!isRecord8(rawNode)) {
69930
+ if (!isRecord9(rawNode)) {
69780
69931
  diagnostics.push(diagnostic("error", "schema.node_object", "schema", `Node ${index2 + 1} must be an object.`, `nodes[${index2}]`));
69781
69932
  continue;
69782
69933
  }
@@ -69813,7 +69964,7 @@ function parseSections(input) {
69813
69964
  const sectionIds = new Set;
69814
69965
  for (const [sectionIndex, rawSection] of input.value.entries()) {
69815
69966
  const field = `views[${input.viewIndex}].sections[${sectionIndex}]`;
69816
- if (!isRecord8(rawSection)) {
69967
+ if (!isRecord9(rawSection)) {
69817
69968
  input.diagnostics.push(diagnostic("error", "schema.section_object", "schema", "Section must be an object.", field));
69818
69969
  continue;
69819
69970
  }
@@ -69915,7 +70066,7 @@ function parseViews(value, nodes, diagnostics) {
69915
70066
  const nodeByRef = new Map(nodes.map((node3) => [node3.node_ref, node3]));
69916
70067
  const views = [];
69917
70068
  for (const [index2, rawView] of value.entries()) {
69918
- if (!isRecord8(rawView)) {
70069
+ if (!isRecord9(rawView)) {
69919
70070
  diagnostics.push(diagnostic("error", "schema.view_object", "schema", `View ${index2 + 1} must be an object.`, `views[${index2}]`));
69920
70071
  continue;
69921
70072
  }
@@ -69934,7 +70085,7 @@ function parseEdges(value, diagnostics) {
69934
70085
  }
69935
70086
  const edges = [];
69936
70087
  for (const [index2, rawEdge] of value.entries()) {
69937
- if (!isRecord8(rawEdge)) {
70088
+ if (!isRecord9(rawEdge)) {
69938
70089
  diagnostics.push(diagnostic("error", "schema.edge_object", "schema", `Edge ${index2 + 1} must be an object.`, `edges[${index2}]`));
69939
70090
  continue;
69940
70091
  }
@@ -69981,7 +70132,7 @@ function parseUnresolved(value, diagnostics) {
69981
70132
  }
69982
70133
  const unresolved = [];
69983
70134
  for (const [index2, rawIssue] of value.entries()) {
69984
- if (!isRecord8(rawIssue)) {
70135
+ if (!isRecord9(rawIssue)) {
69985
70136
  diagnostics.push(diagnostic("error", "schema.unresolved_object", "schema", `Unresolved issue ${index2 + 1} must be an object.`, `unresolved[${index2}]`));
69986
70137
  continue;
69987
70138
  }
@@ -70004,7 +70155,7 @@ function parseUnresolved(value, diagnostics) {
70004
70155
  function parseLifecycle(value, diagnostics) {
70005
70156
  if (value === undefined)
70006
70157
  return { state: "draft" };
70007
- if (!isRecord8(value)) {
70158
+ if (!isRecord9(value)) {
70008
70159
  diagnostics.push(diagnostic("error", "schema.lifecycle_object", "schema", "Payload lifecycle must be an object.", "lifecycle"));
70009
70160
  return { state: "draft" };
70010
70161
  }
@@ -70062,7 +70213,7 @@ function structureBody(input) {
70062
70213
  }
70063
70214
  function parseAlignPayload(value) {
70064
70215
  const diagnostics = [];
70065
- if (!isRecord8(value)) {
70216
+ if (!isRecord9(value)) {
70066
70217
  return {
70067
70218
  diagnostics: [diagnostic("error", "schema.payload_object", "schema", "Payload must be a YAML/JSON object.", "schema")]
70068
70219
  };
@@ -70147,7 +70298,7 @@ function snapshotPath(projectRoot, structureDigest) {
70147
70298
  structure_digest: structureDigest
70148
70299
  });
70149
70300
  }
70150
- return join18(projectRoot, STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70301
+ return join19(projectRoot, STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70151
70302
  }
70152
70303
  function normalizedSnapshot(payload) {
70153
70304
  const { user_or_agent_hints: _hints, ...body } = payload;
@@ -70163,8 +70314,8 @@ function normalizedSnapshot(payload) {
70163
70314
  });
70164
70315
  }
70165
70316
  async function readSlots(projectRoot) {
70166
- const path3 = join18(projectRoot, STRUCTURE_SLOT_FILE);
70167
- if (!existsSync9(path3))
70317
+ const path3 = join19(projectRoot, STRUCTURE_SLOT_FILE);
70318
+ if (!existsSync10(path3))
70168
70319
  return [];
70169
70320
  const parsed = import_yaml9.default.parse(await readFile16(path3, "utf8"));
70170
70321
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -70212,8 +70363,8 @@ async function updateSlots(projectRoot, payload) {
70212
70363
  ...current2.filter((slot) => !replacements.has(`${slot.source}\x00${slot.collection}`)),
70213
70364
  ...replacements.values()
70214
70365
  ].sort((left, right) => left.source.localeCompare(right.source) || left.collection.localeCompare(right.collection));
70215
- const path3 = join18(projectRoot, STRUCTURE_SLOT_FILE);
70216
- await mkdir12(dirname16(path3), { recursive: true });
70366
+ const path3 = join19(projectRoot, STRUCTURE_SLOT_FILE);
70367
+ await mkdir12(dirname17(path3), { recursive: true });
70217
70368
  await writeFile8(path3, import_yaml9.default.stringify({ schema_version: STRUCTURE_SLOT_SCHEMA_VERSION, slots }), "utf8");
70218
70369
  }
70219
70370
  async function writeStructureSnapshot(projectRoot, payload) {
@@ -70228,7 +70379,7 @@ async function writeStructureSnapshot(projectRoot, payload) {
70228
70379
  });
70229
70380
  }
70230
70381
  const content3 = import_yaml9.default.stringify(normalized);
70231
- if (existsSync9(path3)) {
70382
+ if (existsSync10(path3)) {
70232
70383
  const current2 = await readFile16(path3, "utf8");
70233
70384
  const existing = parseAlignPayload(import_yaml9.default.parse(current2)).payload;
70234
70385
  if (existing?.structure_digest !== payload.structure_digest) {
@@ -70244,14 +70395,14 @@ async function writeStructureSnapshot(projectRoot, payload) {
70244
70395
  await updateSlots(projectRoot, payload);
70245
70396
  return path3;
70246
70397
  }
70247
- await mkdir12(dirname16(path3), { recursive: true });
70398
+ await mkdir12(dirname17(path3), { recursive: true });
70248
70399
  await writeFile8(path3, content3, "utf8");
70249
70400
  await updateSlots(projectRoot, payload);
70250
70401
  return path3;
70251
70402
  }
70252
70403
  async function readStructureSnapshot(projectRoot, structureDigest) {
70253
70404
  const path3 = snapshotPath(projectRoot, structureDigest);
70254
- if (!existsSync9(path3))
70405
+ if (!existsSync10(path3))
70255
70406
  return null;
70256
70407
  try {
70257
70408
  return import_yaml9.default.parse(await readFile16(path3, "utf8"));
@@ -70279,8 +70430,8 @@ async function readStructureSnapshotPayload(projectRoot, structureDigest) {
70279
70430
  return { ...record, structure_digest: structureDigest };
70280
70431
  }
70281
70432
  async function archiveActiveStructure(projectRoot) {
70282
- const path3 = join18(projectRoot, LIFECYCLE_STRUCTURE_FILE);
70283
- if (!existsSync9(path3))
70433
+ const path3 = join19(projectRoot, LIFECYCLE_STRUCTURE_FILE);
70434
+ if (!existsSync10(path3))
70284
70435
  return null;
70285
70436
  let parsed;
70286
70437
  try {
@@ -70308,7 +70459,7 @@ function structureSnapshotRelativePath(structureDigest) {
70308
70459
  const match = STRUCTURE_DIGEST_PATTERN.exec(structureDigest);
70309
70460
  if (match?.[1] === undefined)
70310
70461
  return STRUCTURE_SNAPSHOT_ROOT;
70311
- return join18(STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70462
+ return join19(STRUCTURE_SNAPSHOT_ROOT, `${match[1]}.yaml`);
70312
70463
  }
70313
70464
  async function currentStructureSlotDigest(projectRoot, source2, collection) {
70314
70465
  return (await readSlots(projectRoot)).find((slot) => slot.source === source2 && slot.collection === collection)?.structure_digest;
@@ -70323,9 +70474,9 @@ async function activeStructureSlots(projectRoot, collection) {
70323
70474
 
70324
70475
  // src/project/approvedStructureEdges.ts
70325
70476
  var KNOWLEDGE_ROOT = "knowledge";
70326
- var APPROVED_STRUCTURE_PATH = join19(KNOWLEDGE_ROOT, "structure.yaml");
70477
+ var APPROVED_STRUCTURE_PATH = join20(KNOWLEDGE_ROOT, "structure.yaml");
70327
70478
  var STRUCTURE_EDGE_CONFIDENCE_SET = new Set(STRUCTURE_EDGE_CONFIDENCES);
70328
- function isRecord9(value) {
70479
+ function isRecord10(value) {
70329
70480
  return value !== null && typeof value === "object" && !Array.isArray(value);
70330
70481
  }
70331
70482
  function readEdgeArray(structure) {
@@ -70335,7 +70486,7 @@ function normalizeApprovedEdges(input) {
70335
70486
  const allowed = new Set(STRUCTURE_EDGE_TYPES);
70336
70487
  const edges = [];
70337
70488
  for (const [index2, rawEdge] of input.rawEdges.entries()) {
70338
- if (!isRecord9(rawEdge)) {
70489
+ if (!isRecord10(rawEdge)) {
70339
70490
  throw new ContextError(ExitCode.WorkspaceStateError, "structure edge must be an object", {
70340
70491
  category: ErrorCategory.WorkspaceStateInvalid,
70341
70492
  path: input.path,
@@ -70426,20 +70577,20 @@ function structureEndpointRefs(structure) {
70426
70577
  const refs = [];
70427
70578
  if (Array.isArray(structure.nodes)) {
70428
70579
  for (const node3 of structure.nodes) {
70429
- if (isRecord9(node3) && typeof node3.node_ref === "string")
70580
+ if (isRecord10(node3) && typeof node3.node_ref === "string")
70430
70581
  refs.push(node3.node_ref);
70431
70582
  }
70432
70583
  }
70433
70584
  if (Array.isArray(structure.views)) {
70434
70585
  for (const view of structure.views) {
70435
- if (!isRecord9(view))
70586
+ if (!isRecord10(view))
70436
70587
  continue;
70437
70588
  if (typeof view.view_ref === "string")
70438
70589
  refs.push(view.view_ref);
70439
70590
  if (!Array.isArray(view.sections))
70440
70591
  continue;
70441
70592
  for (const section of view.sections) {
70442
- if (isRecord9(section) && typeof section.section_ref === "string")
70593
+ if (isRecord10(section) && typeof section.section_ref === "string")
70443
70594
  refs.push(section.section_ref);
70444
70595
  }
70445
70596
  }
@@ -70447,12 +70598,12 @@ function structureEndpointRefs(structure) {
70447
70598
  return refs;
70448
70599
  }
70449
70600
  async function readYamlRecord(projectRoot, relPath) {
70450
- const absPath = join19(projectRoot, relPath);
70451
- if (!existsSync10(absPath))
70601
+ const absPath = join20(projectRoot, relPath);
70602
+ if (!existsSync11(absPath))
70452
70603
  return null;
70453
70604
  try {
70454
70605
  const parsed = import_yaml10.default.parse(await readFile17(absPath, "utf8"));
70455
- return isRecord9(parsed) ? parsed : null;
70606
+ return isRecord10(parsed) ? parsed : null;
70456
70607
  } catch (error) {
70457
70608
  throw new ContextError(ExitCode.WorkspaceStateError, `${relPath} is invalid YAML`, {
70458
70609
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -70491,7 +70642,7 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70491
70642
  const snapshotEdges = [];
70492
70643
  for (const structureDigest of [...new Set(slots.map((slot) => slot.structureDigest))].sort()) {
70493
70644
  const structure2 = await readStructureSnapshot(projectRoot, structureDigest);
70494
- if (!isRecord9(structure2)) {
70645
+ if (!isRecord10(structure2)) {
70495
70646
  throw new ContextError(ExitCode.WorkspaceStateError, "active structure snapshot is missing", {
70496
70647
  category: ErrorCategory.WorkspaceStateInvalid,
70497
70648
  structure_digest: structureDigest,
@@ -70532,7 +70683,7 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70532
70683
  }
70533
70684
  if (structure === null)
70534
70685
  return null;
70535
- const lifecycle = isRecord9(structure.lifecycle) ? structure.lifecycle : {};
70686
+ const lifecycle = isRecord10(structure.lifecycle) ? structure.lifecycle : {};
70536
70687
  if (lifecycle.state !== "confirmed" && lifecycle.state !== "frozen")
70537
70688
  return null;
70538
70689
  return normalizeApprovedEdges({
@@ -70548,15 +70699,15 @@ async function readConfirmedStructureEdgeProjection(projectRoot, approvedEndpoin
70548
70699
  init_cliFeedback();
70549
70700
  init_errors();
70550
70701
  init_exitCode();
70551
- import { existsSync as existsSync17 } from "node:fs";
70702
+ import { existsSync as existsSync18 } from "node:fs";
70552
70703
  import { readFile as readFile23 } from "node:fs/promises";
70553
- import { join as join27 } from "node:path";
70704
+ import { join as join28 } from "node:path";
70554
70705
 
70555
70706
  // src/project/verifyApprovedStructure.ts
70556
70707
  var import_yaml12 = __toESM(require_dist3(), 1);
70557
- import { existsSync as existsSync13 } from "node:fs";
70708
+ import { existsSync as existsSync14 } from "node:fs";
70558
70709
  import { readFile as readFile19 } from "node:fs/promises";
70559
- import { join as join23 } from "node:path";
70710
+ import { join as join24 } from "node:path";
70560
70711
 
70561
70712
  // src/project/approvedStructureInputHash.ts
70562
70713
  import { createHash as createHash11 } from "node:crypto";
@@ -70597,11 +70748,11 @@ function approvedStructureInputHash(input) {
70597
70748
  }
70598
70749
 
70599
70750
  // src/project/verifyApprovedStructureEdges.ts
70600
- import { join as join21 } from "node:path";
70751
+ import { join as join22 } from "node:path";
70601
70752
 
70602
70753
  // src/project/verifyCanonicalSourceRefs.ts
70603
- import { existsSync as existsSync11 } from "node:fs";
70604
- import { join as join20 } from "node:path";
70754
+ import { existsSync as existsSync12 } from "node:fs";
70755
+ import { join as join21 } from "node:path";
70605
70756
  var CANONICAL_SOURCE_REF = /^repo:([^#]+)#symbol:(.+):([^:@]+):([^:@]+)@([a-f0-9]+)$/iu;
70606
70757
  function validateCanonicalSourceRef(input) {
70607
70758
  const path3 = input.path ?? ".tmp/context-runtime/lifecycle/candidates.jsonl";
@@ -70657,7 +70808,7 @@ async function validateCanonicalEvidenceSourceRef(input) {
70657
70808
  const registryEntry = input.sourceRegistry.loaded ? registeredDocumentSource(input.sourceRegistry, locator.sourceType, locator.sourceName) : undefined;
70658
70809
  const materializedAt = registryEntry?.materializedAt ?? defaultDocumentMaterializedAt(locator.sourceType, locator.sourceName);
70659
70810
  const manifestPath = registryEntry?.snapshot?.manifest ?? defaultDocumentManifest(materializedAt);
70660
- if (!existsSync11(join20(input.projectRoot, manifestPath)) && !snapshotRootExists(input.projectRoot, materializedAt)) {
70811
+ if (!existsSync12(join21(input.projectRoot, manifestPath)) && !snapshotRootExists(input.projectRoot, materializedAt)) {
70661
70812
  input.issues.push({
70662
70813
  severity: unresolvedSeverity,
70663
70814
  code: "approved-evidence-unavailable",
@@ -70730,7 +70881,7 @@ async function validateCanonicalEvidenceSourceRef(input) {
70730
70881
  }
70731
70882
 
70732
70883
  // src/project/verifyApprovedStructureEdges.ts
70733
- var APPROVED_STRUCTURE_PATH2 = join21("knowledge", "structure.yaml");
70884
+ var APPROVED_STRUCTURE_PATH2 = join22("knowledge", "structure.yaml");
70734
70885
  function approvedStructureEdgeRecords(parsed, issues) {
70735
70886
  if (parsed.edges === undefined)
70736
70887
  return [];
@@ -70863,7 +71014,7 @@ async function validateApprovedStructureEdgeRecords(input) {
70863
71014
  init_cliFeedback();
70864
71015
  init_errors();
70865
71016
  init_exitCode();
70866
- function isRecord10(value) {
71017
+ function isRecord11(value) {
70867
71018
  return value !== null && typeof value === "object" && !Array.isArray(value);
70868
71019
  }
70869
71020
  function codegraphEdgesFromFrontmatter(frontmatter, path3) {
@@ -70876,7 +71027,7 @@ function codegraphEdgesFromFrontmatter(frontmatter, path3) {
70876
71027
  });
70877
71028
  }
70878
71029
  return frontmatter.code_edges.map((rawEdge, index2) => {
70879
- if (!isRecord10(rawEdge)) {
71030
+ if (!isRecord11(rawEdge)) {
70880
71031
  throw new ContextError(ExitCode.WorkspaceStateError, "approved code edge must be an object", {
70881
71032
  category: ErrorCategory.WorkspaceStateInvalid,
70882
71033
  path: path3,
@@ -70936,17 +71087,17 @@ function codegraphRelationshipCoverage(input) {
70936
71087
  }
70937
71088
 
70938
71089
  // src/project/approvedStructureInputs.ts
70939
- import { existsSync as existsSync12 } from "node:fs";
71090
+ import { existsSync as existsSync13 } from "node:fs";
70940
71091
  import { readFile as readFile18 } from "node:fs/promises";
70941
- import { join as join22 } from "node:path";
71092
+ import { join as join23 } from "node:path";
70942
71093
  init_cliFeedback();
70943
71094
  init_errors();
70944
71095
  init_exitCode();
70945
71096
  var import_yaml11 = __toESM(require_dist3(), 1);
70946
- var APPROVED_STRUCTURE_FILE = join22("knowledge", "structure.yaml");
71097
+ var APPROVED_STRUCTURE_FILE = join23("knowledge", "structure.yaml");
70947
71098
  var COLLECTIONS = new Set(KNOWLEDGE_COLLECTIONS);
70948
71099
  var SNAPSHOT_HASH_PATTERN = /^sha256:[a-f0-9]{64}$/u;
70949
- function isRecord11(value) {
71100
+ function isRecord12(value) {
70950
71101
  return value !== null && typeof value === "object" && !Array.isArray(value);
70951
71102
  }
70952
71103
  function invalidSourceInputs(reason) {
@@ -70965,14 +71116,14 @@ function sortedSourceInputs(values2) {
70965
71116
  function parseApprovedStructureSourceInputs(structure) {
70966
71117
  if (structure.source_inputs === undefined)
70967
71118
  return [];
70968
- if (!isRecord11(structure.source_inputs)) {
71119
+ if (!isRecord12(structure.source_inputs)) {
70969
71120
  throw invalidSourceInputs("source_inputs must be an object when present");
70970
71121
  }
70971
71122
  const inputs = new Map;
70972
71123
  for (const [source2, collections] of Object.entries(structure.source_inputs)) {
70973
71124
  if (source2.trim().length === 0)
70974
71125
  throw invalidSourceInputs("source_inputs source key must not be empty");
70975
- if (!isRecord11(collections)) {
71126
+ if (!isRecord12(collections)) {
70976
71127
  throw invalidSourceInputs(`source_inputs.${source2} must be an object`);
70977
71128
  }
70978
71129
  for (const [collection, snapshotHash] of Object.entries(collections)) {
@@ -70997,8 +71148,8 @@ function approvedStructureSourceInputsRecord(inputs) {
70997
71148
  return result;
70998
71149
  }
70999
71150
  async function readApprovedStructureSourceInputs(projectRoot) {
71000
- const path3 = join22(projectRoot, APPROVED_STRUCTURE_FILE);
71001
- if (!existsSync12(path3))
71151
+ const path3 = join23(projectRoot, APPROVED_STRUCTURE_FILE);
71152
+ if (!existsSync13(path3))
71002
71153
  return [];
71003
71154
  let parsed;
71004
71155
  try {
@@ -71006,7 +71157,7 @@ async function readApprovedStructureSourceInputs(projectRoot) {
71006
71157
  } catch {
71007
71158
  return [];
71008
71159
  }
71009
- if (!isRecord11(parsed))
71160
+ if (!isRecord12(parsed))
71010
71161
  return [];
71011
71162
  return parseApprovedStructureSourceInputs(parsed);
71012
71163
  }
@@ -71035,14 +71186,14 @@ function approvedStructureSourceInputKey(input) {
71035
71186
  }
71036
71187
 
71037
71188
  // src/project/verifyApprovedStructure.ts
71038
- var APPROVED_STRUCTURE_PATH3 = join23("knowledge", "structure.yaml");
71189
+ var APPROVED_STRUCTURE_PATH3 = join24("knowledge", "structure.yaml");
71039
71190
  var APPROVED_STRUCTURE_SCHEMA_VERSION = "context.approved-structure.v1";
71040
71191
  var LOCAL_REF = /^src-(\d+)(#(?:span|symbol):.+)$/u;
71041
71192
  async function readApprovedStructureForVerify(input) {
71042
71193
  if (input.structureOverride !== undefined)
71043
71194
  return input.structureOverride;
71044
- const structurePath = join23(input.projectRoot, APPROVED_STRUCTURE_PATH3);
71045
- if (!existsSync13(structurePath))
71195
+ const structurePath = join24(input.projectRoot, APPROVED_STRUCTURE_PATH3);
71196
+ if (!existsSync14(structurePath))
71046
71197
  return;
71047
71198
  let rawParsed;
71048
71199
  try {
@@ -71267,7 +71418,7 @@ async function approvedStructureProjection(projectRoot) {
71267
71418
  const views = [];
71268
71419
  const parentIndexes = [];
71269
71420
  const codeEdges = [];
71270
- for (const file of await walkMarkdown(join23(projectRoot, "knowledge"))) {
71421
+ for (const file of await walkMarkdown(join24(projectRoot, "knowledge"))) {
71271
71422
  if (isKnowledgeAssetPath(file.relPath))
71272
71423
  continue;
71273
71424
  const content3 = await readFile19(file.absPath, "utf8");
@@ -71681,13 +71832,13 @@ async function validateApprovedStructureEdges(input) {
71681
71832
  init_workspace();
71682
71833
 
71683
71834
  // src/project/reviewDecisions.ts
71684
- import { existsSync as existsSync16 } from "node:fs";
71835
+ import { existsSync as existsSync17 } from "node:fs";
71685
71836
  import { mkdir as mkdir15, readFile as readFile22, rename as rename3, rm as rm8, writeFile as writeFile11 } from "node:fs/promises";
71686
- import { dirname as dirname19, join as join26 } from "node:path";
71837
+ import { dirname as dirname20, join as join27 } from "node:path";
71687
71838
  init_cliFeedback();
71688
71839
  init_errors();
71689
71840
  init_exitCode();
71690
- var REVIEW_DECISIONS_FILE = join26("knowledge", "decisions.json");
71841
+ var REVIEW_DECISIONS_FILE = join27("knowledge", "decisions.json");
71691
71842
  var FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/u;
71692
71843
  var COLLECTIONS2 = new Set(KNOWLEDGE_COLLECTIONS);
71693
71844
  function isCandidateId(value) {
@@ -71702,8 +71853,8 @@ function invalidDecisions(reason) {
71702
71853
  });
71703
71854
  }
71704
71855
  async function readRejectedDecisions(projectRoot) {
71705
- const path3 = join26(projectRoot, REVIEW_DECISIONS_FILE);
71706
- if (!existsSync16(path3))
71856
+ const path3 = join27(projectRoot, REVIEW_DECISIONS_FILE);
71857
+ if (!existsSync17(path3))
71707
71858
  return new Map;
71708
71859
  let parsed;
71709
71860
  try {
@@ -71727,14 +71878,14 @@ async function readRejectedDecisions(projectRoot) {
71727
71878
  return decisions;
71728
71879
  }
71729
71880
  async function writeRejectedDecisions(projectRoot, decisions) {
71730
- const path3 = join26(projectRoot, REVIEW_DECISIONS_FILE);
71881
+ const path3 = join27(projectRoot, REVIEW_DECISIONS_FILE);
71731
71882
  if (decisions.size === 0) {
71732
71883
  await rm8(path3, { force: true });
71733
71884
  return;
71734
71885
  }
71735
71886
  const rejected = Object.fromEntries([...decisions.entries()].sort(([left], [right]) => left.localeCompare(right)));
71736
71887
  const tempPath = `${path3}.${process.pid}.tmp`;
71737
- await mkdir15(dirname19(path3), { recursive: true });
71888
+ await mkdir15(dirname20(path3), { recursive: true });
71738
71889
  await writeFile11(tempPath, `${JSON.stringify(rejected, null, 2)}
71739
71890
  `, "utf8");
71740
71891
  await rename3(tempPath, path3);
@@ -71911,7 +72062,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
71911
72062
  issues
71912
72063
  });
71913
72064
  const seenViewRefs = new Set;
71914
- for (const file of await walkMarkdown(join27(projectRoot, "knowledge"))) {
72065
+ for (const file of await walkMarkdown(join28(projectRoot, "knowledge"))) {
71915
72066
  if (isKnowledgeAssetPath(file.relPath))
71916
72067
  continue;
71917
72068
  const content3 = await readFile23(file.absPath, "utf8");
@@ -71934,7 +72085,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
71934
72085
  pageRelPath: `knowledge/${file.relPath}`,
71935
72086
  content: content3
71936
72087
  })) {
71937
- if (!existsSync17(join27(projectRoot, assetPath))) {
72088
+ if (!existsSync18(join28(projectRoot, assetPath))) {
71938
72089
  issues.push({
71939
72090
  severity: "error",
71940
72091
  code: "approved-resource-missing",
@@ -72120,9 +72271,9 @@ init_writeLock();
72120
72271
 
72121
72272
  // src/project/proseCompileBatch.ts
72122
72273
  var import_yaml13 = __toESM(require_dist3(), 1);
72123
- import { existsSync as existsSync19 } from "node:fs";
72274
+ import { existsSync as existsSync20 } from "node:fs";
72124
72275
  import { readFile as readFile25 } from "node:fs/promises";
72125
- import { join as join29 } from "node:path";
72276
+ import { join as join30 } from "node:path";
72126
72277
  init_cliFeedback();
72127
72278
  init_errors();
72128
72279
  init_exitCode();
@@ -72131,9 +72282,9 @@ init_exitCode();
72131
72282
  init_cliFeedback();
72132
72283
  init_errors();
72133
72284
  init_exitCode();
72134
- import { existsSync as existsSync18 } from "node:fs";
72285
+ import { existsSync as existsSync19 } from "node:fs";
72135
72286
  import { readFile as readFile24, readdir as readdir10 } from "node:fs/promises";
72136
- import { basename as basename6, join as join28, relative as relative12 } from "node:path";
72287
+ import { basename as basename6, join as join29, relative as relative12 } from "node:path";
72137
72288
  init_writeLock();
72138
72289
  function candidateSourceKey(record) {
72139
72290
  return record.source === undefined ? undefined : `${record.source.type}:${record.source.name}`;
@@ -72145,11 +72296,11 @@ function toPosixPath8(value) {
72145
72296
  return value.split(/[\\/]+/u).join("/");
72146
72297
  }
72147
72298
  async function approvedPageIdentities(projectRoot) {
72148
- const root = join28(projectRoot, "knowledge");
72299
+ const root = join29(projectRoot, "knowledge");
72149
72300
  const identities = [];
72150
72301
  const visit2 = async (directory) => {
72151
72302
  for (const entry of await readdir10(directory, { withFileTypes: true })) {
72152
- const absolutePath = join28(directory, entry.name);
72303
+ const absolutePath = join29(directory, entry.name);
72153
72304
  if (entry.isDirectory()) {
72154
72305
  await visit2(absolutePath);
72155
72306
  continue;
@@ -72167,7 +72318,7 @@ async function approvedPageIdentities(projectRoot) {
72167
72318
  });
72168
72319
  }
72169
72320
  };
72170
- if (existsSync18(root))
72321
+ if (existsSync19(root))
72171
72322
  await visit2(root);
72172
72323
  return {
72173
72324
  byPath: new Map(identities.map((identity) => [identity.path, identity])),
@@ -72396,7 +72547,7 @@ async function preserveApprovedPathIdentities(input) {
72396
72547
  }
72397
72548
 
72398
72549
  // src/project/proseCompileBatch.ts
72399
- function isRecord13(value) {
72550
+ function isRecord14(value) {
72400
72551
  return value !== null && typeof value === "object" && !Array.isArray(value);
72401
72552
  }
72402
72553
  function stringField2(value, field) {
@@ -72404,11 +72555,11 @@ function stringField2(value, field) {
72404
72555
  return typeof candidate === "string" && candidate.trim().length > 0 ? candidate.trim() : undefined;
72405
72556
  }
72406
72557
  async function readConfirmedStructure(projectRoot) {
72407
- const path3 = join29(projectRoot, LIFECYCLE_STRUCTURE_FILE);
72408
- if (!existsSync19(path3))
72558
+ const path3 = join30(projectRoot, LIFECYCLE_STRUCTURE_FILE);
72559
+ if (!existsSync20(path3))
72409
72560
  return;
72410
72561
  const parsed = import_yaml13.default.parse(await readFile25(path3, "utf8"));
72411
- if (!isRecord13(parsed) || !isRecord13(parsed.lifecycle))
72562
+ if (!isRecord14(parsed) || !isRecord14(parsed.lifecycle))
72412
72563
  return;
72413
72564
  if (parsed.lifecycle.state !== "confirmed" && parsed.lifecycle.state !== "frozen")
72414
72565
  return;
@@ -72423,7 +72574,7 @@ async function readCurrentSnapshotHashes(projectRoot) {
72423
72574
  }
72424
72575
  async function approvedViewRefs(projectRoot, planned) {
72425
72576
  const approved = [];
72426
- for (const file of await walkMarkdown(join29(projectRoot, "knowledge"))) {
72577
+ for (const file of await walkMarkdown(join30(projectRoot, "knowledge"))) {
72427
72578
  if (isKnowledgeAssetPath(file.relPath))
72428
72579
  continue;
72429
72580
  const content3 = await readFile25(file.absPath, "utf8");
@@ -72691,7 +72842,7 @@ function proseCompileBatchNextAction(input) {
72691
72842
 
72692
72843
  // src/project/lifecycleCleanup.ts
72693
72844
  import { rm as rm9 } from "node:fs/promises";
72694
- import { join as join30 } from "node:path";
72845
+ import { join as join31 } from "node:path";
72695
72846
  var COMPLETED_RUNTIME_PATHS = [
72696
72847
  LIFECYCLE_ROOT,
72697
72848
  REVIEW_RUNTIME_ROOT,
@@ -72700,13 +72851,13 @@ var COMPLETED_RUNTIME_PATHS = [
72700
72851
  CANDIDATE_SNAPSHOT_ROOT
72701
72852
  ];
72702
72853
  async function clearCompletedLifecycle(projectRoot) {
72703
- await Promise.all(COMPLETED_RUNTIME_PATHS.map((path3) => rm9(join30(projectRoot, path3), { recursive: true, force: true })));
72854
+ await Promise.all(COMPLETED_RUNTIME_PATHS.map((path3) => rm9(join31(projectRoot, path3), { recursive: true, force: true })));
72704
72855
  }
72705
72856
 
72706
72857
  // src/project/knowledgeAssetRepair.ts
72707
- import { existsSync as existsSync20 } from "node:fs";
72858
+ import { existsSync as existsSync21 } from "node:fs";
72708
72859
  import { mkdir as mkdir16, readFile as readFile26, writeFile as writeFile12 } from "node:fs/promises";
72709
- import { dirname as dirname20, join as join31 } from "node:path";
72860
+ import { dirname as dirname21, join as join32 } from "node:path";
72710
72861
  init_cliFeedback();
72711
72862
  init_errors();
72712
72863
  init_exitCode();
@@ -72717,14 +72868,14 @@ function sourceLocators(frontmatter) {
72717
72868
  ])];
72718
72869
  }
72719
72870
  async function bytesEqual(path3, expected) {
72720
- if (!existsSync20(path3))
72871
+ if (!existsSync21(path3))
72721
72872
  return false;
72722
72873
  const actual = await readFile26(path3);
72723
72874
  return actual.length === expected.length && actual.equals(Buffer.from(expected));
72724
72875
  }
72725
72876
  async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72726
72877
  const affected = [];
72727
- for (const file of await walkMarkdown(join31(projectRoot, "knowledge"))) {
72878
+ for (const file of await walkMarkdown(join32(projectRoot, "knowledge"))) {
72728
72879
  if (isKnowledgeAssetPath(file.relPath))
72729
72880
  continue;
72730
72881
  const content3 = await readFile26(file.absPath, "utf8");
@@ -72798,7 +72949,7 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72798
72949
  for (const asset of assets.values()) {
72799
72950
  if (await bytesEqual(asset.absPath, asset.bytes))
72800
72951
  continue;
72801
- await mkdir16(dirname20(asset.absPath), { recursive: true });
72952
+ await mkdir16(dirname21(asset.absPath), { recursive: true });
72802
72953
  await writeFile12(asset.absPath, asset.bytes);
72803
72954
  writtenAssets.push(asset.relPath);
72804
72955
  }
@@ -72814,7 +72965,7 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
72814
72965
 
72815
72966
  // src/project/close.ts
72816
72967
  var KNOWLEDGE_ROOT2 = "knowledge";
72817
- var STRUCTURE_PATH = join32(KNOWLEDGE_ROOT2, "structure.yaml");
72968
+ var STRUCTURE_PATH = join33(KNOWLEDGE_ROOT2, "structure.yaml");
72818
72969
  var STRUCTURE_SCHEMA_VERSION2 = "context.approved-structure.v1";
72819
72970
  var LOCAL_REF2 = /^src-(\d+)(#(?:span|symbol):.+)$/u;
72820
72971
  var APPROVED_NODE_TYPES2 = new Set(["entity", "domain", "action"]);
@@ -72844,13 +72995,13 @@ function requiredFrontmatterString(frontmatter, field, relPath) {
72844
72995
  });
72845
72996
  }
72846
72997
  async function walkFiles2(root) {
72847
- if (!existsSync21(root))
72998
+ if (!existsSync22(root))
72848
72999
  return [];
72849
73000
  const files = [];
72850
73001
  const visit2 = async (dir) => {
72851
73002
  const entries = await readdir11(dir, { withFileTypes: true });
72852
73003
  for (const entry of entries) {
72853
- const absPath = join32(dir, entry.name);
73004
+ const absPath = join33(dir, entry.name);
72854
73005
  if (entry.isDirectory()) {
72855
73006
  await visit2(absPath);
72856
73007
  continue;
@@ -72875,7 +73026,7 @@ function isDeprecated(content3) {
72875
73026
  return parseFrontmatter3(content3).deprecated === true;
72876
73027
  }
72877
73028
  async function approvedKnowledgeFiles(projectRoot) {
72878
- const files = await walkFiles2(join32(projectRoot, KNOWLEDGE_ROOT2));
73029
+ const files = await walkFiles2(join33(projectRoot, KNOWLEDGE_ROOT2));
72879
73030
  const markdown = await Promise.all(files.filter((file) => file.relPath.endsWith(".md") && !isKnowledgeAssetPath(file.relPath)).map(async (file) => ({
72880
73031
  ...file,
72881
73032
  content: await readFile27(file.absPath, "utf8")
@@ -73145,11 +73296,11 @@ function referencesReceipt() {
73145
73296
  }
73146
73297
  async function readProjectCloseStatus(projectRoot) {
73147
73298
  const approved = await approvedKnowledgeFiles(projectRoot);
73148
- const structurePath = join32(projectRoot, STRUCTURE_PATH);
73149
- if (approved.length === 0 && !existsSync21(structurePath))
73299
+ const structurePath = join33(projectRoot, STRUCTURE_PATH);
73300
+ if (approved.length === 0 && !existsSync22(structurePath))
73150
73301
  return { state: "missing", diagnostics: [] };
73151
73302
  const inputHash = await approvedKnowledgeInputHash(projectRoot);
73152
- if (!existsSync21(structurePath))
73303
+ if (!existsSync22(structurePath))
73153
73304
  return { state: "missing", inputHash, diagnostics: [`close structure is missing: ${STRUCTURE_PATH}`] };
73154
73305
  try {
73155
73306
  const parsed = import_yaml14.default.parse(await readFile27(structurePath, "utf8"));
@@ -73218,8 +73369,8 @@ async function closeProjectWorkspace(projectRoot) {
73218
73369
  next: "Fix context verify errors, then rerun context close --format json."
73219
73370
  });
73220
73371
  }
73221
- const outputPath = join32(projectRoot, STRUCTURE_PATH);
73222
- await mkdir17(dirname21(outputPath), { recursive: true });
73372
+ const outputPath = join33(projectRoot, STRUCTURE_PATH);
73373
+ await mkdir17(dirname22(outputPath), { recursive: true });
73223
73374
  await writeFile13(outputPath, `${import_yaml14.default.stringify(structure)}`, "utf8");
73224
73375
  await clearCompletedLifecycle(projectRoot);
73225
73376
  return {
@@ -73268,22 +73419,33 @@ async function runProjectCloseCommand(input) {
73268
73419
  ].join(`
73269
73420
  `));
73270
73421
  }
73422
+ queueContextRuntimeEvent({
73423
+ cwd: result.projectRoot,
73424
+ kind: "knowledge.closed",
73425
+ properties: {
73426
+ node_count: result.nodes,
73427
+ view_count: result.views,
73428
+ edge_count: result.edges,
73429
+ verify_warning_count: result.verifyWarnings,
73430
+ relationship_coverage: result.relationshipCoverage.state
73431
+ }
73432
+ });
73271
73433
  return true;
73272
73434
  }
73273
73435
 
73274
73436
  // src/project/reviewApply.ts
73275
- import { existsSync as existsSync26 } from "node:fs";
73437
+ import { existsSync as existsSync27 } from "node:fs";
73276
73438
  import { mkdir as mkdir22, readFile as readFile34, rm as rm11, writeFile as writeFile18 } from "node:fs/promises";
73277
- import { dirname as dirname26, join as join41 } from "node:path";
73439
+ import { dirname as dirname27, join as join42 } from "node:path";
73278
73440
  init_cliFeedback();
73279
73441
  init_errors();
73280
73442
  init_exitCode();
73281
73443
 
73282
73444
  // src/project/proseCompileStructure.ts
73283
73445
  import { createHash as createHash15 } from "node:crypto";
73284
- import { existsSync as existsSync24 } from "node:fs";
73446
+ import { existsSync as existsSync25 } from "node:fs";
73285
73447
  import { mkdir as mkdir20, readFile as readFile32, writeFile as writeFile16 } from "node:fs/promises";
73286
- import { dirname as dirname24, join as join39 } from "node:path";
73448
+ import { dirname as dirname25, join as join40 } from "node:path";
73287
73449
  init_cliFeedback();
73288
73450
  init_errors();
73289
73451
  init_exitCode();
@@ -73292,7 +73454,7 @@ var import_yaml20 = __toESM(require_dist3(), 1);
73292
73454
  // src/project/proseAlignEvidence.ts
73293
73455
  import { createHash as createHash13 } from "node:crypto";
73294
73456
  import { readFile as readFile28 } from "node:fs/promises";
73295
- import { join as join33 } from "node:path";
73457
+ import { join as join34 } from "node:path";
73296
73458
 
73297
73459
  // src/incremental/rawBlocks.ts
73298
73460
  var import_yaml15 = __toESM(require_dist3(), 1);
@@ -77187,7 +77349,7 @@ async function loadProseEvidence(input) {
77187
77349
  const documents = [];
77188
77350
  const chunks = [];
77189
77351
  for (const [documentIndex, document4] of indexResult.index.documents.entries()) {
77190
- const markdown = await readFile28(join33(input.projectRoot, indexResult.index.materialized_at, document4.path), "utf8");
77352
+ const markdown = await readFile28(join34(input.projectRoot, indexResult.index.materialized_at, document4.path), "utf8");
77191
77353
  const locator = locatorFor({
77192
77354
  sourceType: resolved.sourceType,
77193
77355
  sourceName: resolved.sourceName,
@@ -77662,19 +77824,19 @@ function repairHints(diagnostics, phaseId) {
77662
77824
 
77663
77825
  // src/project/proseAlignStructureSummary.ts
77664
77826
  import { mkdir as mkdir18, writeFile as writeFile14 } from "node:fs/promises";
77665
- import { dirname as dirname22, join as join36 } from "node:path";
77827
+ import { dirname as dirname23, join as join37 } from "node:path";
77666
77828
 
77667
77829
  // src/project/proseAlignExistingApprovedStructure.ts
77668
77830
  var import_yaml16 = __toESM(require_dist3(), 1);
77669
- import { existsSync as existsSync22 } from "node:fs";
77831
+ import { existsSync as existsSync23 } from "node:fs";
77670
77832
  import { readFile as readFile29, readdir as readdir12 } from "node:fs/promises";
77671
- import { basename as basename7, join as join34, relative as relative14 } from "node:path";
77672
- var APPROVED_STRUCTURE_PATH4 = join34("knowledge", "structure.yaml");
77833
+ import { basename as basename7, join as join35, relative as relative14 } from "node:path";
77834
+ var APPROVED_STRUCTURE_PATH4 = join35("knowledge", "structure.yaml");
77673
77835
  var KNOWLEDGE_ROOT3 = "knowledge";
77674
77836
  function uniqueRefs(refs) {
77675
77837
  return [...new Set(refs)].sort();
77676
77838
  }
77677
- function isRecord14(value) {
77839
+ function isRecord15(value) {
77678
77840
  return value !== null && typeof value === "object" && !Array.isArray(value);
77679
77841
  }
77680
77842
  function stringField3(record, key) {
@@ -77691,14 +77853,14 @@ function toPosixPath10(path4) {
77691
77853
  return path4.split(/[\\/]+/u).join("/");
77692
77854
  }
77693
77855
  async function approvedMarkdownFiles(projectRoot) {
77694
- const root2 = join34(projectRoot, KNOWLEDGE_ROOT3);
77695
- if (!existsSync22(root2))
77856
+ const root2 = join35(projectRoot, KNOWLEDGE_ROOT3);
77857
+ if (!existsSync23(root2))
77696
77858
  return [];
77697
77859
  const files = [];
77698
77860
  const visit3 = async (directory) => {
77699
77861
  const entries = await readdir12(directory, { withFileTypes: true });
77700
77862
  for (const entry of entries) {
77701
- const absolutePath = join34(directory, entry.name);
77863
+ const absolutePath = join35(directory, entry.name);
77702
77864
  if (entry.isDirectory()) {
77703
77865
  await visit3(absolutePath);
77704
77866
  continue;
@@ -77715,7 +77877,7 @@ function frontmatterRecord(markdown) {
77715
77877
  if (match === null)
77716
77878
  return;
77717
77879
  const parsed = import_yaml16.default.parse(match[1] ?? "");
77718
- return isRecord14(parsed) ? parsed : undefined;
77880
+ return isRecord15(parsed) ? parsed : undefined;
77719
77881
  }
77720
77882
  function isDeprecatedApprovedPage(markdown) {
77721
77883
  return /^deprecated:\s*true\s*$/mu.test(markdown);
@@ -77764,7 +77926,7 @@ async function parseExistingApprovedMarkdown(projectRoot) {
77764
77926
  node_type: existingNode?.node_type ?? nodeType,
77765
77927
  tags: uniqueRefs([...existingNode?.tags ?? [], ...nodeTags])
77766
77928
  });
77767
- const relPath = toPosixPath10(relative14(join34(projectRoot, KNOWLEDGE_ROOT3), filePath));
77929
+ const relPath = toPosixPath10(relative14(join35(projectRoot, KNOWLEDGE_ROOT3), filePath));
77768
77930
  const location = pathLocation(relPath);
77769
77931
  const collection = viewRef.split(":", 1)[0] ?? location.collection;
77770
77932
  views.set(viewRef, {
@@ -77793,8 +77955,8 @@ async function parseExistingApprovedMarkdown(projectRoot) {
77793
77955
  return { nodes, views, sections, edges: [], diagnostics: [] };
77794
77956
  }
77795
77957
  async function readFreshApprovedStructureEdges(projectRoot) {
77796
- const absolutePath = join34(projectRoot, APPROVED_STRUCTURE_PATH4);
77797
- if (!existsSync22(absolutePath))
77958
+ const absolutePath = join35(projectRoot, APPROVED_STRUCTURE_PATH4);
77959
+ if (!existsSync23(absolutePath))
77798
77960
  return { edges: [], diagnostics: [] };
77799
77961
  let raw;
77800
77962
  try {
@@ -77803,7 +77965,7 @@ async function readFreshApprovedStructureEdges(projectRoot) {
77803
77965
  const message = error instanceof Error ? error.message : String(error);
77804
77966
  return { edges: [], diagnostics: [`knowledge/structure.yaml could not be parsed: ${message}`] };
77805
77967
  }
77806
- if (!isRecord14(raw) || raw.schema_version !== "context.approved-structure.v1") {
77968
+ if (!isRecord15(raw) || raw.schema_version !== "context.approved-structure.v1") {
77807
77969
  return { edges: [], diagnostics: ["knowledge/structure.yaml schema is not current; approved summary uses Markdown projection only."] };
77808
77970
  }
77809
77971
  const expectedInputHash = await approvedKnowledgeInputHash(projectRoot).catch(() => {
@@ -77837,7 +77999,7 @@ function emptyExistingApprovedStructureSummary(diagnostics = []) {
77837
77999
  function parseApprovedEdges(raw) {
77838
78000
  const edges = [];
77839
78001
  for (const rawEdge of Array.isArray(raw.edges) ? raw.edges : []) {
77840
- if (!isRecord14(rawEdge))
78002
+ if (!isRecord15(rawEdge))
77841
78003
  continue;
77842
78004
  const type = stringField3(rawEdge, "type");
77843
78005
  const from = stringField3(rawEdge, "from");
@@ -77907,7 +78069,7 @@ async function readExistingApprovedStructureSummary(input) {
77907
78069
  const freshStructure = await readFreshApprovedStructureEdges(input.projectRoot);
77908
78070
  approved.edges = freshStructure.edges;
77909
78071
  approved.diagnostics.push(...freshStructure.diagnostics);
77910
- if (approved.nodes.size === 0 && approved.views.size === 0 && approved.sections.size === 0 && !existsSync22(join34(input.projectRoot, APPROVED_STRUCTURE_PATH4))) {
78072
+ if (approved.nodes.size === 0 && approved.views.size === 0 && approved.sections.size === 0 && !existsSync23(join35(input.projectRoot, APPROVED_STRUCTURE_PATH4))) {
77911
78073
  return emptyExistingApprovedStructureSummary();
77912
78074
  }
77913
78075
  const endpointRefs = new Set([
@@ -79015,12 +79177,12 @@ function renderStructureSummaryHtml(input) {
79015
79177
 
79016
79178
  // src/project/localHtmlReport.ts
79017
79179
  import { execFile as execFile3 } from "node:child_process";
79018
- import { isAbsolute as isAbsolute7, join as join35 } from "node:path";
79180
+ import { isAbsolute as isAbsolute7, join as join36 } from "node:path";
79019
79181
  import { pathToFileURL } from "node:url";
79020
79182
  import { promisify as promisify3 } from "node:util";
79021
79183
  var execFileAsync3 = promisify3(execFile3);
79022
79184
  function htmlReportReference(input) {
79023
- const absolutePath = isAbsolute7(input.path) ? input.path : join35(input.projectRoot, input.path);
79185
+ const absolutePath = isAbsolute7(input.path) ? input.path : join36(input.projectRoot, input.path);
79024
79186
  return {
79025
79187
  format: "html",
79026
79188
  path: input.path,
@@ -79366,9 +79528,9 @@ function buildStructureSummary(input) {
79366
79528
  async function writeStructureSummaryReport(input) {
79367
79529
  const summary = buildStructureSummary(input);
79368
79530
  const shortDigest = summary.structure_digest.replace(/^sha256:/u, "").slice(0, 16);
79369
- const reportPath = join36(".tmp", "context-runtime", "reports", `structure-summary-${shortDigest}.html`);
79370
- const absolutePath = join36(input.projectRoot, reportPath);
79371
- await mkdir18(dirname22(absolutePath), { recursive: true });
79531
+ const reportPath = join37(".tmp", "context-runtime", "reports", `structure-summary-${shortDigest}.html`);
79532
+ const absolutePath = join37(input.projectRoot, reportPath);
79533
+ await mkdir18(dirname23(absolutePath), { recursive: true });
79372
79534
  await writeFile14(absolutePath, renderStructureSummaryHtml({ summary, diagnostics: input.diagnostics }), "utf8");
79373
79535
  return {
79374
79536
  summary,
@@ -79543,9 +79705,9 @@ function withStructureReviewArtifacts(input) {
79543
79705
  // src/project/proseCompileViews.ts
79544
79706
  var import_yaml17 = __toESM(require_dist3(), 1);
79545
79707
  import { createHash as createHash14 } from "node:crypto";
79546
- import { existsSync as existsSync23 } from "node:fs";
79708
+ import { existsSync as existsSync24 } from "node:fs";
79547
79709
  import { readFile as readFile30 } from "node:fs/promises";
79548
- import { join as join37 } from "node:path";
79710
+ import { join as join38 } from "node:path";
79549
79711
 
79550
79712
  // src/project/proseCompileSemanticRules.ts
79551
79713
  function compileSemanticRules(input) {
@@ -79948,8 +80110,8 @@ function canonicalizeApprovedSourceRef2(ref2, sources) {
79948
80110
  }
79949
80111
  async function existingApprovedNodeSections(input) {
79950
80112
  const relativePath = `knowledge/${input.node.path}`;
79951
- const absolutePath = join37(input.projectRoot, relativePath);
79952
- if (!existsSync23(absolutePath)) {
80113
+ const absolutePath = join38(input.projectRoot, relativePath);
80114
+ if (!existsSync24(absolutePath)) {
79953
80115
  return {
79954
80116
  path: relativePath,
79955
80117
  present: false,
@@ -80331,7 +80493,7 @@ function parsePayloadText(raw) {
80331
80493
  // src/project/proseAlignPayloadStage.ts
80332
80494
  var import_yaml19 = __toESM(require_dist3(), 1);
80333
80495
  import { mkdir as mkdir19, writeFile as writeFile15 } from "node:fs/promises";
80334
- import { dirname as dirname23, join as join38 } from "node:path";
80496
+ import { dirname as dirname24, join as join39 } from "node:path";
80335
80497
  init_writeLock();
80336
80498
  async function resolveStagedPayloadConfirmation(input) {
80337
80499
  await archiveActiveStructure(input.projectRoot);
@@ -80402,7 +80564,7 @@ async function stageAlignPayload(input) {
80402
80564
  next: readPlanCommand
80403
80565
  });
80404
80566
  }
80405
- const structurePath = join38(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
80567
+ const structurePath = join39(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
80406
80568
  const resolved = await resolveStagedPayloadConfirmation(input);
80407
80569
  const effectivePayload = {
80408
80570
  ...resolved.payload,
@@ -80414,7 +80576,7 @@ async function stageAlignPayload(input) {
80414
80576
  if (effectivePayload.lifecycle.state === "confirmed" || effectivePayload.lifecycle.state === "frozen") {
80415
80577
  await writeStructureSnapshot(input.projectRoot, effectivePayload);
80416
80578
  }
80417
- await mkdir19(dirname23(structurePath), { recursive: true });
80579
+ await mkdir19(dirname24(structurePath), { recursive: true });
80418
80580
  await writeFile15(structurePath, import_yaml19.default.stringify(normalizeAlignPayloadForWrite(effectivePayload)), "utf8");
80419
80581
  return {
80420
80582
  structureFile: LIFECYCLE_STRUCTURE_FILE,
@@ -80930,7 +81092,7 @@ function canonicalJson2(value) {
80930
81092
  function digest3(value) {
80931
81093
  return `sha256:${createHash15("sha256").update(canonicalJson2(value)).digest("hex")}`;
80932
81094
  }
80933
- function isRecord15(value) {
81095
+ function isRecord16(value) {
80934
81096
  return value !== null && typeof value === "object" && !Array.isArray(value);
80935
81097
  }
80936
81098
  function stringField4(record, field) {
@@ -80941,8 +81103,8 @@ function stringArray2(value) {
80941
81103
  return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
80942
81104
  }
80943
81105
  async function readStructureFile(projectRoot) {
80944
- const structurePath = join39(projectRoot, LIFECYCLE_STRUCTURE_FILE);
80945
- if (!existsSync24(structurePath)) {
81106
+ const structurePath = join40(projectRoot, LIFECYCLE_STRUCTURE_FILE);
81107
+ if (!existsSync25(structurePath)) {
80946
81108
  return null;
80947
81109
  }
80948
81110
  let raw;
@@ -80967,8 +81129,8 @@ async function readStructureFile(projectRoot) {
80967
81129
  }
80968
81130
  }
80969
81131
  async function readApprovedStructureFile(projectRoot) {
80970
- const structurePath = join39(projectRoot, APPROVED_STRUCTURE_FILE2);
80971
- if (!existsSync24(structurePath))
81132
+ const structurePath = join40(projectRoot, APPROVED_STRUCTURE_FILE2);
81133
+ if (!existsSync25(structurePath))
80972
81134
  return null;
80973
81135
  try {
80974
81136
  return import_yaml20.default.parse(await readFile32(structurePath, "utf8"));
@@ -80983,13 +81145,13 @@ async function readApprovedStructureFile(projectRoot) {
80983
81145
  async function compileStructureSlotDigest(input) {
80984
81146
  const slotDigest = await currentStructureSlotDigest(input.projectRoot, input.sourceKey, input.collection);
80985
81147
  const current2 = await readStructureFile(input.projectRoot);
80986
- if (current2 === null || !isRecord15(current2) || !Array.isArray(current2.sources) || !Array.isArray(current2.views)) {
81148
+ if (current2 === null || !isRecord16(current2) || !Array.isArray(current2.sources) || !Array.isArray(current2.views)) {
80987
81149
  return slotDigest;
80988
81150
  }
80989
- const currentOwnsTarget = current2.sources.includes(input.sourceKey) && current2.views.some((view) => isRecord15(view) && view.collection === input.collection);
81151
+ const currentOwnsTarget = current2.sources.includes(input.sourceKey) && current2.views.some((view) => isRecord16(view) && view.collection === input.collection);
80990
81152
  if (!currentOwnsTarget)
80991
81153
  return slotDigest;
80992
- const lifecycle = isRecord15(current2.lifecycle) ? current2.lifecycle : undefined;
81154
+ const lifecycle = isRecord16(current2.lifecycle) ? current2.lifecycle : undefined;
80993
81155
  const currentDigest = lifecycle === undefined ? undefined : stringField4(lifecycle, "structure_digest");
80994
81156
  return slotDigest !== undefined && slotDigest !== currentDigest ? slotDigest : undefined;
80995
81157
  }
@@ -80998,7 +81160,7 @@ function parseApprovedSections(value, viewRef) {
80998
81160
  return [];
80999
81161
  const sections = [];
81000
81162
  for (const rawSection of value) {
81001
- if (!isRecord15(rawSection))
81163
+ if (!isRecord16(rawSection))
81002
81164
  continue;
81003
81165
  const id2 = stringField4(rawSection, "id");
81004
81166
  const kind = stringField4(rawSection, "kind");
@@ -81021,7 +81183,7 @@ function parseApprovedNodes(value) {
81021
81183
  return [];
81022
81184
  const nodes = [];
81023
81185
  for (const rawNode of value) {
81024
- if (!isRecord15(rawNode))
81186
+ if (!isRecord16(rawNode))
81025
81187
  continue;
81026
81188
  const nodeRef = stringField4(rawNode, "node_ref");
81027
81189
  const title = stringField4(rawNode, "title");
@@ -81045,7 +81207,7 @@ function parseApprovedViews(value, nodes) {
81045
81207
  const nodeByRef = new Map(nodes.map((node3) => [node3.node_ref, node3]));
81046
81208
  const views = [];
81047
81209
  for (const rawView of value) {
81048
- if (!isRecord15(rawView))
81210
+ if (!isRecord16(rawView))
81049
81211
  continue;
81050
81212
  const viewRef = stringField4(rawView, "view_ref");
81051
81213
  const nodeRef = stringField4(rawView, "node_ref");
@@ -81083,7 +81245,7 @@ function parseApprovedEdges2(value) {
81083
81245
  return [];
81084
81246
  const edges = [];
81085
81247
  for (const rawEdge of value) {
81086
- if (!isRecord15(rawEdge))
81248
+ if (!isRecord16(rawEdge))
81087
81249
  continue;
81088
81250
  const type = stringField4(rawEdge, "type");
81089
81251
  const from = stringField4(rawEdge, "from");
@@ -81147,7 +81309,7 @@ function assertApprovedEdgeContract(value, endpointRefs) {
81147
81309
  });
81148
81310
  }
81149
81311
  for (const [index2, rawEdge] of value.entries()) {
81150
- if (!isRecord15(rawEdge)) {
81312
+ if (!isRecord16(rawEdge)) {
81151
81313
  throw workspaceError("knowledge/structure.yaml edge must be an object", {
81152
81314
  path: APPROVED_STRUCTURE_FILE2,
81153
81315
  edge_index: index2,
@@ -81287,7 +81449,7 @@ async function loadConfirmedStructure(input) {
81287
81449
  let rawStructure = input.structureDigest === undefined ? await readStructureFile(input.projectRoot) : await readStructureSnapshot(input.projectRoot, input.structureDigest);
81288
81450
  if (rawStructure === null && input.structureDigest !== undefined) {
81289
81451
  const active = await readStructureFile(input.projectRoot);
81290
- const activeDigest = isRecord15(active) && isRecord15(active.lifecycle) ? stringField4(active.lifecycle, "structure_digest") : undefined;
81452
+ const activeDigest = isRecord16(active) && isRecord16(active.lifecycle) ? stringField4(active.lifecycle, "structure_digest") : undefined;
81291
81453
  if (activeDigest === input.structureDigest) {
81292
81454
  rawStructure = active;
81293
81455
  } else if (input.readOnly !== true) {
@@ -81304,7 +81466,7 @@ async function loadConfirmedStructure(input) {
81304
81466
  });
81305
81467
  }
81306
81468
  const approvedStructure = await readApprovedStructureFile(input.projectRoot);
81307
- if (!isRecord15(approvedStructure)) {
81469
+ if (!isRecord16(approvedStructure)) {
81308
81470
  throw workspaceError("compileProse requires confirmed .tmp/context-runtime/lifecycle/structure.yaml or approved knowledge/structure.yaml", {
81309
81471
  path: LIFECYCLE_STRUCTURE_FILE,
81310
81472
  approved_structure: APPROVED_STRUCTURE_FILE2,
@@ -81400,8 +81562,8 @@ async function freezeStructureIfNeeded(input) {
81400
81562
  };
81401
81563
  await archiveActiveStructure(input.projectRoot);
81402
81564
  await writeStructureSnapshot(input.projectRoot, nextStructure);
81403
- const structurePath = join39(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
81404
- await mkdir20(dirname24(structurePath), { recursive: true });
81565
+ const structurePath = join40(input.projectRoot, LIFECYCLE_STRUCTURE_FILE);
81566
+ await mkdir20(dirname25(structurePath), { recursive: true });
81405
81567
  await writeFile16(structurePath, import_yaml20.default.stringify({
81406
81568
  schema_version: nextStructure.schema_version,
81407
81569
  sources: nextStructure.sources,
@@ -81484,9 +81646,9 @@ var import_yaml22 = __toESM(require_dist3(), 1);
81484
81646
 
81485
81647
  // src/project/reviewShared.ts
81486
81648
  import { createHash as createHash16 } from "node:crypto";
81487
- import { existsSync as existsSync25, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "node:fs";
81649
+ import { existsSync as existsSync26, readdirSync as readdirSync2, readFileSync as readFileSync7 } from "node:fs";
81488
81650
  import { mkdir as mkdir21, readFile as readFile33, rm as rm10, rmdir as rmdir2, writeFile as writeFile17 } from "node:fs/promises";
81489
- import { dirname as dirname25, join as join40 } from "node:path";
81651
+ import { dirname as dirname26, join as join41 } from "node:path";
81490
81652
  init_cliFeedback();
81491
81653
  init_errors();
81492
81654
  init_exitCode();
@@ -81516,10 +81678,10 @@ function proseCandidateMarkdown(input) {
81516
81678
 
81517
81679
  // src/project/reviewShared.ts
81518
81680
  init_workspace();
81519
- var SNAPSHOT_ROOT2 = join40(".tmp", "context-runtime", "extract", "candidates");
81520
- var REVIEW_ACTION_ROOT2 = join40(".tmp", "context-runtime", "review-actions");
81681
+ var SNAPSHOT_ROOT2 = join41(".tmp", "context-runtime", "extract", "candidates");
81682
+ var REVIEW_ACTION_ROOT2 = join41(".tmp", "context-runtime", "review-actions");
81521
81683
  var REVIEW_PAYLOAD_SCHEMA = "context.review.decisions.v1";
81522
- function isRecord16(value) {
81684
+ function isRecord17(value) {
81523
81685
  return value !== null && typeof value === "object" && !Array.isArray(value);
81524
81686
  }
81525
81687
  function assertCollection(value) {
@@ -81540,26 +81702,26 @@ function assertCollection(value) {
81540
81702
  }
81541
81703
  function snapshotPath2(projectRoot, candidateId) {
81542
81704
  assertSafeEntityId(candidateId);
81543
- return join40(projectRoot, SNAPSHOT_ROOT2, `${candidateId}.json`);
81705
+ return join41(projectRoot, SNAPSHOT_ROOT2, `${candidateId}.json`);
81544
81706
  }
81545
81707
  async function readCandidateSnapshot(projectRoot, candidateId) {
81546
81708
  const file = snapshotPath2(projectRoot, candidateId);
81547
- if (!existsSync25(file))
81709
+ if (!existsSync26(file))
81548
81710
  return;
81549
81711
  let parsed;
81550
81712
  try {
81551
81713
  parsed = JSON.parse(await readFile33(file, "utf8"));
81552
81714
  } catch (error) {
81553
81715
  const message = error instanceof Error ? error.message : String(error);
81554
- throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid JSON: ${join40(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81716
+ throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid JSON: ${join41(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81555
81717
  category: ErrorCategory.SchemaInvalid,
81556
81718
  candidate_id: candidateId,
81557
81719
  reason: message,
81558
81720
  next: "Rerun the extract phase before reviewing this candidate."
81559
81721
  });
81560
81722
  }
81561
- if (!isRecord16(parsed) || typeof parsed.candidate_id !== "string" || typeof parsed.markdown !== "string") {
81562
- throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid: ${join40(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81723
+ if (!isRecord17(parsed) || typeof parsed.candidate_id !== "string" || typeof parsed.markdown !== "string") {
81724
+ throw new ContextError(ExitCode.WorkspaceStateError, `candidate snapshot is invalid: ${join41(SNAPSHOT_ROOT2, `${candidateId}.json`)}`, {
81563
81725
  category: ErrorCategory.SchemaInvalid,
81564
81726
  candidate_id: candidateId,
81565
81727
  next: "Rerun the extract phase before reviewing this candidate."
@@ -81590,15 +81752,15 @@ async function extractCandidateSnapshotIsCurrent(projectRoot, snapshot) {
81590
81752
  async function removeCandidateSnapshot2(projectRoot, candidateId) {
81591
81753
  const file = snapshotPath2(projectRoot, candidateId);
81592
81754
  await rm10(file, { force: true });
81593
- const snapshotRoot = join40(projectRoot, SNAPSHOT_ROOT2);
81594
- let current2 = dirname25(file);
81755
+ const snapshotRoot = join41(projectRoot, SNAPSHOT_ROOT2);
81756
+ let current2 = dirname26(file);
81595
81757
  while (current2 !== snapshotRoot && current2.startsWith(snapshotRoot)) {
81596
81758
  try {
81597
81759
  await rmdir2(current2);
81598
81760
  } catch {
81599
81761
  break;
81600
81762
  }
81601
- current2 = dirname25(current2);
81763
+ current2 = dirname26(current2);
81602
81764
  }
81603
81765
  }
81604
81766
  function parseCanonicalSourceRef(ref2) {
@@ -81719,11 +81881,11 @@ function findApprovedPageForViewRef(projectRoot, viewRef) {
81719
81881
  }
81720
81882
  const nodeRef = viewRef.slice(separator + 1);
81721
81883
  assertSafeEntityId(nodeRef);
81722
- const collectionRoot = join40(projectRoot, "knowledge", collection);
81723
- if (existsSync25(collectionRoot)) {
81884
+ const collectionRoot = join41(projectRoot, "knowledge", collection);
81885
+ if (existsSync26(collectionRoot)) {
81724
81886
  const visit3 = (dir, relDir) => {
81725
81887
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
81726
- const absPath = join40(dir, entry.name);
81888
+ const absPath = join41(dir, entry.name);
81727
81889
  const rel = relDir.length === 0 ? entry.name : `${relDir}/${entry.name}`;
81728
81890
  if (entry.isDirectory()) {
81729
81891
  const found2 = visit3(absPath, rel);
@@ -81733,16 +81895,16 @@ function findApprovedPageForViewRef(projectRoot, viewRef) {
81733
81895
  }
81734
81896
  if (!entry.isFile() || !entry.name.endsWith(".md"))
81735
81897
  continue;
81736
- const block = frontmatterBlock(readFileSync6(absPath, "utf8"));
81898
+ const block = frontmatterBlock(readFileSync7(absPath, "utf8"));
81737
81899
  if (block === null)
81738
81900
  continue;
81739
81901
  const parsed = import_yaml21.default.parse(block.yaml);
81740
- if (!isRecord16(parsed) || parsed.view_ref !== viewRef)
81902
+ if (!isRecord17(parsed) || parsed.view_ref !== viewRef)
81741
81903
  continue;
81742
81904
  const approvedNodeRef = typeof parsed.node_ref === "string" && parsed.node_ref.trim().length > 0 ? parsed.node_ref.trim() : nodeRef;
81743
81905
  return {
81744
81906
  path: absPath,
81745
- relPath: join40("knowledge", collection, rel),
81907
+ relPath: join41("knowledge", collection, rel),
81746
81908
  nodeRef: approvedNodeRef
81747
81909
  };
81748
81910
  }
@@ -81783,7 +81945,7 @@ function updateFrontmatter(content3, mutate) {
81783
81945
  });
81784
81946
  }
81785
81947
  const parsed = import_yaml21.default.parse(block.yaml);
81786
- if (!isRecord16(parsed)) {
81948
+ if (!isRecord17(parsed)) {
81787
81949
  throw new ContextError(ExitCode.WorkspaceStateError, "approved page frontmatter must be a YAML object", {
81788
81950
  category: ErrorCategory.SchemaInvalid
81789
81951
  });
@@ -81798,16 +81960,16 @@ function parseApprovedSources(content3) {
81798
81960
  if (block === null)
81799
81961
  return [];
81800
81962
  const parsed = import_yaml21.default.parse(block.yaml);
81801
- if (!isRecord16(parsed))
81963
+ if (!isRecord17(parsed))
81802
81964
  return [];
81803
81965
  const sources = parsed.sources;
81804
81966
  return Array.isArray(sources) ? sources.filter((source2) => typeof source2 === "string") : [];
81805
81967
  }
81806
81968
  async function writeReviewActionLog(input) {
81807
81969
  const stamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
81808
- const relPath = join40(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
81809
- const path4 = join40(input.projectRoot, relPath);
81810
- await mkdir21(dirname25(path4), { recursive: true });
81970
+ const relPath = join41(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
81971
+ const path4 = join41(input.projectRoot, relPath);
81972
+ await mkdir21(dirname26(path4), { recursive: true });
81811
81973
  await writeFile17(path4, `${JSON.stringify({
81812
81974
  action: input.action,
81813
81975
  id: input.id,
@@ -82302,7 +82464,7 @@ async function prepareApprovedPage(input) {
82302
82464
  if (input.record.candidate_type !== "prose-align") {
82303
82465
  assertSafeEntityId(input.record.node_ref);
82304
82466
  }
82305
- relPath = join41("knowledge", input.record.path);
82467
+ relPath = join42("knowledge", input.record.path);
82306
82468
  const existingView = findApprovedPageForViewRef(input.projectRoot, input.record.view_ref);
82307
82469
  if (existingView !== undefined && existingView.relPath !== relPath) {
82308
82470
  throw new ContextError(ExitCode.WorkspaceStateError, `approved page already exists for view_ref at a different path: ${input.record.view_ref}`, {
@@ -82314,8 +82476,8 @@ async function prepareApprovedPage(input) {
82314
82476
  next: "Resolve the approved page path migration explicitly before approving this candidate."
82315
82477
  });
82316
82478
  }
82317
- const absPath = join41(input.projectRoot, relPath);
82318
- const existing = existsSync26(absPath) ? await readFile34(absPath, "utf8") : undefined;
82479
+ const absPath = join42(input.projectRoot, relPath);
82480
+ const existing = existsSync27(absPath) ? await readFile34(absPath, "utf8") : undefined;
82319
82481
  if (existing !== undefined) {
82320
82482
  const frontmatter = parseFrontmatterLoose(existing);
82321
82483
  const existingViewRef = typeof frontmatter.view_ref === "string" ? frontmatter.view_ref : undefined;
@@ -82387,11 +82549,11 @@ async function prepareApprovedPage(input) {
82387
82549
  }
82388
82550
  async function writePreparedApprovedPage(page) {
82389
82551
  for (const asset of page.assets) {
82390
- await mkdir22(dirname26(asset.absPath), { recursive: true });
82552
+ await mkdir22(dirname27(asset.absPath), { recursive: true });
82391
82553
  await writeFile18(asset.absPath, asset.bytes);
82392
82554
  }
82393
82555
  if (page.changed) {
82394
- await mkdir22(dirname26(page.absPath), { recursive: true });
82556
+ await mkdir22(dirname27(page.absPath), { recursive: true });
82395
82557
  await writeFile18(page.absPath, page.content, "utf8");
82396
82558
  }
82397
82559
  }
@@ -82622,18 +82784,18 @@ init_errors();
82622
82784
  init_exitCode();
82623
82785
 
82624
82786
  // src/project/repoSources.ts
82625
- import { existsSync as existsSync29 } from "node:fs";
82787
+ import { existsSync as existsSync30 } from "node:fs";
82626
82788
  import { lstat, mkdir as mkdir23, readFile as readFile35, readlink, realpath as realpath2, rm as rm12, symlink } from "node:fs/promises";
82627
82789
  import { execFile as execFile4 } from "node:child_process";
82628
82790
  import { promisify as promisify4 } from "node:util";
82629
- import { dirname as dirname27, isAbsolute as isAbsolute8, join as join44, relative as relative15, resolve as resolve17 } from "node:path";
82791
+ import { dirname as dirname28, isAbsolute as isAbsolute8, join as join45, relative as relative15, resolve as resolve17 } from "node:path";
82630
82792
  init_cliFeedback();
82631
82793
  init_errors();
82632
82794
  init_exitCode();
82633
82795
 
82634
82796
  // src/project/repoSourceModules.ts
82635
- import { existsSync as existsSync27 } from "node:fs";
82636
- import { join as join42, resolve as resolve16 } from "node:path";
82797
+ import { existsSync as existsSync28 } from "node:fs";
82798
+ import { join as join43, resolve as resolve16 } from "node:path";
82637
82799
  function normalizeSubpath(value) {
82638
82800
  if (value === undefined)
82639
82801
  return;
@@ -82660,8 +82822,8 @@ function suggestedModuleName(module) {
82660
82822
  return slug || "module";
82661
82823
  }
82662
82824
  async function inspectRepoSourceModules(input) {
82663
- const inspectPath = input.scopedAbs !== null && existsSync27(input.scopedAbs) ? input.scopedAbs : join42(input.projectRoot, input.status.materializedAt);
82664
- const modules = existsSync27(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
82825
+ const inspectPath = input.scopedAbs !== null && existsSync28(input.scopedAbs) ? input.scopedAbs : join43(input.projectRoot, input.status.materializedAt);
82826
+ const modules = existsSync28(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
82665
82827
  const recommended_sources = modules.filter((module) => module.path !== "." || modules.length === 1).map((module) => {
82666
82828
  const local = sourceModuleLocalForDisplay({ source: input.source, status: input.status, module });
82667
82829
  return {
@@ -82692,8 +82854,8 @@ function resolveRepoSourceScopedPath(localAbs, subpath) {
82692
82854
 
82693
82855
  // src/project/repoSourceRegistry.ts
82694
82856
  var import_yaml24 = __toESM(require_dist3(), 1);
82695
- import { existsSync as existsSync28 } from "node:fs";
82696
- import { join as join43 } from "node:path";
82857
+ import { existsSync as existsSync29 } from "node:fs";
82858
+ import { join as join44 } from "node:path";
82697
82859
  init_cliFeedback();
82698
82860
  init_errors();
82699
82861
  init_exitCode();
@@ -82750,14 +82912,14 @@ function registryEntryToRecord(entry) {
82750
82912
  };
82751
82913
  }
82752
82914
  function registryPath(projectRoot) {
82753
- return join43(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
82915
+ return join44(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
82754
82916
  }
82755
82917
  function defaultRepoMaterializedAt(source2) {
82756
82918
  return `sources/repo/${source2.namespace}/${source2.module}`;
82757
82919
  }
82758
82920
  async function readRepoRegistry(projectRoot) {
82759
82921
  const path4 = registryPath(projectRoot);
82760
- if (!existsSync28(path4))
82922
+ if (!existsSync29(path4))
82761
82923
  return { repos: [] };
82762
82924
  const registry2 = await loadSourcesRegistry({ rootDir: projectRoot });
82763
82925
  return {
@@ -82833,13 +82995,13 @@ async function gitOutput(cwd, args) {
82833
82995
  }
82834
82996
  }
82835
82997
  async function readGitOriginRemote(cwd) {
82836
- const directConfigPath = join44(cwd, ".git", "config");
82998
+ const directConfigPath = join45(cwd, ".git", "config");
82837
82999
  let config = await readFile35(directConfigPath, "utf8").catch(() => "");
82838
83000
  if (config.length === 0) {
82839
83001
  const gitDir = await resolveGitDir(cwd);
82840
83002
  if (gitDir === null)
82841
83003
  return null;
82842
- config = await readFile35(join44(gitDir, "config"), "utf8").catch(() => "");
83004
+ config = await readFile35(join45(gitDir, "config"), "utf8").catch(() => "");
82843
83005
  }
82844
83006
  let inOriginBlock = false;
82845
83007
  for (const line of config.split(/\r?\n/u)) {
@@ -82859,17 +83021,17 @@ async function readGitOriginRemote(cwd) {
82859
83021
  async function resolveGitRoot(cwd) {
82860
83022
  let current2 = resolve17(cwd);
82861
83023
  while (true) {
82862
- if (existsSync29(join44(current2, ".git")))
83024
+ if (existsSync30(join45(current2, ".git")))
82863
83025
  return current2;
82864
- const parent = dirname27(current2);
83026
+ const parent = dirname28(current2);
82865
83027
  if (parent === current2)
82866
83028
  return null;
82867
83029
  current2 = parent;
82868
83030
  }
82869
83031
  }
82870
83032
  async function resolveGitDir(cwd) {
82871
- const dotGit = join44(cwd, ".git");
82872
- if (!existsSync29(dotGit))
83033
+ const dotGit = join45(cwd, ".git");
83034
+ if (!existsSync30(dotGit))
82873
83035
  return null;
82874
83036
  const stats = await lstat(dotGit);
82875
83037
  if (stats.isDirectory())
@@ -82886,17 +83048,17 @@ async function readGitHead(cwd) {
82886
83048
  const gitDir = await resolveGitDir(cwd);
82887
83049
  if (gitDir === null)
82888
83050
  return null;
82889
- const headRaw = (await readFile35(join44(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
83051
+ const headRaw = (await readFile35(join45(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
82890
83052
  if (/^[a-f0-9]{40}$/iu.test(headRaw))
82891
83053
  return headRaw.toLowerCase();
82892
83054
  const match = /^ref:\s*(.+)\s*$/iu.exec(headRaw);
82893
83055
  const refPath = match?.[1];
82894
83056
  if (refPath === undefined)
82895
83057
  return null;
82896
- const looseRef = (await readFile35(join44(gitDir, refPath), "utf8").catch(() => "")).trim();
83058
+ const looseRef = (await readFile35(join45(gitDir, refPath), "utf8").catch(() => "")).trim();
82897
83059
  if (/^[a-f0-9]{40}$/iu.test(looseRef))
82898
83060
  return looseRef.toLowerCase();
82899
- const packedRefs = await readFile35(join44(gitDir, "packed-refs"), "utf8").catch(() => "");
83061
+ const packedRefs = await readFile35(join45(gitDir, "packed-refs"), "utf8").catch(() => "");
82900
83062
  for (const line of packedRefs.split(/\r?\n/u)) {
82901
83063
  if (line.startsWith("#") || line.startsWith("^"))
82902
83064
  continue;
@@ -82907,27 +83069,27 @@ async function readGitHead(cwd) {
82907
83069
  return null;
82908
83070
  }
82909
83071
  async function ensureMaterializedSymlink(input) {
82910
- const linkPath = join44(input.projectRoot, input.materializedAt);
82911
- await mkdir23(dirname27(linkPath), { recursive: true });
82912
- if (existsSync29(linkPath)) {
83072
+ const linkPath = join45(input.projectRoot, input.materializedAt);
83073
+ await mkdir23(dirname28(linkPath), { recursive: true });
83074
+ if (existsSync30(linkPath)) {
82913
83075
  const stats = await lstat(linkPath);
82914
83076
  if (!stats.isSymbolicLink()) {
82915
83077
  input.diagnostics.push(`materialized path exists and is not a symlink: ${input.materializedAt}`);
82916
83078
  return false;
82917
83079
  }
82918
83080
  const current2 = await readlink(linkPath);
82919
- const currentAbs = resolve17(dirname27(linkPath), current2);
83081
+ const currentAbs = resolve17(dirname28(linkPath), current2);
82920
83082
  if (currentAbs === input.localAbs)
82921
83083
  return true;
82922
83084
  await rm12(linkPath);
82923
83085
  }
82924
- const relTarget = relative15(dirname27(linkPath), input.localAbs) || ".";
83086
+ const relTarget = relative15(dirname28(linkPath), input.localAbs) || ".";
82925
83087
  await symlink(relTarget, linkPath);
82926
83088
  return true;
82927
83089
  }
82928
83090
  async function diagnoseMaterializedSymlink(input) {
82929
- const linkPath = join44(input.projectRoot, input.materializedAt);
82930
- if (!existsSync29(linkPath)) {
83091
+ const linkPath = join45(input.projectRoot, input.materializedAt);
83092
+ if (!existsSync30(linkPath)) {
82931
83093
  input.diagnostics.push(`materialized path is missing: ${input.materializedAt}`);
82932
83094
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to materialize the local source link.`);
82933
83095
  return false;
@@ -82938,9 +83100,9 @@ async function diagnoseMaterializedSymlink(input) {
82938
83100
  return false;
82939
83101
  }
82940
83102
  const current2 = await readlink(linkPath);
82941
- const currentAbs = resolve17(dirname27(linkPath), current2);
83103
+ const currentAbs = resolve17(dirname28(linkPath), current2);
82942
83104
  if (currentAbs !== input.localAbs) {
82943
- input.diagnostics.push(`materialized path points to ${current2}, expected local checkout ${relative15(dirname27(linkPath), input.localAbs) || "."}`);
83105
+ input.diagnostics.push(`materialized path points to ${current2}, expected local checkout ${relative15(dirname28(linkPath), input.localAbs) || "."}`);
82944
83106
  input.agent_hints.push(`Run context source ensure ${input.sourceName} to refresh the local source link.`);
82945
83107
  return false;
82946
83108
  }
@@ -82972,7 +83134,7 @@ async function normalizeInputRef(input) {
82972
83134
  next: "Pass --local <path> with a git checkout, or use a full 40-character commit sha."
82973
83135
  });
82974
83136
  }
82975
- if (!existsSync29(localAbs)) {
83137
+ if (!existsSync30(localAbs)) {
82976
83138
  throw new ContextError(ExitCode.UserError, `short repo source ref cannot be resolved because local path is missing: ${input.local}`, {
82977
83139
  category: ErrorCategory.UserInputInvalid,
82978
83140
  sourceName: input.sourceName,
@@ -83024,7 +83186,7 @@ async function normalizeAddInput(input, existing) {
83024
83186
  let gitRootAbs = null;
83025
83187
  if (originalLocal !== undefined) {
83026
83188
  const originalLocalAbs = resolveLocalPath(input.projectRoot, originalLocal);
83027
- if (originalLocalAbs !== null && existsSync29(originalLocalAbs)) {
83189
+ if (originalLocalAbs !== null && existsSync30(originalLocalAbs)) {
83028
83190
  gitRootAbs = await resolveGitRoot(originalLocalAbs);
83029
83191
  if (gitRootAbs !== null && input.local !== undefined) {
83030
83192
  const detectedSubpath = normalizeSubpath2(relative15(gitRootAbs, originalLocalAbs));
@@ -83120,11 +83282,11 @@ async function inspectRepoSource(input) {
83120
83282
  const diagnostics = [];
83121
83283
  const agent_hints = [];
83122
83284
  const localAbs = resolveLocalPath(input.projectRoot, source2.local);
83123
- const localExists = localAbs !== null && existsSync29(localAbs);
83285
+ const localExists = localAbs !== null && existsSync30(localAbs);
83124
83286
  const subpath = normalizeSubpath2(source2.subpath);
83125
83287
  const scopedAbs = localAbs === null ? null : scopedLocalPath(localAbs, subpath);
83126
- const scopeExists = scopedAbs !== null && existsSync29(scopedAbs);
83127
- let materialized = existsSync29(join44(input.projectRoot, materializedAt));
83288
+ const scopeExists = scopedAbs !== null && existsSync30(scopedAbs);
83289
+ let materialized = existsSync30(join45(input.projectRoot, materializedAt));
83128
83290
  const checkout = await inspectRepoCheckout({
83129
83291
  source: source2,
83130
83292
  localAbs,
@@ -83773,24 +83935,24 @@ The approved symbol is no longer present in the current code extraction.
83773
83935
  // src/project/packageBuilder.ts
83774
83936
  init_cliFeedback();
83775
83937
  init_errors();
83776
- init_exitCode();
83777
83938
  var import_yaml28 = __toESM(require_dist3(), 1);
83778
83939
  import { createHash as createHash20 } from "node:crypto";
83779
- import { existsSync as existsSync34 } from "node:fs";
83940
+ import { existsSync as existsSync35 } from "node:fs";
83780
83941
  import { mkdir as mkdir27, readdir as readdir15, readFile as readFile41, rm as rm13, writeFile as writeFile22 } from "node:fs/promises";
83781
- import { dirname as dirname33, join as join51, resolve as resolve19 } from "node:path";
83942
+ import { dirname as dirname34, join as join52, resolve as resolve19 } from "node:path";
83943
+ init_exitCode();
83782
83944
 
83783
83945
  // src/project/packageBuildInventory.ts
83784
83946
  var import_yaml26 = __toESM(require_dist3(), 1);
83785
83947
  import { createHash as createHash17 } from "node:crypto";
83786
- import { existsSync as existsSync31 } from "node:fs";
83948
+ import { existsSync as existsSync32 } from "node:fs";
83787
83949
  import { mkdir as mkdir25, readFile as readFile37, writeFile as writeFile20 } from "node:fs/promises";
83788
- import { dirname as dirname29, join as join46 } from "node:path";
83950
+ import { dirname as dirname30, join as join47 } from "node:path";
83789
83951
 
83790
83952
  // src/project/packageIndexes.ts
83791
- import { existsSync as existsSync30, statSync } from "node:fs";
83953
+ import { existsSync as existsSync31, statSync } from "node:fs";
83792
83954
  import { mkdir as mkdir24, readdir as readdir13, readFile as readFile36, writeFile as writeFile19 } from "node:fs/promises";
83793
- import { dirname as dirname28, join as join45, posix as pathPosix, relative as relative16 } from "node:path";
83955
+ import { dirname as dirname29, join as join46, posix as pathPosix, relative as relative16 } from "node:path";
83794
83956
  init_cliFeedback();
83795
83957
  init_errors();
83796
83958
  init_exitCode();
@@ -83944,7 +84106,7 @@ var PACKAGE_INVENTORY_FIELDS = [
83944
84106
  "candidate_fingerprint"
83945
84107
  ];
83946
84108
  var COMPILER_ONLY_TAGS = new Set(["docs", "prose", "parent-index"]);
83947
- function isRecord17(value) {
84109
+ function isRecord18(value) {
83948
84110
  return value !== null && typeof value === "object" && !Array.isArray(value);
83949
84111
  }
83950
84112
  function stringList2(value) {
@@ -83958,7 +84120,7 @@ function parseKnowledgeFrontmatter(content3) {
83958
84120
  return {};
83959
84121
  try {
83960
84122
  const parsed = import_yaml25.parse(match[1]);
83961
- return isRecord17(parsed) ? parsed : {};
84123
+ return isRecord18(parsed) ? parsed : {};
83962
84124
  } catch {
83963
84125
  return {};
83964
84126
  }
@@ -84053,13 +84215,13 @@ function packageKind(pkg) {
84053
84215
  return pkg.kind === "package.kb" ? "kb" : "llms";
84054
84216
  }
84055
84217
  async function walkFiles3(root2) {
84056
- if (!existsSync30(root2))
84218
+ if (!existsSync31(root2))
84057
84219
  return [];
84058
84220
  const files = [];
84059
84221
  const visit3 = async (dir) => {
84060
84222
  const entries = await readdir13(dir, { withFileTypes: true });
84061
84223
  for (const entry of entries) {
84062
- const absPath = join45(dir, entry.name);
84224
+ const absPath = join46(dir, entry.name);
84063
84225
  if (entry.isDirectory()) {
84064
84226
  await visit3(absPath);
84065
84227
  continue;
@@ -84351,10 +84513,10 @@ async function writeKnowledgeDirectoryIndexes(input) {
84351
84513
  let written = 0;
84352
84514
  for (const directory of collectKnowledgeDirectoryIndexes(input.pkg, input.selected)) {
84353
84515
  assertSafeRenderedPath(directory.relPath, "knowledge directory index path");
84354
- const outputPath = join45(input.projectRoot, input.pkg.outDir, directory.relPath);
84355
- if (existsSync30(outputPath))
84516
+ const outputPath = join46(input.projectRoot, input.pkg.outDir, directory.relPath);
84517
+ if (existsSync31(outputPath))
84356
84518
  continue;
84357
- await mkdir24(dirname28(outputPath), { recursive: true });
84519
+ await mkdir24(dirname29(outputPath), { recursive: true });
84358
84520
  await writeFile19(outputPath, renderKnowledgeDirectoryIndex({
84359
84521
  pkg: input.pkg,
84360
84522
  directory,
@@ -84400,23 +84562,23 @@ function packageLinkTargetExists(packageRoot, targetRelPath) {
84400
84562
  return false;
84401
84563
  }
84402
84564
  const normalized = targetRelPath.endsWith("/") ? `${targetRelPath}index.md` : targetRelPath;
84403
- const targetPath = join45(packageRoot, normalized);
84404
- if (existsSync30(targetPath)) {
84565
+ const targetPath = join46(packageRoot, normalized);
84566
+ if (existsSync31(targetPath)) {
84405
84567
  const stat6 = statSync(targetPath);
84406
84568
  if (stat6.isFile())
84407
84569
  return true;
84408
84570
  if (stat6.isDirectory())
84409
- return existsSync30(join45(targetPath, "index.md"));
84571
+ return existsSync31(join46(targetPath, "index.md"));
84410
84572
  return false;
84411
84573
  }
84412
- if (!pathPosix.extname(normalized) && existsSync30(join45(packageRoot, normalized, "index.md")))
84574
+ if (!pathPosix.extname(normalized) && existsSync31(join46(packageRoot, normalized, "index.md")))
84413
84575
  return true;
84414
84576
  return false;
84415
84577
  }
84416
84578
  async function validatePackageIndexLinks(input) {
84417
84579
  if (packageKind(input.pkg) !== "kb")
84418
84580
  return;
84419
- const packageRoot = join45(input.projectRoot, input.pkg.outDir);
84581
+ const packageRoot = join46(input.projectRoot, input.pkg.outDir);
84420
84582
  const files = await walkFiles3(packageRoot);
84421
84583
  for (const file of files) {
84422
84584
  if (file.relPath !== "index.md" && !file.relPath.endsWith("/index.md"))
@@ -84487,10 +84649,10 @@ function packageKind2(pkg) {
84487
84649
  // src/project/packageBuildInventory.ts
84488
84650
  var PACKAGE_BUILD_INVENTORY_PATH = "context-build-inventory.json";
84489
84651
  function knowledgeStructurePath(projectRoot) {
84490
- return join46(projectRoot, "knowledge", "structure.yaml");
84652
+ return join47(projectRoot, "knowledge", "structure.yaml");
84491
84653
  }
84492
84654
  async function readOptionalText(path4) {
84493
- if (!existsSync31(path4))
84655
+ if (!existsSync32(path4))
84494
84656
  return null;
84495
84657
  return readFile37(path4, "utf8");
84496
84658
  }
@@ -84869,8 +85031,8 @@ function packageBuildInventory(input) {
84869
85031
  };
84870
85032
  }
84871
85033
  async function writePackageBuildInventory(input) {
84872
- const outputPath = join46(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
84873
- await mkdir25(dirname29(outputPath), { recursive: true });
85034
+ const outputPath = join47(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
85035
+ await mkdir25(dirname30(outputPath), { recursive: true });
84874
85036
  await writeFile20(outputPath, `${JSON.stringify(input.inventory, null, 2)}
84875
85037
  `, "utf8");
84876
85038
  return 1;
@@ -84878,12 +85040,12 @@ async function writePackageBuildInventory(input) {
84878
85040
 
84879
85041
  // src/project/packageBuildReceipt.ts
84880
85042
  import { createHash as createHash18 } from "node:crypto";
84881
- import { existsSync as existsSync32 } from "node:fs";
85043
+ import { existsSync as existsSync33 } from "node:fs";
84882
85044
  import { readdir as readdir14, readFile as readFile38 } from "node:fs/promises";
84883
- import { join as join47, relative as relative17 } from "node:path";
85045
+ import { join as join48, relative as relative17 } from "node:path";
84884
85046
  var IGNORED_PACKAGE_FS_ENTRIES = new Set([".DS_Store"]);
84885
85047
  async function walkPackageFiles(root2) {
84886
- if (!existsSync32(root2))
85048
+ if (!existsSync33(root2))
84887
85049
  return [];
84888
85050
  const files = [];
84889
85051
  const visit3 = async (dir) => {
@@ -84891,7 +85053,7 @@ async function walkPackageFiles(root2) {
84891
85053
  for (const entry of entries) {
84892
85054
  if (IGNORED_PACKAGE_FS_ENTRIES.has(entry.name))
84893
85055
  continue;
84894
- const absPath = join47(dir, entry.name);
85056
+ const absPath = join48(dir, entry.name);
84895
85057
  if (entry.isDirectory()) {
84896
85058
  await visit3(absPath);
84897
85059
  continue;
@@ -84922,7 +85084,7 @@ function classifyOutputFile(path4, knowledgeGroups) {
84922
85084
  }
84923
85085
  async function packageOutputSnapshot(projectRoot, pkg, knowledgeGroups, previousOutputs = []) {
84924
85086
  const previousByPath = new Map(previousOutputs.map((file) => [file.path, file]));
84925
- return Promise.all((await walkPackageFiles(join47(projectRoot, pkg.outDir))).map(async (file) => {
85087
+ return Promise.all((await walkPackageFiles(join48(projectRoot, pkg.outDir))).map(async (file) => {
84926
85088
  const current2 = classifyOutputFile(file.relPath, knowledgeGroups);
84927
85089
  const previous3 = previousByPath.get(file.relPath);
84928
85090
  const classification = current2.kind === "file" && previous3 !== undefined ? { path: file.relPath, kind: previous3.kind, ...previous3.group === undefined ? {} : { group: previous3.group } } : current2;
@@ -84936,7 +85098,7 @@ async function packageOutputFingerprint(projectRoot, pkg) {
84936
85098
  const snapshot = await packageOutputSnapshot(projectRoot, pkg, new Map);
84937
85099
  return {
84938
85100
  fingerprint: createHash18("sha256").update(JSON.stringify({
84939
- outDirExists: existsSync32(join47(projectRoot, pkg.outDir)),
85101
+ outDirExists: existsSync33(join48(projectRoot, pkg.outDir)),
84940
85102
  files: snapshot.map(({ path: path4, sha256: sha2564 }) => ({ path: path4, sha256: sha2564 }))
84941
85103
  })).digest("hex"),
84942
85104
  files: snapshot.length
@@ -85010,16 +85172,16 @@ function formatPackageBuildSummary(pkg) {
85010
85172
  }
85011
85173
 
85012
85174
  // src/project/packageBuildContent.ts
85013
- import { existsSync as existsSync33 } from "node:fs";
85175
+ import { existsSync as existsSync34 } from "node:fs";
85014
85176
  import { mkdir as mkdir26, readFile as readFile40, writeFile as writeFile21 } from "node:fs/promises";
85015
- import { dirname as dirname32, join as join50 } from "node:path";
85177
+ import { dirname as dirname33, join as join51 } from "node:path";
85016
85178
 
85017
85179
  // src/project/packageAssets.ts
85018
85180
  init_errors();
85019
85181
  init_cliFeedback();
85020
85182
  init_exitCode();
85021
85183
  import { readFile as readFile39 } from "node:fs/promises";
85022
- import { dirname as dirname30, relative as relative18, sep as sep3 } from "node:path";
85184
+ import { dirname as dirname31, relative as relative18, sep as sep3 } from "node:path";
85023
85185
  function posixPath2(value) {
85024
85186
  return value.split(sep3).join("/");
85025
85187
  }
@@ -85041,7 +85203,7 @@ function packageAssetPath(projectRoot, absolute) {
85041
85203
  };
85042
85204
  }
85043
85205
  function packageMarkdownTarget(pageOutputPath, assetOutputPath) {
85044
- const target = posixPath2(relative18(dirname30(pageOutputPath), assetOutputPath));
85206
+ const target = posixPath2(relative18(dirname31(pageOutputPath), assetOutputPath));
85045
85207
  return target.startsWith(".") ? target : `./${target}`;
85046
85208
  }
85047
85209
  async function projectPackageKnowledgeAssets(input) {
@@ -85081,7 +85243,7 @@ init_errors();
85081
85243
  init_exitCode();
85082
85244
  import { execFile as execFile5 } from "node:child_process";
85083
85245
  import { realpath as realpath3 } from "node:fs/promises";
85084
- import { join as join49, relative as relative19, sep as sep4 } from "node:path";
85246
+ import { join as join50, relative as relative19, sep as sep4 } from "node:path";
85085
85247
  import { promisify as promisify5 } from "node:util";
85086
85248
 
85087
85249
  // src/project/packageAssetOptimization.ts
@@ -85090,7 +85252,7 @@ init_errors();
85090
85252
  init_exitCode();
85091
85253
  import { createHash as createHash19 } from "node:crypto";
85092
85254
  import { createRequire as createRequire4 } from "node:module";
85093
- import { dirname as dirname31, extname as extname10, join as join48 } from "node:path";
85255
+ import { dirname as dirname32, extname as extname10, join as join49 } from "node:path";
85094
85256
  import { pathToFileURL as pathToFileURL2 } from "node:url";
85095
85257
  var PACKAGE_ASSET_OPTIMIZATION_THRESHOLD_BYTES = 20 * 1024 * 1024;
85096
85258
  function isPng(bytes) {
@@ -85112,10 +85274,10 @@ function isWebp(bytes) {
85112
85274
  }
85113
85275
  function contentAddressedWebpPath(asset, bytes) {
85114
85276
  const digest4 = createHash19("sha256").update(bytes).digest("hex");
85115
- return `${dirname31(asset.packageRelPath)}/${digest4}.webp`;
85277
+ return `${dirname32(asset.packageRelPath)}/${digest4}.webp`;
85116
85278
  }
85117
85279
  async function loadSharpProcessor(projectRoot) {
85118
- const requireFromWorkspace = createRequire4(join48(projectRoot, "package.json"));
85280
+ const requireFromWorkspace = createRequire4(join49(projectRoot, "package.json"));
85119
85281
  let resolved;
85120
85282
  try {
85121
85283
  resolved = requireFromWorkspace.resolve("sharp");
@@ -85235,7 +85397,7 @@ async function git(projectRoot, args) {
85235
85397
  }
85236
85398
  }
85237
85399
  function repositoryPath(repoRoot, projectRoot, asset) {
85238
- const path4 = relative19(repoRoot, join49(projectRoot, asset.knowledgeRelPath)).split(sep4).join("/");
85400
+ const path4 = relative19(repoRoot, join50(projectRoot, asset.knowledgeRelPath)).split(sep4).join("/");
85239
85401
  if (path4 === ".." || path4.startsWith("../") || path4.startsWith("/")) {
85240
85402
  throw new ContextError(ExitCode.WorkspaceStateError, "knowledge asset is outside the current Git repository", {
85241
85403
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -85350,6 +85512,20 @@ async function deliverFromGit(input) {
85350
85512
  }
85351
85513
  };
85352
85514
  }
85515
+ async function packageAssetDeliveryFingerprintInput(input) {
85516
+ if (input.definition?.delivery !== "git-raw" || input.assets.length === 0)
85517
+ return null;
85518
+ const delivery = await deliverFromGit({
85519
+ projectRoot: input.projectRoot,
85520
+ assets: input.assets,
85521
+ definition: input.definition
85522
+ });
85523
+ return {
85524
+ state: "git-raw",
85525
+ ...delivery.summary.git === undefined ? {} : { git: delivery.summary.git },
85526
+ targets: [...delivery.targetByOriginal.entries()].sort(([left], [right]) => left.localeCompare(right))
85527
+ };
85528
+ }
85353
85529
  async function deliverPackageAssetFiles(input) {
85354
85530
  if (input.definition?.delivery === "git-raw") {
85355
85531
  return deliverFromGit({ projectRoot: input.projectRoot, assets: input.assets, definition: input.definition });
@@ -85528,8 +85704,8 @@ async function writeRenderedPackageTemplate(input) {
85528
85704
  templateRelPath: renderedRelPath,
85529
85705
  logicalTemplateRelPath: renderedLogicalRelPath
85530
85706
  });
85531
- const outputPath = join50(input.projectRoot, input.pkg.outDir, renderedRelPath);
85532
- await mkdir26(dirname32(outputPath), { recursive: true });
85707
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, renderedRelPath);
85708
+ await mkdir26(dirname33(outputPath), { recursive: true });
85533
85709
  await writeFile21(outputPath, renderTemplateText(file.content, contentVars), "utf8");
85534
85710
  written++;
85535
85711
  }
@@ -85555,7 +85731,7 @@ async function writeSelectedPackageKnowledge(input) {
85555
85731
  const { projectedPages, delivered } = input.prepared ?? await prepareSelectedPackageKnowledge(input);
85556
85732
  for (const projected of projectedPages) {
85557
85733
  assertSafeRenderedPath2(projected.pageOutputPath, "knowledge path");
85558
- const outputPath = join50(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
85734
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
85559
85735
  const rewritten = replaceMarkdownInlineLinkTargets(projected.content, (link2) => {
85560
85736
  for (const [inputPath, outputPath2] of delivered.targetByOriginal) {
85561
85737
  if (link2.target === packageMarkdownTarget(projected.pageOutputPath, inputPath)) {
@@ -85564,14 +85740,14 @@ async function writeSelectedPackageKnowledge(input) {
85564
85740
  }
85565
85741
  return;
85566
85742
  });
85567
- await mkdir26(dirname32(outputPath), { recursive: true });
85743
+ await mkdir26(dirname33(outputPath), { recursive: true });
85568
85744
  await writeFile21(outputPath, projectPackageKnowledgeMarkdown(rewritten), "utf8");
85569
85745
  }
85570
85746
  const deliveredAssets = new Map(delivered.assets.map((asset) => [asset.packageRelPath, asset]));
85571
85747
  for (const asset of deliveredAssets.values()) {
85572
85748
  assertSafeRenderedPath2(asset.packageRelPath, "package resource path");
85573
- const outputPath = join50(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
85574
- await mkdir26(dirname32(outputPath), { recursive: true });
85749
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
85750
+ await mkdir26(dirname33(outputPath), { recursive: true });
85575
85751
  await writeFile21(outputPath, asset.bytes);
85576
85752
  }
85577
85753
  return {
@@ -85584,8 +85760,8 @@ async function writeSelectedPackageKnowledge(input) {
85584
85760
  async function appendLlmsKnowledge(input) {
85585
85761
  if (packageKind2(input.pkg) !== "llms" || input.templateConsumesKnowledge || input.knowledgeCount === 0)
85586
85762
  return 0;
85587
- const outputPath = join50(input.projectRoot, input.pkg.outDir, "llms.txt");
85588
- const existed = existsSync33(outputPath);
85763
+ const outputPath = join51(input.projectRoot, input.pkg.outDir, "llms.txt");
85764
+ const existed = existsSync34(outputPath);
85589
85765
  const existing = existed ? await readFile40(outputPath, "utf8") : "";
85590
85766
  const content3 = existing.trim().length > 0 ? `${existing.trimEnd()}
85591
85767
 
@@ -85594,7 +85770,7 @@ async function appendLlmsKnowledge(input) {
85594
85770
  ${input.bundle}
85595
85771
  ` : `${input.bundle}
85596
85772
  `;
85597
- await mkdir26(dirname32(outputPath), { recursive: true });
85773
+ await mkdir26(dirname33(outputPath), { recursive: true });
85598
85774
  await writeFile21(outputPath, content3, "utf8");
85599
85775
  return existed ? 0 : 1;
85600
85776
  }
@@ -85780,8 +85956,8 @@ function validateRenderedSkillDefinition(input) {
85780
85956
  init_workspace();
85781
85957
  init_packageTemplateReview();
85782
85958
  var KNOWLEDGE_ROOT4 = "knowledge";
85783
- var PACKAGE_FINGERPRINT_ROOT = join51(".tmp", "context-runtime", "packages");
85784
- var PACKAGE_BUILDER_PROTOCOL_VERSION = "v13-explicit-asset-delivery";
85959
+ var PACKAGE_FINGERPRINT_ROOT = join52(".tmp", "context-runtime", "packages");
85960
+ var PACKAGE_BUILDER_PROTOCOL_VERSION = "v14-git-asset-identity";
85785
85961
  function packageAssetDeliverySummary(value) {
85786
85962
  if (value === null || typeof value !== "object" || Array.isArray(value))
85787
85963
  return;
@@ -85803,10 +85979,10 @@ function assertPackageOutputDir(pkg) {
85803
85979
  }
85804
85980
  function packageFingerprintPath(projectRoot, pkg) {
85805
85981
  assertSafeRenderedPath2(`${pkg.name}.json`, "package fingerprint path");
85806
- return join51(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
85982
+ return join52(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
85807
85983
  }
85808
85984
  async function listApprovedKnowledge(projectRoot) {
85809
- const files = await walkPackageFiles(join51(projectRoot, KNOWLEDGE_ROOT4));
85985
+ const files = await walkPackageFiles(join52(projectRoot, KNOWLEDGE_ROOT4));
85810
85986
  const knowledge = await Promise.all(files.filter((file) => file.relPath.endsWith(".md") && !file.relPath.startsWith("assets/")).map(async (file) => ({
85811
85987
  ...file,
85812
85988
  content: await readFile41(file.absPath, "utf8")
@@ -85827,7 +86003,7 @@ function isDeprecatedKnowledge(content3) {
85827
86003
  async function listTemplateFiles(projectRoot, templatePath) {
85828
86004
  assertSafeRenderedPath2(templatePath, "package template path");
85829
86005
  const templateRoot = resolve19(projectRoot, templatePath);
85830
- if (!existsSync34(templateRoot)) {
86006
+ if (!existsSync35(templateRoot)) {
85831
86007
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${templatePath}`, {
85832
86008
  category: ErrorCategory.WorkspaceStateInvalid,
85833
86009
  path: templatePath,
@@ -85851,11 +86027,18 @@ async function packageInputFingerprint(input) {
85851
86027
  content: file.content
85852
86028
  })));
85853
86029
  const assets = new Map;
86030
+ const assetFiles = new Map;
85854
86031
  for (const projection of projectedAssets) {
85855
86032
  for (const asset of projection.assets) {
85856
86033
  assets.set(asset.packageRelPath, createHash20("sha256").update(asset.bytes).digest("hex"));
86034
+ assetFiles.set(asset.packageRelPath, asset);
85857
86035
  }
85858
86036
  }
86037
+ const assetDelivery = input.pkg.kind === "package.kb" ? await packageAssetDeliveryFingerprintInput({
86038
+ projectRoot: input.projectRoot,
86039
+ assets: [...assetFiles.values()],
86040
+ ...input.pkg.assets === undefined ? {} : { definition: input.pkg.assets }
86041
+ }) : null;
85859
86042
  return stableHash3({
85860
86043
  builder: PACKAGE_BUILDER_PROTOCOL_VERSION,
85861
86044
  package: {
@@ -85873,6 +86056,7 @@ async function packageInputFingerprint(input) {
85873
86056
  content: file.content
85874
86057
  })),
85875
86058
  assets: [...assets].sort(([left], [right]) => left.localeCompare(right)),
86059
+ assetDelivery,
85876
86060
  template: input.templateFiles.map((file) => ({
85877
86061
  path: file.relPath,
85878
86062
  content: file.content
@@ -85881,7 +86065,7 @@ async function packageInputFingerprint(input) {
85881
86065
  }
85882
86066
  async function readPackageManifest(projectRoot, pkg) {
85883
86067
  const filePath = packageFingerprintPath(projectRoot, pkg);
85884
- if (!existsSync34(filePath))
86068
+ if (!existsSync35(filePath))
85885
86069
  return null;
85886
86070
  try {
85887
86071
  const parsed = JSON.parse(await readFile41(filePath, "utf8"));
@@ -85914,7 +86098,7 @@ async function readPackageManifest(projectRoot, pkg) {
85914
86098
  }
85915
86099
  async function writePackageFingerprint(input) {
85916
86100
  const filePath = packageFingerprintPath(input.projectRoot, input.pkg);
85917
- await mkdir27(dirname33(filePath), { recursive: true });
86101
+ await mkdir27(dirname34(filePath), { recursive: true });
85918
86102
  await writeFile22(filePath, `${JSON.stringify({
85919
86103
  package: input.pkg.name,
85920
86104
  kind: packageKind2(input.pkg),
@@ -85929,12 +86113,12 @@ async function writePackageFingerprint(input) {
85929
86113
  `, "utf8");
85930
86114
  }
85931
86115
  async function removeOrphanPackageDirs(projectRoot, packages) {
85932
- const distRoot = join51(projectRoot, "dist");
85933
- if (!existsSync34(distRoot))
86116
+ const distRoot = join52(projectRoot, "dist");
86117
+ if (!existsSync35(distRoot))
85934
86118
  return;
85935
86119
  const declaredNames = new Set(packages.map((pkg) => pkg.name));
85936
86120
  const entries = await readdir15(distRoot, { withFileTypes: true });
85937
- await Promise.all(entries.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm13(join51(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
86121
+ await Promise.all(entries.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm13(join52(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
85938
86122
  }
85939
86123
  async function collectPackageFreshness(projectRoot, packages) {
85940
86124
  const approved = await listApprovedKnowledge(projectRoot);
@@ -85942,8 +86126,8 @@ async function collectPackageFreshness(projectRoot, packages) {
85942
86126
  assertPackageOutputDir(pkg);
85943
86127
  const selected = selectPackageKnowledge(approved, pkg);
85944
86128
  assertSafeRenderedPath2(pkg.template.path, "package template path");
85945
- const templateRoot = join51(projectRoot, pkg.template.path);
85946
- const templateExists = existsSync34(templateRoot);
86129
+ const templateRoot = join52(projectRoot, pkg.template.path);
86130
+ const templateExists = existsSync35(templateRoot);
85947
86131
  if (!templateExists) {
85948
86132
  throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${pkg.template.path}`, {
85949
86133
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -86077,8 +86261,8 @@ async function buildProjectPackages(projectRoot) {
86077
86261
  files: selected,
86078
86262
  ...assetProcessor === undefined ? {} : { assetProcessor }
86079
86263
  });
86080
- await rm13(join51(projectRoot, pkg.outDir), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
86081
- await mkdir27(join51(projectRoot, pkg.outDir), { recursive: true });
86264
+ await rm13(join52(projectRoot, pkg.outDir), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
86265
+ await mkdir27(join52(projectRoot, pkg.outDir), { recursive: true });
86082
86266
  const rendered = await writeRenderedPackageTemplate({
86083
86267
  projectRoot,
86084
86268
  pkg,
@@ -86216,20 +86400,32 @@ async function runProjectBuildCommand(input) {
86216
86400
  return false;
86217
86401
  const result = await buildProjectPackages(found.projectRoot);
86218
86402
  process.stdout.write(formatProjectBuildResult(result, input.format ?? "text", input.verbose === true));
86403
+ queueContextRuntimeEvent({
86404
+ cwd: result.projectRoot,
86405
+ kind: "package.build.completed",
86406
+ properties: {
86407
+ package_count: result.packages.length,
86408
+ created_count: result.packages.filter((pkg) => pkg.state === "created").length,
86409
+ updated_count: result.packages.filter((pkg) => pkg.state === "updated").length,
86410
+ unchanged_count: result.packages.filter((pkg) => pkg.state === "unchanged").length,
86411
+ output_file_count: result.packages.reduce((total, pkg) => total + pkg.files, 0),
86412
+ resource_file_count: result.packages.reduce((total, pkg) => total + pkg.resources.files, 0)
86413
+ }
86414
+ });
86219
86415
  return true;
86220
86416
  }
86221
86417
 
86222
86418
  // src/project/statusReaders.ts
86223
86419
  init_workspace();
86224
86420
  async function countFiles(root2, predicate) {
86225
- if (!existsSync35(root2))
86421
+ if (!existsSync36(root2))
86226
86422
  return 0;
86227
86423
  let count = 0;
86228
86424
  const visit3 = async (dir, prefix = "") => {
86229
86425
  const entries = await readdir16(dir, { withFileTypes: true });
86230
86426
  for (const entry of entries) {
86231
86427
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
86232
- const abs = join52(dir, entry.name);
86428
+ const abs = join53(dir, entry.name);
86233
86429
  if (entry.isDirectory())
86234
86430
  await visit3(abs, rel);
86235
86431
  else if (entry.isFile() && predicate(rel))
@@ -86271,14 +86467,14 @@ async function readDraftCandidateStatus(projectRoot) {
86271
86467
  throw error;
86272
86468
  }
86273
86469
  }
86274
- function isRecord18(value) {
86470
+ function isRecord19(value) {
86275
86471
  return value !== null && typeof value === "object" && !Array.isArray(value);
86276
86472
  }
86277
86473
  function stagedStructureCounts(parsed) {
86278
86474
  const views = Array.isArray(parsed.views) ? parsed.views : [];
86279
- const sections = views.flatMap((view) => isRecord18(view) && Array.isArray(view.sections) ? view.sections : []);
86475
+ const sections = views.flatMap((view) => isRecord19(view) && Array.isArray(view.sections) ? view.sections : []);
86280
86476
  const sourceRefs = new Set(sections.flatMap((section) => {
86281
- if (!isRecord18(section))
86477
+ if (!isRecord19(section))
86282
86478
  return [];
86283
86479
  return [
86284
86480
  ...typeof section.source_ref === "string" ? [section.source_ref] : [],
@@ -86295,12 +86491,12 @@ function stagedStructureCounts(parsed) {
86295
86491
  };
86296
86492
  }
86297
86493
  function readStructureDraftStatus(projectRoot) {
86298
- const structurePath = join52(projectRoot, LIFECYCLE_STRUCTURE_FILE);
86299
- if (!existsSync35(structurePath))
86494
+ const structurePath = join53(projectRoot, LIFECYCLE_STRUCTURE_FILE);
86495
+ if (!existsSync36(structurePath))
86300
86496
  return { state: "missing", sourceKeys: [], collections: [], diagnostics: [] };
86301
86497
  try {
86302
- const parsed = import_yaml29.default.parse(readFileSync7(structurePath, "utf8"));
86303
- if (!isRecord18(parsed)) {
86498
+ const parsed = import_yaml29.default.parse(readFileSync8(structurePath, "utf8"));
86499
+ if (!isRecord19(parsed)) {
86304
86500
  return {
86305
86501
  state: "invalid",
86306
86502
  sourceKeys: [],
@@ -86308,7 +86504,7 @@ function readStructureDraftStatus(projectRoot) {
86308
86504
  diagnostics: [`${LIFECYCLE_STRUCTURE_FILE} must be a YAML object`]
86309
86505
  };
86310
86506
  }
86311
- const lifecycle = isRecord18(parsed.lifecycle) ? parsed.lifecycle : {};
86507
+ const lifecycle = isRecord19(parsed.lifecycle) ? parsed.lifecycle : {};
86312
86508
  const lifecycleState = lifecycle.state;
86313
86509
  if (lifecycleState === "draft" || lifecycleState === "confirmed" || lifecycleState === "frozen") {
86314
86510
  const structureDigest = typeof parsed.structure_digest === "string" ? parsed.structure_digest : typeof lifecycle.structure_digest === "string" ? lifecycle.structure_digest : undefined;
@@ -86318,7 +86514,7 @@ function readStructureDraftStatus(projectRoot) {
86318
86514
  lifecycleState,
86319
86515
  ...typeof lifecycle.phase_collection === "string" ? { phaseCollection: lifecycle.phase_collection } : {},
86320
86516
  sourceKeys: Array.isArray(parsed.sources) ? parsed.sources.filter((item) => typeof item === "string") : [],
86321
- collections: Array.isArray(parsed.views) ? [...new Set(parsed.views.flatMap((view) => isRecord18(view) && typeof view.collection === "string" ? [view.collection] : []))].sort() : [],
86517
+ collections: Array.isArray(parsed.views) ? [...new Set(parsed.views.flatMap((view) => isRecord19(view) && typeof view.collection === "string" ? [view.collection] : []))].sort() : [],
86322
86518
  ...structureDigest === undefined ? {} : { structureDigest },
86323
86519
  ...evidenceSnapshotHash === undefined ? {} : { evidenceSnapshotHash },
86324
86520
  ...stagedStructureCounts(parsed),
@@ -86495,8 +86691,8 @@ async function documentSourceSiteHint(input) {
86495
86691
  });
86496
86692
  }
86497
86693
  function documentSnapshotReadiness(input) {
86498
- const manifestPath = join52(input.projectRoot, input.manifest);
86499
- if (!existsSync35(manifestPath)) {
86694
+ const manifestPath = join53(input.projectRoot, input.manifest);
86695
+ if (!existsSync36(manifestPath)) {
86500
86696
  return {
86501
86697
  ready: false,
86502
86698
  diagnostics: [`snapshot is missing: ${input.manifest}`],
@@ -86504,7 +86700,7 @@ function documentSnapshotReadiness(input) {
86504
86700
  };
86505
86701
  }
86506
86702
  try {
86507
- const manifest = findDocumentSnapshotForSource(JSON.parse(readFileSync7(manifestPath, "utf8")), input.sourceName);
86703
+ const manifest = findDocumentSnapshotForSource(JSON.parse(readFileSync8(manifestPath, "utf8")), input.sourceName);
86508
86704
  if (manifest === null) {
86509
86705
  return {
86510
86706
  ready: false,
@@ -86565,7 +86761,7 @@ function documentSnapshotReadiness(input) {
86565
86761
  const missingFiles = [
86566
86762
  ...manifest.files.map((file) => file.path),
86567
86763
  ...(manifest.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
86568
- ].filter((path4) => !existsSync35(join52(input.projectRoot, input.materializedAt, path4)));
86764
+ ].filter((path4) => !existsSync36(join53(input.projectRoot, input.materializedAt, path4)));
86569
86765
  if (missingFiles.length > 0) {
86570
86766
  return {
86571
86767
  ready: false,
@@ -86812,9 +87008,9 @@ async function readActiveStructuresStatus(projectRoot, currentSnapshotHashes) {
86812
87008
  init_packageTemplateReview();
86813
87009
 
86814
87010
  // src/project/workflow/workflowProvider.ts
86815
- import { existsSync as existsSync36 } from "node:fs";
86816
- import { dirname as dirname34, resolve as resolve20 } from "node:path";
86817
- import { fileURLToPath as fileURLToPath6 } from "node:url";
87011
+ import { existsSync as existsSync37 } from "node:fs";
87012
+ import { dirname as dirname35, resolve as resolve20 } from "node:path";
87013
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
86818
87014
 
86819
87015
  // src/project/workflow/verifyFacts.ts
86820
87016
  var CLOSE_REPAIRABLE_APPROVED_STRUCTURE_CODES = new Set([
@@ -87164,12 +87360,13 @@ function createContextWorkflowFacts(observation, authorities) {
87164
87360
  }
87165
87361
 
87166
87362
  // src/project/workflow/workflowHostPlans.ts
87167
- function command(value, effect, managedExecution = effect === "write" ? "automatic" : "agent-required") {
87363
+ function command(value, effect, managedExecution = effect === "write" ? "automatic" : "agent-required", execution) {
87168
87364
  return {
87169
87365
  command: value,
87170
87366
  effect,
87171
87367
  availability: "immediate",
87172
- managed_execution: managedExecution
87368
+ managed_execution: managedExecution,
87369
+ ...execution === undefined ? {} : { execution }
87173
87370
  };
87174
87371
  }
87175
87372
  function withJsonFormat(value) {
@@ -87257,8 +87454,10 @@ var HOST_PLAN_RESOLVERS = {
87257
87454
  }),
87258
87455
  "context.extract.next": (observation) => {
87259
87456
  const phase = observation.staleSourcePhases[0] ?? observation.pendingExtractPhases[0];
87457
+ const definition3 = observation.phases.find((candidate) => candidate.id === phase);
87458
+ const projectCode = definition3?.kind === "phase.extract.custom" || definition3?.kind === "phase.custom";
87260
87459
  return {
87261
- commands: phase === undefined ? [] : [command(`context run ${phase} --format json`, "write")]
87460
+ commands: phase === undefined ? [] : [command(`context run ${phase} --format json`, "write", "automatic", projectCode ? { target: "subprocess" } : undefined)]
87262
87461
  };
87263
87462
  },
87264
87463
  "context.document.inspect-classification": (observation) => ({
@@ -87383,7 +87582,7 @@ function planForResolvedCommandPlan(commandPlan, observation) {
87383
87582
 
87384
87583
  // src/project/workflow/workflowEvidenceResources.ts
87385
87584
  import { createHash as createHash21 } from "node:crypto";
87386
- import { join as join53 } from "node:path";
87585
+ import { join as join54 } from "node:path";
87387
87586
  function sourceKeysForRoute(node3, observation) {
87388
87587
  if (node3 === "classify-document") {
87389
87588
  return observation.unclassifiedDocumentTargets.map((target) => target.sourceKey);
@@ -87435,7 +87634,7 @@ async function currentSourceBodyResources(input) {
87435
87634
  kind: "context-view",
87436
87635
  media_type: "text/markdown",
87437
87636
  digest: document4.content_hash,
87438
- path: join53(input.observation.projectRoot, source2.materializedAt, document4.path),
87637
+ path: join54(input.observation.projectRoot, source2.materializedAt, document4.path),
87439
87638
  read_state: isCurrent(id2, document4.content_hash, input.receipts) ? "current" : "read-required"
87440
87639
  });
87441
87640
  }
@@ -87447,7 +87646,7 @@ async function currentSourceBodyResources(input) {
87447
87646
  // src/project/workflow/workflowProvider.ts
87448
87647
  var providerPromise;
87449
87648
  function providerCandidates() {
87450
- const moduleDir2 = dirname34(fileURLToPath6(import.meta.url));
87649
+ const moduleDir2 = dirname35(fileURLToPath7(import.meta.url));
87451
87650
  return [
87452
87651
  ...process.env.C4A_CONTEXT_WORKFLOW_PROVIDER ? [resolve20(process.env.C4A_CONTEXT_WORKFLOW_PROVIDER)] : [],
87453
87652
  resolve20(moduleDir2, "providers", "context", "manifest.json"),
@@ -87455,7 +87654,7 @@ function providerCandidates() {
87455
87654
  ];
87456
87655
  }
87457
87656
  function contextWorkflowProviderPath() {
87458
- const candidate = providerCandidates().find((path4) => existsSync36(path4));
87657
+ const candidate = providerCandidates().find((path4) => existsSync37(path4));
87459
87658
  if (candidate === undefined) {
87460
87659
  throw new Error("Context workflow Provider is missing. Rebuild @c4a/context-cli or reinstall the published package.");
87461
87660
  }
@@ -88469,13 +88668,13 @@ async function collectProjectStatusSnapshot(projectRoot, options = {}) {
88469
88668
  requestedCollections: [...new Set(alignTargets.map((target) => target.collection))],
88470
88669
  requestedGroups: alignGroups
88471
88670
  });
88472
- const approvedPages = await countFiles(join54(projectRoot, "knowledge"), (rel) => rel.endsWith(".md") && !rel.startsWith("assets/"));
88671
+ const approvedPages = await countFiles(join55(projectRoot, "knowledge"), (rel) => rel.endsWith(".md") && !rel.startsWith("assets/"));
88473
88672
  const approvedCollections = (await Promise.all(KNOWLEDGE_COLLECTIONS.map(async (collection) => ({
88474
88673
  collection,
88475
- count: await countFiles(join54(projectRoot, "knowledge", collection), (rel) => rel.endsWith(".md"))
88674
+ count: await countFiles(join55(projectRoot, "knowledge", collection), (rel) => rel.endsWith(".md"))
88476
88675
  })))).filter((item) => item.count > 0).map((item) => item.collection);
88477
88676
  const closeStatus = await readCloseStatus(projectRoot);
88478
- const distFiles = await countFiles(join54(projectRoot, "dist"), () => true);
88677
+ const distFiles = await countFiles(join55(projectRoot, "dist"), () => true);
88479
88678
  const sourceFreshness = phaseStatus.projectEntryValid ? await collectSourceFreshness({
88480
88679
  projectRoot,
88481
88680
  phases,
@@ -88839,6 +89038,7 @@ async function runProjectStatusCommand(input) {
88839
89038
  } else {
88840
89039
  process.stdout.write(formatProjectStatus(status));
88841
89040
  }
89041
+ input.onSuccess?.(status);
88842
89042
  return true;
88843
89043
  }
88844
89044
  async function assertProjectWorkflowRevision(input) {
@@ -88895,11 +89095,11 @@ function shellQuote6(value) {
88895
89095
  }
88896
89096
  function receiptSetPath(receipts) {
88897
89097
  const token = digestText(JSON.stringify(receipts)).slice("sha256:".length);
88898
- return join55(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
89098
+ return join56(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
88899
89099
  }
88900
89100
  async function writeReceiptContinuation(input) {
88901
89101
  const path4 = receiptSetPath(input.receipts);
88902
- await writeJsonAtomic(join55(input.projectRoot, path4), input.receipts);
89102
+ await writeJsonAtomic(join56(input.projectRoot, path4), input.receipts);
88903
89103
  const command2 = input.managed ? [
88904
89104
  "context",
88905
89105
  "--workflow-resource-receipts",
@@ -88960,7 +89160,7 @@ async function materializeContextWorkflowResource(input) {
88960
89160
  }
88961
89161
  const content3 = renderContextWorkflowResource(resourceId2, status);
88962
89162
  const location = await materializeResource(await loadContextWorkflowProvider(), resourceId2, {
88963
- cache: join55(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
89163
+ cache: join56(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
88964
89164
  workspace: found.projectRoot,
88965
89165
  revision: input.revision,
88966
89166
  input: {
@@ -89186,7 +89386,7 @@ function registerContextWorkflowResourceCommands(program2) {
89186
89386
  }
89187
89387
 
89188
89388
  // src/commands/runProject.ts
89189
- import { fileURLToPath as fileURLToPath7 } from "node:url";
89389
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
89190
89390
  init_cliFeedback();
89191
89391
  init_errors();
89192
89392
 
@@ -89197,11 +89397,11 @@ init_exitCode();
89197
89397
 
89198
89398
  // src/project/documentCaptureLark.ts
89199
89399
  import { readdir as readdir18, readFile as readFile44 } from "node:fs/promises";
89200
- import { basename as basename8, extname as extname12, join as join58 } from "node:path";
89400
+ import { basename as basename8, extname as extname12, join as join59 } from "node:path";
89201
89401
 
89202
89402
  // src/lib/atomicFileBatch.ts
89203
89403
  import { lstat as lstat2, mkdir as mkdir28, mkdtemp, rename as rename4, rm as rm14, writeFile as writeFile23 } from "node:fs/promises";
89204
- import { dirname as dirname35, join as join56, resolve as resolve22 } from "node:path";
89404
+ import { dirname as dirname36, join as join57, resolve as resolve22 } from "node:path";
89205
89405
  async function existingFileKind(path4) {
89206
89406
  try {
89207
89407
  const stats = await lstat2(path4);
@@ -89231,9 +89431,9 @@ async function applyAtomicFileBatch(input) {
89231
89431
  for (const path4 of writesByPath.keys())
89232
89432
  removalPaths.delete(path4);
89233
89433
  await mkdir28(input.transactionRoot, { recursive: true });
89234
- const transactionDir = await mkdtemp(join56(input.transactionRoot, "batch-"));
89235
- const stagedRoot = join56(transactionDir, "staged");
89236
- const backupRoot = join56(transactionDir, "backup");
89434
+ const transactionDir = await mkdtemp(join57(input.transactionRoot, "batch-"));
89435
+ const stagedRoot = join57(transactionDir, "staged");
89436
+ const backupRoot = join57(transactionDir, "backup");
89237
89437
  const writes = [...writesByPath.values()].sort((left, right) => left.path.localeCompare(right.path));
89238
89438
  const affectedPaths = [...new Set([...writesByPath.keys(), ...removalPaths])].sort();
89239
89439
  const staged = new Map;
@@ -89243,20 +89443,20 @@ async function applyAtomicFileBatch(input) {
89243
89443
  try {
89244
89444
  await mkdir28(stagedRoot, { recursive: true });
89245
89445
  for (const [index2, write] of writes.entries()) {
89246
- const path4 = join56(stagedRoot, String(index2));
89446
+ const path4 = join57(stagedRoot, String(index2));
89247
89447
  await writeFile23(path4, write.bytes);
89248
89448
  staged.set(write.path, path4);
89249
89449
  }
89250
89450
  for (const [index2, path4] of affectedPaths.entries()) {
89251
89451
  if (await existingFileKind(path4) === "missing")
89252
89452
  continue;
89253
- const backupPath = join56(backupRoot, String(index2));
89254
- await mkdir28(dirname35(backupPath), { recursive: true });
89453
+ const backupPath = join57(backupRoot, String(index2));
89454
+ await mkdir28(dirname36(backupPath), { recursive: true });
89255
89455
  await rename4(path4, backupPath);
89256
89456
  backups.set(path4, backupPath);
89257
89457
  }
89258
89458
  for (const write of writes) {
89259
- await mkdir28(dirname35(write.path), { recursive: true });
89459
+ await mkdir28(dirname36(write.path), { recursive: true });
89260
89460
  await rename4(staged.get(write.path), write.path);
89261
89461
  installed.push(write.path);
89262
89462
  }
@@ -89268,7 +89468,7 @@ async function applyAtomicFileBatch(input) {
89268
89468
  });
89269
89469
  }
89270
89470
  for (const [path4, backupPath] of [...backups.entries()].reverse()) {
89271
- await mkdir28(dirname35(path4), { recursive: true });
89471
+ await mkdir28(dirname36(path4), { recursive: true });
89272
89472
  await rename4(backupPath, path4).catch((rollbackError) => {
89273
89473
  rollbackFailures.push(`restore ${path4}: ${String(rollbackError)}`);
89274
89474
  });
@@ -89305,7 +89505,7 @@ function detectExternalEnvironmentIssue(value) {
89305
89505
  }
89306
89506
 
89307
89507
  // src/lib/feishu.ts
89308
- import { spawn as spawn2 } from "node:child_process";
89508
+ import { spawn as spawn3 } from "node:child_process";
89309
89509
 
89310
89510
  // src/lib/larkDocxXml.ts
89311
89511
  import { createHash as createHash23 } from "node:crypto";
@@ -93590,7 +93790,7 @@ function projectLarkDocxXmlBlock(input) {
93590
93790
  // src/lib/larkResourceMaterialization.ts
93591
93791
  import { createHash as createHash24 } from "node:crypto";
93592
93792
  import { mkdtemp as mkdtemp2, readFile as readFile43, readdir as readdir17, rm as rm15 } from "node:fs/promises";
93593
- import { extname as extname11, join as join57 } from "node:path";
93793
+ import { extname as extname11, join as join58 } from "node:path";
93594
93794
  import { tmpdir } from "node:os";
93595
93795
 
93596
93796
  // src/lib/larkResourceCommand.ts
@@ -93789,7 +93989,7 @@ function findBooleanField(value, name2) {
93789
93989
  return;
93790
93990
  }
93791
93991
  async function downloadedFile(input) {
93792
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-resource-"));
93992
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-resource-"));
93793
93993
  try {
93794
93994
  await runLarkResourceCommand(input.runner, [
93795
93995
  "docs",
@@ -93810,7 +94010,7 @@ async function downloadedFile(input) {
93810
94010
  if (entries.length !== 1)
93811
94011
  throw new Error(`media download produced ${entries.length} files, expected exactly one`);
93812
94012
  const path4 = entries[0]?.name ?? "resource.bin";
93813
- const bytes = await readFile43(join57(tempRoot, path4));
94013
+ const bytes = await readFile43(join58(tempRoot, path4));
93814
94014
  return { path: path4, bytes, mediaType: mediaTypeFor(path4, bytes) };
93815
94015
  } finally {
93816
94016
  await rm15(tempRoot, { recursive: true, force: true });
@@ -93901,9 +94101,9 @@ async function sheetMaterialization(resource, runner2) {
93901
94101
  const sheetId = resource.attributes["sheet-id"];
93902
94102
  if (token === undefined || sheetId === undefined)
93903
94103
  throw new Error("embedded Sheet requires token and sheet-id");
93904
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-sheet-"));
94104
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-sheet-"));
93905
94105
  try {
93906
- const outputPath = join57(tempRoot, "sheet.json");
94106
+ const outputPath = join58(tempRoot, "sheet.json");
93907
94107
  const stdout = await runLarkResourceCommand(runner2, [
93908
94108
  "sheets",
93909
94109
  "+csv-get",
@@ -94059,7 +94259,7 @@ async function whiteboardMaterialization(resource, runner2) {
94059
94259
  if (token === undefined)
94060
94260
  throw new Error(`${resource.kind} has no whiteboard token`);
94061
94261
  const preview = await downloadedFile({ runner: runner2, token, type: "whiteboard" });
94062
- const tempRoot = await mkdtemp2(join57(tmpdir(), "context-lark-whiteboard-"));
94262
+ const tempRoot = await mkdtemp2(join58(tmpdir(), "context-lark-whiteboard-"));
94063
94263
  let rawPayload;
94064
94264
  try {
94065
94265
  await runLarkResourceCommand(runner2, [
@@ -94077,7 +94277,7 @@ async function whiteboardMaterialization(resource, runner2) {
94077
94277
  "--format",
94078
94278
  "json"
94079
94279
  ], { cwd: tempRoot });
94080
- rawPayload = JSON.parse(await readFile43(join57(tempRoot, "raw.json"), "utf8"));
94280
+ rawPayload = JSON.parse(await readFile43(join58(tempRoot, "raw.json"), "utf8"));
94081
94281
  } finally {
94082
94282
  await rm15(tempRoot, { recursive: true, force: true });
94083
94283
  }
@@ -94350,7 +94550,7 @@ class LarkCliError extends Error {
94350
94550
  }
94351
94551
  }
94352
94552
  var defaultRunner = (args, options) => new Promise((resolve8, reject) => {
94353
- const child = spawn2(LARK_BIN, args, {
94553
+ const child = spawn3(LARK_BIN, args, {
94354
94554
  ...options?.cwd === undefined ? {} : { cwd: options.cwd },
94355
94555
  stdio: ["ignore", "pipe", "pipe"]
94356
94556
  });
@@ -94757,7 +94957,7 @@ async function fileContentMatches(path4, content3) {
94757
94957
  }
94758
94958
  }
94759
94959
  function sourceManifestPath2(entry) {
94760
- return entry.snapshot?.manifest ?? join58(entry.materializedAt, "manifest.json");
94960
+ return entry.snapshot?.manifest ?? join59(entry.materializedAt, "manifest.json");
94761
94961
  }
94762
94962
  function larkRuntimeError(message, detail) {
94763
94963
  return new ContextError(ExitCode.ExternalToolError, message, {
@@ -94883,7 +95083,7 @@ function assetManifestEntry(asset, assetRoot) {
94883
95083
  };
94884
95084
  }
94885
95085
  async function listSnapshotAssetFiles(root2, assetRoot) {
94886
- const assetsRoot = join58(root2, assetRoot);
95086
+ const assetsRoot = join59(root2, assetRoot);
94887
95087
  const files = [];
94888
95088
  const visit3 = async (dir, prefix = assetRoot) => {
94889
95089
  let entries;
@@ -94896,7 +95096,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
94896
95096
  }
94897
95097
  for (const entry of entries) {
94898
95098
  const relPath = `${prefix}/${entry.name}`;
94899
- const absolutePath = join58(dir, entry.name);
95099
+ const absolutePath = join59(dir, entry.name);
94900
95100
  if (entry.isDirectory()) {
94901
95101
  await visit3(absolutePath, relPath);
94902
95102
  continue;
@@ -94911,7 +95111,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
94911
95111
  }
94912
95112
  async function staleSnapshotAssetPaths(input) {
94913
95113
  const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
94914
- return existingPaths.filter((path4) => !input.currentPaths.has(path4)).map((path4) => join58(input.materializedAtAbsPath, path4));
95114
+ return existingPaths.filter((path4) => !input.currentPaths.has(path4)).map((path4) => join59(input.materializedAtAbsPath, path4));
94915
95115
  }
94916
95116
  function normalizeLarkError(error, sourceName) {
94917
95117
  if (error instanceof ContextError)
@@ -94985,9 +95185,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
94985
95185
  locator
94986
95186
  }];
94987
95187
  const manifestPath = sourceManifestPath2(entry);
94988
- const manifestAbsPath = join58(input.projectRoot, manifestPath);
95188
+ const manifestAbsPath = join59(input.projectRoot, manifestPath);
94989
95189
  const materializedAt = entry.materializedAt;
94990
- const materializedAtAbsPath = join58(input.projectRoot, materializedAt);
95190
+ const materializedAtAbsPath = join59(input.projectRoot, materializedAt);
94991
95191
  const manifest = createDocumentSnapshotManifest({
94992
95192
  sourceType: "lark",
94993
95193
  sourceName: resolved.sourceName,
@@ -95017,13 +95217,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
95017
95217
  }));
95018
95218
  try {
95019
95219
  const requestedWrites = [{
95020
- path: join58(materializedAtAbsPath, documentPath),
95220
+ path: join59(materializedAtAbsPath, documentPath),
95021
95221
  bytes: normalized
95022
95222
  }];
95023
95223
  for (const asset of assets) {
95024
95224
  if (asset.bytes !== undefined) {
95025
95225
  requestedWrites.push({
95026
- path: join58(materializedAtAbsPath, asset.entry.path),
95226
+ path: join59(materializedAtAbsPath, asset.entry.path),
95027
95227
  bytes: asset.bytes
95028
95228
  });
95029
95229
  }
@@ -95040,7 +95240,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
95040
95240
  currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
95041
95241
  });
95042
95242
  await applyAtomicFileBatch({
95043
- transactionRoot: join58(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
95243
+ transactionRoot: join59(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
95044
95244
  writes,
95045
95245
  removals
95046
95246
  });
@@ -97463,7 +97663,7 @@ function compileDiagnostic(severity, code3, family, message, field, extra = {})
97463
97663
  ...extra
97464
97664
  };
97465
97665
  }
97466
- function isRecord19(value) {
97666
+ function isRecord20(value) {
97467
97667
  return value !== null && typeof value === "object" && !Array.isArray(value);
97468
97668
  }
97469
97669
 
@@ -97858,7 +98058,7 @@ function compileActionFromFields(fields) {
97858
98058
  return action;
97859
98059
  }
97860
98060
  function parseCompileAction(raw, index2, diagnostics) {
97861
- if (!isRecord19(raw)) {
98061
+ if (!isRecord20(raw)) {
97862
98062
  diagnostics.push(compileDiagnostic("error", "schema.action_object", "schema", "Each action must be an object.", `actions[${index2}]`));
97863
98063
  return;
97864
98064
  }
@@ -97870,7 +98070,7 @@ function parseCompileAction(raw, index2, diagnostics) {
97870
98070
  }
97871
98071
  function parseCompilePayload(value) {
97872
98072
  const diagnostics = [];
97873
- if (!isRecord19(value)) {
98073
+ if (!isRecord20(value)) {
97874
98074
  return {
97875
98075
  diagnostics: [compileDiagnostic("error", "schema.payload_object", "schema", "Compile action payload must be an object.", "schema")]
97876
98076
  };
@@ -98833,9 +99033,9 @@ init_atomicWrite();
98833
99033
  init_cliFeedback();
98834
99034
  init_errors();
98835
99035
  init_exitCode();
98836
- import { existsSync as existsSync37 } from "node:fs";
99036
+ import { existsSync as existsSync38 } from "node:fs";
98837
99037
  import { readFile as readFile46 } from "node:fs/promises";
98838
- import { join as join59 } from "node:path";
99038
+ import { join as join60 } from "node:path";
98839
99039
  init_writeLock();
98840
99040
  var CUSTOM_PHASE_MANIFEST = ".tmp/context-runtime/extract/custom-phase-candidates.json";
98841
99041
  function customInputError(phaseId, message, detail = {}) {
@@ -98989,8 +99189,8 @@ function candidateFromCustom(input) {
98989
99189
  };
98990
99190
  }
98991
99191
  async function readManifest(projectRoot) {
98992
- const path4 = join59(projectRoot, CUSTOM_PHASE_MANIFEST);
98993
- if (!existsSync37(path4))
99192
+ const path4 = join60(projectRoot, CUSTOM_PHASE_MANIFEST);
99193
+ if (!existsSync38(path4))
98994
99194
  return { version: 2, phases: {} };
98995
99195
  try {
98996
99196
  const parsed = JSON.parse(await readFile46(path4, "utf8"));
@@ -99090,7 +99290,7 @@ async function runExtractCustomPhase(input) {
99090
99290
  symbols: built.flatMap((item) => item.symbols),
99091
99291
  removeSymbols: previousOwned?.symbols ?? []
99092
99292
  });
99093
- await atomicWriteFile(join59(input.projectRoot, CUSTOM_PHASE_MANIFEST), `${JSON.stringify({
99293
+ await atomicWriteFile(join60(input.projectRoot, CUSTOM_PHASE_MANIFEST), `${JSON.stringify({
99094
99294
  version: 2,
99095
99295
  phases: {
99096
99296
  ...manifest.phases,
@@ -99150,7 +99350,7 @@ async function runExtractCustomPhase(input) {
99150
99350
 
99151
99351
  // src/project/reviewHtml.ts
99152
99352
  import { mkdir as mkdir29, writeFile as writeFile24 } from "node:fs/promises";
99153
- import { dirname as dirname36, isAbsolute as isAbsolute9, join as join61, resolve as resolve23 } from "node:path";
99353
+ import { dirname as dirname37, isAbsolute as isAbsolute9, join as join62, resolve as resolve23 } from "node:path";
99154
99354
  import { pathToFileURL as pathToFileURL3 } from "node:url";
99155
99355
 
99156
99356
  // src/project/reviewSourceExcerpts.ts
@@ -99260,9 +99460,9 @@ async function collectReviewSourceExcerpts(projectRoot, candidates) {
99260
99460
  }
99261
99461
 
99262
99462
  // src/project/reviewHtmlPresentation.ts
99263
- import { existsSync as existsSync38 } from "node:fs";
99463
+ import { existsSync as existsSync39 } from "node:fs";
99264
99464
  import { readFile as readFile47 } from "node:fs/promises";
99265
- import { join as join60 } from "node:path";
99465
+ import { join as join61 } from "node:path";
99266
99466
  var import_yaml31 = __toESM(require_dist3(), 1);
99267
99467
  function escapeHtml3(value) {
99268
99468
  return value.replace(/&/gu, "&amp;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;").replace(/"/gu, "&quot;");
@@ -99343,8 +99543,8 @@ function filterEdgePreviewForCandidate(record, edges) {
99343
99543
  return edges.filter((edge2) => endpoints.has(edge2.from) || endpoints.has(edge2.to));
99344
99544
  }
99345
99545
  async function readEdgePreview(projectRoot) {
99346
- const filePath = join60(projectRoot, LIFECYCLE_STRUCTURE_FILE);
99347
- if (!existsSync38(filePath))
99546
+ const filePath = join61(projectRoot, LIFECYCLE_STRUCTURE_FILE);
99547
+ if (!existsSync39(filePath))
99348
99548
  return [];
99349
99549
  try {
99350
99550
  const parsed = import_yaml31.default.parse(await readFile47(filePath, "utf8"));
@@ -99521,7 +99721,7 @@ var REVIEW_HTML_STYLES = `
99521
99721
  `;
99522
99722
 
99523
99723
  // src/project/reviewHtml.ts
99524
- var REVIEW_HTML_ROOT = join61(".tmp", "context-runtime", "review");
99724
+ var REVIEW_HTML_ROOT = join62(".tmp", "context-runtime", "review");
99525
99725
  function decodedLinkTarget(value) {
99526
99726
  try {
99527
99727
  return decodeURIComponent(value);
@@ -99535,7 +99735,7 @@ function linkedResourcePreviews(input) {
99535
99735
  const target = link2.target;
99536
99736
  if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("/"))
99537
99737
  continue;
99538
- const assetPath = join61(dirname36(input.documentPath), decodedLinkTarget(target)).split("\\").join("/");
99738
+ const assetPath = join62(dirname37(input.documentPath), decodedLinkTarget(target)).split("\\").join("/");
99539
99739
  const asset = input.assetsByPath.get(assetPath);
99540
99740
  if (asset?.content_hash === undefined || asset.role === "audit")
99541
99741
  continue;
@@ -99543,7 +99743,7 @@ function linkedResourcePreviews(input) {
99543
99743
  label: link2.label || "Resource",
99544
99744
  kind: asset.source?.kind ?? "resource",
99545
99745
  status: "materialized",
99546
- url: pathToFileURL3(join61(input.projectRoot, input.materializedAt, asset.path)).href,
99746
+ url: pathToFileURL3(join62(input.projectRoot, input.materializedAt, asset.path)).href,
99547
99747
  media_type: asset.media_type ?? "application/octet-stream",
99548
99748
  image: asset.media_type?.startsWith("image/") === true
99549
99749
  });
@@ -99552,7 +99752,7 @@ function linkedResourcePreviews(input) {
99552
99752
  }
99553
99753
  function materializationPreview(input) {
99554
99754
  const linkedAsset = input.item.asset_paths.flatMap((path4) => [path4, path4.startsWith("assets/") ? path4 : `assets/${path4}`]).map((path4) => input.assetsByPath.get(path4)).find((asset) => asset !== undefined && asset.role !== "audit");
99555
- const url = input.existing?.url ?? (linkedAsset?.content_hash === undefined ? undefined : pathToFileURL3(join61(input.projectRoot, input.materializedAt, linkedAsset.path)).href);
99755
+ const url = input.existing?.url ?? (linkedAsset?.content_hash === undefined ? undefined : pathToFileURL3(join62(input.projectRoot, input.materializedAt, linkedAsset.path)).href);
99556
99756
  return {
99557
99757
  key: linkedAsset?.path ?? input.item.locator,
99558
99758
  preview: {
@@ -100096,7 +100296,7 @@ function renderReviewHtml(candidates, reviewScope, edgePreview, sourceExcerpts,
100096
100296
  }
100097
100297
  function resolveOutputPath(projectRoot, outPath, reviewScope) {
100098
100298
  if (outPath === undefined)
100099
- return join61(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
100299
+ return join62(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
100100
100300
  return isAbsolute9(outPath) ? outPath : resolve23(projectRoot, outPath);
100101
100301
  }
100102
100302
  async function writeReviewHtml(input) {
@@ -100109,7 +100309,7 @@ async function writeReviewHtml(input) {
100109
100309
  const sourceExcerpts = await collectReviewSourceExcerpts(input.projectRoot, candidates);
100110
100310
  const resourcePreviews = await collectReviewResourcePreviews(input.projectRoot, candidates);
100111
100311
  const outPath = resolveOutputPath(input.projectRoot, input.out, reviewScope);
100112
- await mkdir29(dirname36(outPath), { recursive: true });
100312
+ await mkdir29(dirname37(outPath), { recursive: true });
100113
100313
  await writeFile24(outPath, renderReviewHtml(candidates, reviewScope, edgePreview, sourceExcerpts, resourcePreviews), "utf8");
100114
100314
  return {
100115
100315
  path: outPath,
@@ -100524,17 +100724,17 @@ function compactJsonResult(result, verbose) {
100524
100724
  }
100525
100725
 
100526
100726
  // src/project/runLog.ts
100527
- import { randomUUID as randomUUID2 } from "node:crypto";
100727
+ import { randomUUID as randomUUID3 } from "node:crypto";
100528
100728
  import { mkdir as mkdir30, writeFile as writeFile25 } from "node:fs/promises";
100529
- import { dirname as dirname37, join as join62 } from "node:path";
100729
+ import { dirname as dirname38, join as join63 } from "node:path";
100530
100730
  var createPhaseRunId = () => {
100531
100731
  const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
100532
- return `run_${timestamp}_${randomUUID2().slice(0, 8)}`;
100732
+ return `run_${timestamp}_${randomUUID3().slice(0, 8)}`;
100533
100733
  };
100534
100734
  async function writePhaseRunLog(input) {
100535
- const relPath = join62(".tmp", "context-runtime", "runs", `${input.runId}.json`);
100536
- const absPath = join62(input.projectRoot, relPath);
100537
- await mkdir30(dirname37(absPath), { recursive: true });
100735
+ const relPath = join63(".tmp", "context-runtime", "runs", `${input.runId}.json`);
100736
+ const absPath = join63(input.projectRoot, relPath);
100737
+ await mkdir30(dirname38(absPath), { recursive: true });
100538
100738
  await writeFile25(absPath, `${JSON.stringify({
100539
100739
  run_id: input.runId,
100540
100740
  phase_id: input.phase.id,
@@ -101235,14 +101435,14 @@ init_exitCode();
101235
101435
  import { resolve as resolve24 } from "node:path";
101236
101436
  init_workspace();
101237
101437
  var PROSE_STRUCTURE_BATCH_SCHEMA = "context.prose.structure-batch.v1";
101238
- function isRecord20(value) {
101438
+ function isRecord21(value) {
101239
101439
  return value !== null && typeof value === "object" && !Array.isArray(value);
101240
101440
  }
101241
101441
  function shellQuote8(value) {
101242
101442
  return /^[A-Za-z0-9._/=-]+$/u.test(value) ? value : `'${value.replace(/'/gu, `'"'"'`)}'`;
101243
101443
  }
101244
101444
  function parseBatchPayload(value) {
101245
- if (!isRecord20(value) || value.schema !== PROSE_STRUCTURE_BATCH_SCHEMA || !Array.isArray(value.items)) {
101445
+ if (!isRecord21(value) || value.schema !== PROSE_STRUCTURE_BATCH_SCHEMA || !Array.isArray(value.items)) {
101246
101446
  throw new ContextError(ExitCode.UserError, `batch input must match ${PROSE_STRUCTURE_BATCH_SCHEMA}`, {
101247
101447
  category: ErrorCategory.UserInputInvalid,
101248
101448
  next: "Read the current Route action input_schema and provide one phase_id/input pair per pending structure slot."
@@ -101255,7 +101455,7 @@ function parseBatchPayload(value) {
101255
101455
  }
101256
101456
  const seen = new Set;
101257
101457
  return value.items.map((item, index2) => {
101258
- if (!isRecord20(item) || typeof item.phase_id !== "string" || typeof item.input !== "string") {
101458
+ if (!isRecord21(item) || typeof item.phase_id !== "string" || typeof item.input !== "string") {
101259
101459
  throw new ContextError(ExitCode.UserError, `structure batch items[${index2}] requires phase_id and input`, {
101260
101460
  category: ErrorCategory.UserInputInvalid
101261
101461
  });
@@ -101287,7 +101487,7 @@ function alignPhase(phases, phaseId) {
101287
101487
  return phase;
101288
101488
  }
101289
101489
  function validationSummary(phaseId, input, result) {
101290
- const counts2 = result.structure_summary_compact !== undefined && isRecord20(result.structure_summary_compact.counts) ? result.structure_summary_compact.counts : undefined;
101490
+ const counts2 = result.structure_summary_compact !== undefined && isRecord21(result.structure_summary_compact.counts) ? result.structure_summary_compact.counts : undefined;
101291
101491
  return {
101292
101492
  phase_id: phaseId,
101293
101493
  input,
@@ -101629,7 +101829,8 @@ async function runWorkflowUntilBlockedOrComplete(input) {
101629
101829
  receipt = await input.execute({
101630
101830
  cwd: status.projectRoot,
101631
101831
  command: selected.command.command,
101632
- effect: selected.command.effect
101832
+ effect: selected.command.effect,
101833
+ ...selected.command.execution === undefined ? {} : { execution: selected.command.execution }
101633
101834
  });
101634
101835
  } catch (error) {
101635
101836
  steps.push(step);
@@ -101780,7 +101981,7 @@ init_debugTrace();
101780
101981
  // src/project/workflow/workflowExecutionRuntime.ts
101781
101982
  init_debugTrace();
101782
101983
  import { createHash as createHash26 } from "node:crypto";
101783
- import { spawn as spawn3 } from "node:child_process";
101984
+ import { spawn as spawn4 } from "node:child_process";
101784
101985
  function digestText2(value, includeTail) {
101785
101986
  const bytes = Buffer.byteLength(value);
101786
101987
  return {
@@ -101874,7 +102075,7 @@ class WorkspaceExecutionRuntime {
101874
102075
  throw new Error(`workspace execution runtime cannot cross roots: ${input.cwd}`);
101875
102076
  }
101876
102077
  const args = parseContextCommand(input.command);
101877
- if (input.effect !== "external" && this.inProcess.supports({ ...input, args })) {
102078
+ if (input.execution?.target !== "subprocess" && input.effect !== "external" && this.inProcess.supports({ ...input, args })) {
101878
102079
  return this.executeInProcess({ ...input, args });
101879
102080
  }
101880
102081
  return this.executeSubprocess(input);
@@ -101930,7 +102131,7 @@ execution scope cleanup failed`, true)
101930
102131
  try {
101931
102132
  receipt = await new Promise((resolve8, reject) => {
101932
102133
  let settled = false;
101933
- const child = spawn3(process.execPath, [this.cliEntryPath, ...args], {
102134
+ const child = spawn4(process.execPath, [this.cliEntryPath, ...args], {
101934
102135
  cwd: input.cwd,
101935
102136
  env: { ...process.env, ...debugChildEnvironment() },
101936
102137
  stdio: ["ignore", "pipe", "pipe"],
@@ -102295,7 +102496,7 @@ function requirePayloadHeaderField(value, field) {
102295
102496
  return value;
102296
102497
  }
102297
102498
  function parsePayloadLineDecision(value, index2) {
102298
- if (!isRecord16(value) || typeof value.candidate_id !== "string") {
102499
+ if (!isRecord17(value) || typeof value.candidate_id !== "string") {
102299
102500
  throw new ContextError(ExitCode.UserError, `review payload line ${index2} must contain candidate_id and status`, {
102300
102501
  category: ErrorCategory.UserInputInvalid
102301
102502
  });
@@ -102308,7 +102509,7 @@ function parsePayloadLineDecision(value, index2) {
102308
102509
  function parsePayloadScope(value) {
102309
102510
  if (value === undefined)
102310
102511
  return;
102311
- if (!isRecord16(value) || typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || typeof value.ids_sha256 !== "string" || !/^[a-f0-9]{64}$/iu.test(value.ids_sha256)) {
102512
+ if (!isRecord17(value) || typeof value.count !== "number" || !Number.isInteger(value.count) || value.count < 0 || typeof value.ids_sha256 !== "string" || !/^[a-f0-9]{64}$/iu.test(value.ids_sha256)) {
102312
102513
  throw new ContextError(ExitCode.UserError, "review payload scope must contain count and ids_sha256", {
102313
102514
  category: ErrorCategory.UserInputInvalid
102314
102515
  });
@@ -102347,7 +102548,7 @@ function parsePayloadScope(value) {
102347
102548
  }
102348
102549
  function parsePayloadValues(parsed) {
102349
102550
  const first = parsed[0];
102350
- if (!isRecord16(first)) {
102551
+ if (!isRecord17(first)) {
102351
102552
  throw new ContextError(ExitCode.UserError, "review payload header must be a JSON object", {
102352
102553
  category: ErrorCategory.UserInputInvalid
102353
102554
  });
@@ -103259,7 +103460,7 @@ async function runManagedUntil(input) {
103259
103460
  const resourceReceipts = input.resourceReceiptsReference === undefined ? undefined : await parseWorkflowResourceReceipts(input.resourceReceiptsReference, found.projectRoot);
103260
103461
  const runtime = new WorkspaceExecutionRuntime({
103261
103462
  projectRoot: found.projectRoot,
103262
- cliEntryPath: fileURLToPath7(input.cliModuleUrl),
103463
+ cliEntryPath: fileURLToPath8(input.cliModuleUrl),
103263
103464
  inProcess: createWorkflowInProcessExecutor()
103264
103465
  });
103265
103466
  let result;
@@ -103404,10 +103605,10 @@ function registerDebugCommands(program2) {
103404
103605
 
103405
103606
  // src/commands/cleanClaudePluginCache.ts
103406
103607
  init_cliFeedback();
103407
- import { existsSync as existsSync39 } from "node:fs";
103608
+ import { existsSync as existsSync40 } from "node:fs";
103408
103609
  import { readdir as readdir19, rm as rm16 } from "node:fs/promises";
103409
103610
  import { homedir } from "node:os";
103410
- import { join as join63 } from "node:path";
103611
+ import { join as join64 } from "node:path";
103411
103612
  var ORPHAN_MARKER = ".orphaned_at";
103412
103613
  var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
103413
103614
  var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
@@ -103416,7 +103617,7 @@ async function cleanClaudePluginCache(opts = {}) {
103416
103617
  const lines = [];
103417
103618
  let removed = 0;
103418
103619
  let scanned = 0;
103419
- if (!existsSync39(cacheRoot)) {
103620
+ if (!existsSync40(cacheRoot)) {
103420
103621
  lines.push("· claude plugin cache: missing — nothing to clean");
103421
103622
  return { lines, removed, scanned };
103422
103623
  }
@@ -103424,20 +103625,20 @@ async function cleanClaudePluginCache(opts = {}) {
103424
103625
  for (const mp of marketplaces) {
103425
103626
  if (!mp.isDirectory())
103426
103627
  continue;
103427
- const mpDir = join63(cacheRoot, mp.name);
103628
+ const mpDir = join64(cacheRoot, mp.name);
103428
103629
  const plugins = await readdir19(mpDir, { withFileTypes: true });
103429
103630
  for (const pl of plugins) {
103430
103631
  if (!pl.isDirectory())
103431
103632
  continue;
103432
- const plDir = join63(mpDir, pl.name);
103633
+ const plDir = join64(mpDir, pl.name);
103433
103634
  const versions = await readdir19(plDir, { withFileTypes: true });
103434
103635
  for (const ver of versions) {
103435
103636
  if (!ver.isDirectory())
103436
103637
  continue;
103437
103638
  scanned += 1;
103438
- const verDir = join63(plDir, ver.name);
103439
- const markerPath = join63(verDir, ORPHAN_MARKER);
103440
- if (!existsSync39(markerPath))
103639
+ const verDir = join64(plDir, ver.name);
103640
+ const markerPath = join64(verDir, ORPHAN_MARKER);
103641
+ if (!existsSync40(markerPath))
103441
103642
  continue;
103442
103643
  const label3 = `${mp.name}/${pl.name}/${ver.name}`;
103443
103644
  if (opts.dryRun) {
@@ -103468,7 +103669,7 @@ function resolveClaudePluginCacheRoot(opts) {
103468
103669
  if (explicitRoot)
103469
103670
  return explicitRoot;
103470
103671
  const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
103471
- return join63(home, ".claude", "plugins", "cache");
103672
+ return join64(home, ".claude", "plugins", "cache");
103472
103673
  }
103473
103674
  async function isEmptyDir(dir) {
103474
103675
  try {
@@ -103494,17 +103695,17 @@ async function runDoctorCleanClaudePluginCache(opts = {}) {
103494
103695
  }
103495
103696
 
103496
103697
  // src/commands/cleanCache.ts
103497
- import { existsSync as existsSync41 } from "node:fs";
103698
+ import { existsSync as existsSync42 } from "node:fs";
103498
103699
  import { readdir as readdir20, rm as rm17 } from "node:fs/promises";
103499
- import { join as join67 } from "node:path";
103700
+ import { join as join68 } from "node:path";
103500
103701
 
103501
103702
  // src/incremental/cache.ts
103502
- import { basename as basename10, dirname as dirname39, isAbsolute as isAbsolute11, join as join66, resolve as resolve27 } from "node:path";
103703
+ import { basename as basename10, dirname as dirname40, isAbsolute as isAbsolute11, join as join67, resolve as resolve27 } from "node:path";
103503
103704
 
103504
103705
  // src/lib/workspaceLayout.ts
103505
103706
  var import_yaml32 = __toESM(require_dist3(), 1);
103506
- import { existsSync as existsSync40, readFileSync as readFileSync8, statSync as statSync2 } from "node:fs";
103507
- import { dirname as dirname38, join as join64, parse as parse7, resolve as resolve26 } from "node:path";
103707
+ import { existsSync as existsSync41, readFileSync as readFileSync9, statSync as statSync2 } from "node:fs";
103708
+ import { dirname as dirname39, join as join65, parse as parse7, resolve as resolve26 } from "node:path";
103508
103709
  function isDirectorySafe(path4) {
103509
103710
  try {
103510
103711
  return statSync2(path4).isDirectory();
@@ -103513,11 +103714,11 @@ function isDirectorySafe(path4) {
103513
103714
  }
103514
103715
  }
103515
103716
  function hasRootLayoutMarker(dir) {
103516
- const configPath = join64(dir, "config.yaml");
103517
- if (!existsSync40(configPath))
103717
+ const configPath = join65(dir, "config.yaml");
103718
+ if (!existsSync41(configPath))
103518
103719
  return false;
103519
103720
  try {
103520
- const parsed = import_yaml32.default.parse(readFileSync8(configPath, "utf8"));
103721
+ const parsed = import_yaml32.default.parse(readFileSync9(configPath, "utf8"));
103521
103722
  if (!parsed || typeof parsed !== "object")
103522
103723
  return false;
103523
103724
  const workspace = parsed.workspace;
@@ -103530,8 +103731,8 @@ function hasRootLayoutMarker(dir) {
103530
103731
  }
103531
103732
  function findWorkspaceAt(dir) {
103532
103733
  const root2 = resolve26(dir);
103533
- const embedded = join64(root2, ".context");
103534
- if (existsSync40(join64(embedded, "config.yaml")) && isDirectorySafe(embedded)) {
103734
+ const embedded = join65(root2, ".context");
103735
+ if (existsSync41(join65(embedded, "config.yaml")) && isDirectorySafe(embedded)) {
103535
103736
  return { ctxDir: embedded, workspaceRoot: root2, layout: "embedded" };
103536
103737
  }
103537
103738
  if (hasRootLayoutMarker(root2)) {
@@ -103548,7 +103749,7 @@ function findNearestWorkspace(startDir = process.cwd()) {
103548
103749
  return found;
103549
103750
  if (dir === root2)
103550
103751
  return null;
103551
- const parent = dirname38(dir);
103752
+ const parent = dirname39(dir);
103552
103753
  if (parent === dir)
103553
103754
  return null;
103554
103755
  dir = parent;
@@ -103556,9 +103757,9 @@ function findNearestWorkspace(startDir = process.cwd()) {
103556
103757
  }
103557
103758
 
103558
103759
  // src/lib/userCache.ts
103559
- import { basename as basename9, join as join65 } from "node:path";
103760
+ import { basename as basename9, join as join66 } from "node:path";
103560
103761
  function workspaceLocalUserCacheRoot(ctxDir) {
103561
- return join65(ctxDir, ".tmp", "context-cli");
103762
+ return join66(ctxDir, ".tmp", "context-cli");
103562
103763
  }
103563
103764
 
103564
103765
  // src/incremental/cache.ts
@@ -103568,7 +103769,7 @@ function resolveCachePath(value) {
103568
103769
  }
103569
103770
  function workspaceCacheHome(workspaceRoot) {
103570
103771
  const location = findWorkspaceAt(workspaceRoot);
103571
- return workspaceLocalUserCacheRoot(location?.ctxDir ?? join66(workspaceRoot, ".context"));
103772
+ return workspaceLocalUserCacheRoot(location?.ctxDir ?? join67(workspaceRoot, ".context"));
103572
103773
  }
103573
103774
  function resolveCacheHome(input = {}) {
103574
103775
  const explicit = input.cacheHome ?? process.env.C4A_CONTEXT_CACHE_HOME;
@@ -103577,24 +103778,24 @@ function resolveCacheHome(input = {}) {
103577
103778
  if (input.workspaceRoot !== undefined)
103578
103779
  return workspaceCacheHome(resolveCachePath(input.workspaceRoot));
103579
103780
  const nearest = findNearestWorkspace(process.cwd());
103580
- return workspaceLocalUserCacheRoot(nearest?.ctxDir ?? join66(process.cwd(), ".context"));
103781
+ return workspaceLocalUserCacheRoot(nearest?.ctxDir ?? join67(process.cwd(), ".context"));
103581
103782
  }
103582
103783
 
103583
103784
  // src/commands/cleanCache.ts
103584
103785
  async function countFiles2(dir) {
103585
- if (!existsSync41(dir))
103786
+ if (!existsSync42(dir))
103586
103787
  return 0;
103587
103788
  let count = 0;
103588
103789
  for (const entry of await readdir20(dir, { withFileTypes: true })) {
103589
- const full = join67(dir, entry.name);
103790
+ const full = join68(dir, entry.name);
103590
103791
  count += entry.isDirectory() ? await countFiles2(full) : 1;
103591
103792
  }
103592
103793
  return count;
103593
103794
  }
103594
103795
  async function inspectAllRetrievalCache() {
103595
103796
  const cacheHome = resolveCacheHome();
103596
- const cacheRoot = join67(cacheHome, "retrieval");
103597
- const projectIds = existsSync41(cacheRoot) ? (await readdir20(cacheRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort() : [];
103797
+ const cacheRoot = join68(cacheHome, "retrieval");
103798
+ const projectIds = existsSync42(cacheRoot) ? (await readdir20(cacheRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort() : [];
103598
103799
  const files = await countFiles2(cacheRoot);
103599
103800
  return { cacheRoot, projects: projectIds.length, files, projectIds };
103600
103801
  }
@@ -103612,8 +103813,6 @@ async function cleanAllRetrievalCache() {
103612
103813
  init_errors();
103613
103814
  init_cliFeedback();
103614
103815
  init_exitCode();
103615
- init_workspace();
103616
- init_packageTemplateReview();
103617
103816
 
103618
103817
  // src/project/sourceCommands.ts
103619
103818
  import { readFile as readFile54 } from "node:fs/promises";
@@ -103628,9 +103827,9 @@ init_cliFeedback();
103628
103827
  init_errors();
103629
103828
  init_exitCode();
103630
103829
  import { execFile as execFile6 } from "node:child_process";
103631
- import { existsSync as existsSync42 } from "node:fs";
103830
+ import { existsSync as existsSync43 } from "node:fs";
103632
103831
  import { lstat as lstat3, mkdir as mkdir31, readlink as readlink2, realpath as realpath4, rm as rm18, symlink as symlink2 } from "node:fs/promises";
103633
- import { basename as basename11, dirname as dirname40, isAbsolute as isAbsolute12, relative as relative20, resolve as resolve28 } from "node:path";
103832
+ import { basename as basename11, dirname as dirname41, isAbsolute as isAbsolute12, relative as relative20, resolve as resolve28 } from "node:path";
103634
103833
  import { promisify as promisify6 } from "node:util";
103635
103834
  init_writeLock();
103636
103835
  var execFileAsync6 = promisify6(execFile6);
@@ -103772,7 +103971,7 @@ async function git2(cwd, args) {
103772
103971
  }
103773
103972
  async function resolveGitRoot2(path4) {
103774
103973
  const root2 = await git2(path4, ["rev-parse", "--show-toplevel"]);
103775
- if (root2.length === 0 || !existsSync42(root2)) {
103974
+ if (root2.length === 0 || !existsSync43(root2)) {
103776
103975
  throw userInputError3(`local repository path is not a Git checkout: ${path4}`, { path: path4 });
103777
103976
  }
103778
103977
  return realpath4(root2);
@@ -103793,13 +103992,13 @@ async function verifyCheckout(input) {
103793
103992
  }
103794
103993
  async function cloneCheckout(input) {
103795
103994
  const target = resolve28(input.projectRoot, input.target ?? `.tmp/repo/${repositorySlug(input.remote)}-${input.ref.slice(0, 12)}`);
103796
- if (existsSync42(target)) {
103995
+ if (existsSync43(target)) {
103797
103996
  throw userInputError3(`clone target already exists: ${target}`, {
103798
103997
  target,
103799
103998
  next: `Use local mode with path ${JSON.stringify(target)} after inspecting the existing checkout.`
103800
103999
  });
103801
104000
  }
103802
- await mkdir31(dirname40(target), { recursive: true });
104001
+ await mkdir31(dirname41(target), { recursive: true });
103803
104002
  const cloneArgs = ["clone", "--no-checkout", "--depth=1", "--filter=blob:none", input.remote, target];
103804
104003
  try {
103805
104004
  await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
@@ -103848,7 +104047,7 @@ async function bindLocalAlias(input) {
103848
104047
  const stats = await lstat3(alias).catch(() => null);
103849
104048
  if (stats !== null) {
103850
104049
  if (stats.isSymbolicLink()) {
103851
- const actual = resolve28(dirname40(alias), await readlink2(alias));
104050
+ const actual = resolve28(dirname41(alias), await readlink2(alias));
103852
104051
  const actualReal = await realpath4(actual).catch(() => null);
103853
104052
  if (actualReal !== null && actualReal === await realpath4(input.checkout))
103854
104053
  return;
@@ -103864,8 +104063,8 @@ async function bindLocalAlias(input) {
103864
104063
  });
103865
104064
  }
103866
104065
  }
103867
- await mkdir31(dirname40(alias), { recursive: true });
103868
- await symlink2(relative20(dirname40(alias), input.checkout) || ".", alias);
104066
+ await mkdir31(dirname41(alias), { recursive: true });
104067
+ await symlink2(relative20(dirname41(alias), input.checkout) || ".", alias);
103869
104068
  }
103870
104069
  function selectPhysicalGroup(sources, selector) {
103871
104070
  const direct = selectRepoSources(sources, selector);
@@ -103952,13 +104151,13 @@ async function restoreRepositorySources(input) {
103952
104151
  }
103953
104152
 
103954
104153
  // src/project/sourceDocumentStatus.ts
103955
- import { existsSync as existsSync43 } from "node:fs";
104154
+ import { existsSync as existsSync44 } from "node:fs";
103956
104155
  import { readFile as readFile51 } from "node:fs/promises";
103957
- import { join as join69 } from "node:path";
104156
+ import { join as join70 } from "node:path";
103958
104157
 
103959
104158
  // src/project/sourceCommandViews.ts
103960
104159
  import { readFile as readFile50 } from "node:fs/promises";
103961
- import { join as join68 } from "node:path";
104160
+ import { join as join69 } from "node:path";
103962
104161
  init_workspace();
103963
104162
  function repoSourceAgentView(source2) {
103964
104163
  return {
@@ -104020,7 +104219,7 @@ async function fileSourceAgentViewWithNextAction(input) {
104020
104219
  };
104021
104220
  }
104022
104221
  function documentSourceManifestPath(source2) {
104023
- return source2.snapshot?.manifest ?? join68(source2.materializedAt, "manifest.json");
104222
+ return source2.snapshot?.manifest ?? join69(source2.materializedAt, "manifest.json");
104024
104223
  }
104025
104224
  async function fileSourceDocumentSiteHint(input) {
104026
104225
  const detection = await detectDocumentSiteFiles({
@@ -104030,7 +104229,7 @@ async function fileSourceDocumentSiteHint(input) {
104030
104229
  let snapshotConfigured = false;
104031
104230
  const manifest = documentSourceManifestPath(input.source);
104032
104231
  try {
104033
- const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile50(join68(input.projectRoot, manifest), "utf8")), input.source.name);
104232
+ const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile50(join69(input.projectRoot, manifest), "utf8")), input.source.name);
104034
104233
  snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
104035
104234
  } catch {
104036
104235
  snapshotConfigured = false;
@@ -104061,12 +104260,12 @@ async function larkSourceAgentViewWithNextAction(input) {
104061
104260
 
104062
104261
  // src/project/sourceDocumentStatus.ts
104063
104262
  function documentSourceManifestPath2(source2) {
104064
- return source2.snapshot?.manifest ?? join69(source2.materializedAt, "manifest.json");
104263
+ return source2.snapshot?.manifest ?? join70(source2.materializedAt, "manifest.json");
104065
104264
  }
104066
104265
  async function documentSnapshotState(input) {
104067
104266
  const manifest = documentSourceManifestPath2(input.source);
104068
- const manifestPath = join69(input.projectRoot, manifest);
104069
- if (!existsSync43(manifestPath)) {
104267
+ const manifestPath = join70(input.projectRoot, manifest);
104268
+ if (!existsSync44(manifestPath)) {
104070
104269
  return {
104071
104270
  snapshotReady: false,
104072
104271
  state: "needs-capture",
@@ -104144,7 +104343,7 @@ async function documentSnapshotState(input) {
104144
104343
  const missing = [
104145
104344
  ...parsed.files.map((file) => file.path),
104146
104345
  ...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
104147
- ].find((path4) => !existsSync43(join69(input.projectRoot, input.source.materializedAt, path4)));
104346
+ ].find((path4) => !existsSync44(join70(input.projectRoot, input.source.materializedAt, path4)));
104148
104347
  if (missing !== undefined) {
104149
104348
  return {
104150
104349
  snapshotReady: false,
@@ -104216,7 +104415,7 @@ async function inspectDocumentSources(input) {
104216
104415
  // src/project/documentSourceRegistration.ts
104217
104416
  import { createHash as createHash27 } from "node:crypto";
104218
104417
  import { readFile as readFile52, realpath as realpath5 } from "node:fs/promises";
104219
- import { basename as basename12, extname as extname13, isAbsolute as isAbsolute13, join as join70, relative as relative21, resolve as resolve29 } from "node:path";
104418
+ import { basename as basename12, extname as extname13, isAbsolute as isAbsolute13, join as join71, relative as relative21, resolve as resolve29 } from "node:path";
104220
104419
  init_atomicWrite();
104221
104420
  init_cliFeedback();
104222
104421
  init_errors();
@@ -104317,7 +104516,7 @@ function assertSafeFileInclude(value) {
104317
104516
  }
104318
104517
  async function readRegistryDocument(projectRoot, registryPath2) {
104319
104518
  try {
104320
- const content3 = await readFile52(join70(projectRoot, registryPath2), "utf8");
104519
+ const content3 = await readFile52(join71(projectRoot, registryPath2), "utf8");
104321
104520
  return content3.trim().length === 0 ? { sources: [] } : import_yaml33.default.parse(content3);
104322
104521
  } catch (error) {
104323
104522
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -104435,7 +104634,7 @@ async function addFileSourceUnlocked(input) {
104435
104634
  const record2 = entry2;
104436
104635
  return record2.name !== input.name && record2.id !== input.name;
104437
104636
  }), nextEntry];
104438
- await atomicWriteFile(join70(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104637
+ await atomicWriteFile(join71(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104439
104638
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
104440
104639
  const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
104441
104640
  if (entry === undefined) {
@@ -104491,7 +104690,7 @@ async function addLarkSourceUnlocked(input) {
104491
104690
  const record2 = entry2;
104492
104691
  return record2.name !== input.name && record2.id !== input.name;
104493
104692
  }), nextEntry];
104494
- await atomicWriteFile(join70(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104693
+ await atomicWriteFile(join71(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml33.default.stringify({ sources: nextSources }));
104495
104694
  const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
104496
104695
  const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
104497
104696
  if (entry === undefined) {
@@ -104679,10 +104878,10 @@ async function registerSourceBatch(input) {
104679
104878
  }
104680
104879
 
104681
104880
  // src/project/sourceRemoval.ts
104682
- import { existsSync as existsSync44 } from "node:fs";
104881
+ import { existsSync as existsSync45 } from "node:fs";
104683
104882
  import { createHash as createHash28 } from "node:crypto";
104684
104883
  import { readFile as readFile53, readdir as readdir21, rm as rm19 } from "node:fs/promises";
104685
- import { isAbsolute as isAbsolute14, join as join71, relative as relative22, resolve as resolve30, sep as sep6 } from "node:path";
104884
+ import { isAbsolute as isAbsolute14, join as join72, relative as relative22, resolve as resolve30, sep as sep6 } from "node:path";
104686
104885
  var import_yaml34 = __toESM(require_dist3(), 1);
104687
104886
  init_atomicWrite();
104688
104887
  init_cliFeedback();
@@ -104721,8 +104920,8 @@ function collectStrings(value, output) {
104721
104920
  }
104722
104921
  }
104723
104922
  async function yamlReferences(input) {
104724
- const absolutePath = join71(input.projectRoot, input.path);
104725
- if (!existsSync44(absolutePath))
104923
+ const absolutePath = join72(input.projectRoot, input.path);
104924
+ if (!existsSync45(absolutePath))
104726
104925
  return false;
104727
104926
  const parsed = import_yaml34.default.parse(await readFile53(absolutePath, "utf8"));
104728
104927
  const strings = [];
@@ -104829,8 +105028,8 @@ function removeDocumentEntry(document4, source2) {
104829
105028
  }
104830
105029
  async function registryRemovalWrite(projectRoot, source2) {
104831
105030
  const path4 = registryPath2(source2.type);
104832
- const absolutePath = join71(projectRoot, path4);
104833
- const document4 = existsSync44(absolutePath) ? import_yaml34.default.parse(await readFile53(absolutePath, "utf8")) : { sources: [] };
105031
+ const absolutePath = join72(projectRoot, path4);
105032
+ const document4 = existsSync45(absolutePath) ? import_yaml34.default.parse(await readFile53(absolutePath, "utf8")) : { sources: [] };
104834
105033
  return {
104835
105034
  path: absolutePath,
104836
105035
  bytes: import_yaml34.default.stringify(removeDocumentEntry(document4, source2))
@@ -104848,7 +105047,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
104848
105047
  return absolute;
104849
105048
  }
104850
105049
  function safeManagedManifestPath(projectRoot, source2) {
104851
- const manifest = source2.manifest ?? join71(source2.materializedAt, "manifest.json");
105050
+ const manifest = source2.manifest ?? join72(source2.materializedAt, "manifest.json");
104852
105051
  if (isAbsolute14(manifest))
104853
105052
  throw unsafeOwnership(source2, manifest);
104854
105053
  const absolute = resolve30(projectRoot, manifest);
@@ -104954,7 +105153,7 @@ async function createRemovalPlan(projectRoot, selector) {
104954
105153
  }
104955
105154
  } else {
104956
105155
  const materializedPath = safeManagedMaterializedPath(projectRoot, source2);
104957
- if (materializedPath !== undefined && sharedMaterializedBy.length === 0 && existsSync44(materializedPath)) {
105156
+ if (materializedPath !== undefined && sharedMaterializedBy.length === 0 && existsSync45(materializedPath)) {
104958
105157
  absoluteRemovals.push(materializedPath);
104959
105158
  cleanup = {
104960
105159
  mode: "exclusive-materialization",
@@ -105000,9 +105199,9 @@ function publicRemovalResult(plan, action) {
105000
105199
  };
105001
105200
  }
105002
105201
  async function pruneExtractRuntime(projectRoot, source2) {
105003
- const fingerprintPath = join71(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
105202
+ const fingerprintPath = join72(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
105004
105203
  const removedPhaseIds = new Set;
105005
- if (existsSync44(fingerprintPath)) {
105204
+ if (existsSync45(fingerprintPath)) {
105006
105205
  const parsed = JSON.parse(await readFile53(fingerprintPath, "utf8"));
105007
105206
  const phases = parsed.phases ?? {};
105008
105207
  const next = Object.fromEntries(Object.entries(phases).filter(([phaseId, raw]) => {
@@ -105017,20 +105216,20 @@ async function pruneExtractRuntime(projectRoot, source2) {
105017
105216
  await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next }, null, 2)}
105018
105217
  `);
105019
105218
  }
105020
- const symbolPath = join71(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
105021
- if (existsSync44(symbolPath)) {
105219
+ const symbolPath = join72(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
105220
+ if (existsSync45(symbolPath)) {
105022
105221
  const parsed = JSON.parse(await readFile53(symbolPath, "utf8"));
105023
105222
  const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
105024
105223
  const phaseFingerprints = Object.fromEntries(Object.entries(parsed.phaseFingerprints ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
105025
105224
  await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
105026
105225
  `);
105027
105226
  }
105028
- const snapshotRoot = join71(projectRoot, ".tmp/context-runtime/extract/candidates");
105227
+ const snapshotRoot = join72(projectRoot, ".tmp/context-runtime/extract/candidates");
105029
105228
  const visit3 = async (directory) => {
105030
- if (!existsSync44(directory))
105229
+ if (!existsSync45(directory))
105031
105230
  return;
105032
105231
  for (const entry of await readdir21(directory, { withFileTypes: true })) {
105033
- const path4 = join71(directory, entry.name);
105232
+ const path4 = join72(directory, entry.name);
105034
105233
  if (entry.isDirectory()) {
105035
105234
  await visit3(path4);
105036
105235
  continue;
@@ -105080,7 +105279,7 @@ async function removeProjectSource(input) {
105080
105279
  });
105081
105280
  }
105082
105281
  await applyAtomicFileBatch({
105083
- transactionRoot: join71(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
105282
+ transactionRoot: join72(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
105084
105283
  writes: [plan.registryWrite, ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
105085
105284
  removals: plan.absoluteRemovals
105086
105285
  });
@@ -105478,16 +105677,147 @@ the CLI derives a lowercase path-safe module and rejects duplicate batch identit
105478
105677
  });
105479
105678
  }
105480
105679
 
105680
+ // src/cli.ts
105681
+ init_debugTrace();
105682
+
105683
+ // src/registerProjectLifecycleCommands.ts
105684
+ init_cliFeedback();
105685
+ init_errors();
105686
+ init_workspace();
105687
+ init_exitCode();
105688
+ function registerProjectInitCommand(program2) {
105689
+ program2.command("init [project-dir]").description("Initialize a project-local context workspace").option("--name <name>", "display/package name override").option("--language <language>", "workspace and starter-template language: en | zh-CN").option("--dev", "initialize with the locally linked @c4a/context SDK").option("--debug", "enable workspace-local command and Agent Graph tracing").option("--allow-nonempty", "after explicit confirmation, preserve existing files and initialize inside a non-empty non-Context directory").action(async (projectDir, options) => {
105690
+ const targetRoot = resolveContextProjectInitTarget(process.cwd(), projectDir);
105691
+ const wasContextWorkspace = isContextProjectRoot(targetRoot);
105692
+ const result = await initContextProject({
105693
+ cwd: process.cwd(),
105694
+ ...projectDir !== undefined ? { projectDir } : {},
105695
+ ...typeof options.name === "string" ? { name: options.name } : {},
105696
+ ...typeof options.language === "string" ? { language: projectLanguage(options.language) } : {},
105697
+ ...options.dev === true ? { dev: true } : {},
105698
+ ...options.debug === true ? { debug: true } : {},
105699
+ ...options.allowNonempty === true ? { allowNonempty: true } : {}
105700
+ });
105701
+ process.stdout.write(formatProjectInitResult(result));
105702
+ if (!wasContextWorkspace) {
105703
+ queueContextRuntimeEvent({
105704
+ cwd: result.projectRoot,
105705
+ kind: "workspace.initialized",
105706
+ properties: {
105707
+ init_mode: result.kept.length > 0 ? "nonempty_existing" : "new",
105708
+ language: result.language,
105709
+ created_file_count: result.created.length
105710
+ }
105711
+ });
105712
+ }
105713
+ });
105714
+ }
105715
+ function registerProjectStatusCommand(program2) {
105716
+ program2.command("status").description("Print workspace overview and suggested next actions").option("--format <format>", "output format: table | json", "table").option("--view <view>", "with --format json, output view: summary | full", "summary").option("--managed", "use explicit current-conversation managed approval for this status loop").option("--resource-receipts <json-or-@file>", "current-conversation Agent Graph resource read receipts").addOption(new Option("--authority <authority>", "current-conversation scoped authority granted by the user; repeatable").argParser(collectWorkflowAuthorityOption).default([])).action(async (options) => {
105717
+ const rootOptions = program2.opts();
105718
+ const resourceReceiptsReference = typeof options.resourceReceipts === "string" ? options.resourceReceipts : typeof rootOptions.workflowResourceReceipts === "string" ? rootOptions.workflowResourceReceipts : undefined;
105719
+ const resourceReceipts = resourceReceiptsReference !== undefined ? await parseWorkflowResourceReceipts(resourceReceiptsReference, process.cwd()) : undefined;
105720
+ if (await runProjectStatusCommand({
105721
+ cwd: process.cwd(),
105722
+ format: options.format === "json" ? "json" : "table",
105723
+ view: options.view === "full" ? "full" : "summary",
105724
+ managed: options.managed === true,
105725
+ authorities: workflowAuthorities(options.authority),
105726
+ ...resourceReceipts === undefined ? {} : { resourceReceipts },
105727
+ ...resourceReceiptsReference === undefined ? {} : { resourceReceiptsReference },
105728
+ onSuccess: (status) => {
105729
+ queueContextRuntimeEvent({
105730
+ cwd: status.projectRoot,
105731
+ kind: "workspace.active",
105732
+ properties: { workflow_status: status.workflow.status }
105733
+ });
105734
+ }
105735
+ })) {
105736
+ return;
105737
+ }
105738
+ throw new ContextError(ExitCode.WorkspaceStateError, "status requires a context project workspace", {
105739
+ category: ErrorCategory.WorkspaceNotFound
105740
+ });
105741
+ });
105742
+ }
105743
+ function registerProjectCloseAndBuildCommands(program2) {
105744
+ program2.command("close").description("Close approved project knowledge by deriving structure and running final verification").option("--format <format>", "output format: text | json", "text").action(async (options) => {
105745
+ if (options.format !== "text" && options.format !== "json") {
105746
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
105747
+ category: ErrorCategory.UserInputInvalid
105748
+ });
105749
+ }
105750
+ if (await runProjectCloseCommand({
105751
+ cwd: process.cwd(),
105752
+ format: options.format === "json" ? "json" : "text"
105753
+ })) {
105754
+ return;
105755
+ }
105756
+ throw new ContextError(ExitCode.WorkspaceStateError, "close requires a context project workspace", {
105757
+ category: ErrorCategory.WorkspaceNotFound
105758
+ });
105759
+ });
105760
+ program2.command("build").description("Build declared project packages").option("--format <format>", "output format: text | json", "text").option("--verbose", "include per-file build changes in JSON output").action(async (options) => {
105761
+ if (options.format !== "text" && options.format !== "json") {
105762
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
105763
+ category: ErrorCategory.UserInputInvalid
105764
+ });
105765
+ }
105766
+ if (await runProjectBuildCommand({
105767
+ cwd: process.cwd(),
105768
+ format: options.format === "json" ? "json" : "text",
105769
+ verbose: options.verbose === true
105770
+ })) {
105771
+ return;
105772
+ }
105773
+ throw new ContextError(ExitCode.WorkspaceStateError, "build requires a context project workspace", {
105774
+ category: ErrorCategory.WorkspaceNotFound
105775
+ });
105776
+ });
105777
+ }
105778
+ function registerProjectVerifyCommand(program2) {
105779
+ program2.command("verify").description("Validate knowledge workspace").option("--format <format>", "output format: table | json", "table").option("--compact", "return grouped diagnostics without the complete issue list").option("--view <view>", "read a verification view: diagnostics").option("--page-size <n>", "with --view diagnostics, limit returned issues").option("--page-token <token>", "with --view diagnostics, continue pagination").action(async (options) => {
105780
+ if (options.format !== "table" && options.format !== "json") {
105781
+ throw new ContextError(ExitCode.UserError, "--format must be table or json", {
105782
+ category: ErrorCategory.UserInputInvalid
105783
+ });
105784
+ }
105785
+ if (options.view !== undefined && options.view !== "diagnostics") {
105786
+ throw new ContextError(ExitCode.UserError, "--view must be diagnostics", {
105787
+ category: ErrorCategory.UserInputInvalid
105788
+ });
105789
+ }
105790
+ if (options.view === "diagnostics" && options.format !== "json") {
105791
+ throw new ContextError(ExitCode.UserError, "--view diagnostics requires --format json", {
105792
+ category: ErrorCategory.UserInputInvalid
105793
+ });
105794
+ }
105795
+ if (await runProjectVerifyCommand({
105796
+ cwd: process.cwd(),
105797
+ format: options.format === "json" ? "json" : "table",
105798
+ ...options.compact === true ? { compact: true } : {},
105799
+ ...options.view === "diagnostics" ? { view: "diagnostics" } : {},
105800
+ ...typeof options.pageSize === "string" ? { pageSize: options.pageSize } : {},
105801
+ ...typeof options.pageToken === "string" ? { pageToken: options.pageToken } : {}
105802
+ })) {
105803
+ return;
105804
+ }
105805
+ throw new ContextError(ExitCode.WorkspaceStateError, "verify requires a context project workspace", {
105806
+ category: ErrorCategory.WorkspaceNotFound
105807
+ });
105808
+ });
105809
+ }
105810
+
105481
105811
  // src/project/pluginInstall.ts
105482
105812
  init_cliFeedback();
105483
105813
  init_errors();
105484
105814
  init_exitCode();
105485
- import { existsSync as existsSync45 } from "node:fs";
105815
+ import { existsSync as existsSync46 } from "node:fs";
105486
105816
  import { cp, mkdir as mkdir32, readdir as readdir22, readFile as readFile55, rename as rename5, rm as rm20, writeFile as writeFile27 } from "node:fs/promises";
105487
105817
  import { execFile as execFile7 } from "node:child_process";
105488
105818
  import { homedir as homedir2 } from "node:os";
105489
- import { dirname as dirname41, join as join72, resolve as resolve32 } from "node:path";
105490
- import { fileURLToPath as fileURLToPath8 } from "node:url";
105819
+ import { dirname as dirname42, join as join73, resolve as resolve32 } from "node:path";
105820
+ import { fileURLToPath as fileURLToPath9 } from "node:url";
105491
105821
  import { promisify as promisify7 } from "node:util";
105492
105822
  var execFileAsync7 = promisify7(execFile7);
105493
105823
  var MARKETPLACE_NAME = "c4a";
@@ -105526,10 +105856,10 @@ function pluginAgentOption(value) {
105526
105856
  }
105527
105857
  function packageCandidateDirs() {
105528
105858
  const dirs = [];
105529
- let dir = dirname41(fileURLToPath8(import.meta.url));
105859
+ let dir = dirname42(fileURLToPath9(import.meta.url));
105530
105860
  for (let index2 = 0;index2 < 8; index2++) {
105531
105861
  dirs.push(dir);
105532
- const parent = dirname41(dir);
105862
+ const parent = dirname42(dir);
105533
105863
  if (parent === dir)
105534
105864
  break;
105535
105865
  dir = parent;
@@ -105542,13 +105872,13 @@ function pluginRootCandidates() {
105542
105872
  return [resolve32(envRoot)];
105543
105873
  const candidates = [];
105544
105874
  for (const dir of packageCandidateDirs()) {
105545
- candidates.push(join72(dir, "plugins"));
105546
- candidates.push(join72(dir, "dist", "plugins"));
105875
+ candidates.push(join73(dir, "plugins"));
105876
+ candidates.push(join73(dir, "dist", "plugins"));
105547
105877
  }
105548
105878
  return [...new Set(candidates)];
105549
105879
  }
105550
105880
  function isInstallablePluginRoot(root2) {
105551
- return existsSync45(join72(root2, ".claude-plugin", "marketplace.json")) && existsSync45(join72(root2, ".agents", "plugins", "marketplace.json")) && existsSync45(join72(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync45(join72(root2, "codex", ".codex-plugin", "plugin.json"));
105881
+ return existsSync46(join73(root2, ".claude-plugin", "marketplace.json")) && existsSync46(join73(root2, ".agents", "plugins", "marketplace.json")) && existsSync46(join73(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync46(join73(root2, "codex", ".codex-plugin", "plugin.json"));
105552
105882
  }
105553
105883
  function resolveBundledPluginsRoot() {
105554
105884
  const candidates = pluginRootCandidates();
@@ -105613,14 +105943,14 @@ function failedAgentResult(agent, error) {
105613
105943
  };
105614
105944
  }
105615
105945
  function codexHome() {
105616
- return process.env.CODEX_HOME?.trim() || join72(homedir2(), ".codex");
105946
+ return process.env.CODEX_HOME?.trim() || join73(homedir2(), ".codex");
105617
105947
  }
105618
105948
  function claudePluginCacheRoot() {
105619
105949
  const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
105620
105950
  if (explicitRoot)
105621
105951
  return explicitRoot;
105622
105952
  const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
105623
- return join72(home, ".claude", "plugins", "cache");
105953
+ return join73(home, ".claude", "plugins", "cache");
105624
105954
  }
105625
105955
  function blockHeader(line) {
105626
105956
  const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
@@ -105671,7 +106001,7 @@ function pruneLegacyCodexConfigContent(content3) {
105671
106001
  `), removed };
105672
106002
  }
105673
106003
  async function pruneLegacyCodexConfig(dryRun, steps) {
105674
- const configPath = join72(codexHome(), "config.toml");
106004
+ const configPath = join73(codexHome(), "config.toml");
105675
106005
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105676
106006
  if (!current2)
105677
106007
  return;
@@ -105688,8 +106018,8 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
105688
106018
  }
105689
106019
  }
105690
106020
  async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
105691
- const cacheRoot = join72(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
105692
- if (!existsSync45(cacheRoot))
106021
+ const cacheRoot = join73(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
106022
+ if (!existsSync46(cacheRoot))
105693
106023
  return;
105694
106024
  const versions = (await readdir22(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
105695
106025
  if (versions.length === 0)
@@ -105700,7 +106030,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
105700
106030
  status: dryRun ? "planned" : "ran"
105701
106031
  });
105702
106032
  if (!dryRun)
105703
- await Promise.all(versions.map((version3) => rm20(join72(cacheRoot, version3), { recursive: true, force: true })));
106033
+ await Promise.all(versions.map((version3) => rm20(join73(cacheRoot, version3), { recursive: true, force: true })));
105704
106034
  }
105705
106035
  async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
105706
106036
  await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
@@ -105717,22 +106047,22 @@ async function isEmptyDir2(dir) {
105717
106047
  }
105718
106048
  async function pruneClaudeOrphanContextCache(dryRun, steps) {
105719
106049
  const cacheRoot = claudePluginCacheRoot();
105720
- if (!existsSync45(cacheRoot))
106050
+ if (!existsSync46(cacheRoot))
105721
106051
  return;
105722
106052
  const removed = [];
105723
106053
  const marketplaces = await readdir22(cacheRoot, { withFileTypes: true }).catch(() => []);
105724
106054
  for (const marketplace of marketplaces) {
105725
106055
  if (!marketplace.isDirectory())
105726
106056
  continue;
105727
- const pluginDir = join72(cacheRoot, marketplace.name, PLUGIN_NAME);
105728
- if (!existsSync45(pluginDir))
106057
+ const pluginDir = join73(cacheRoot, marketplace.name, PLUGIN_NAME);
106058
+ if (!existsSync46(pluginDir))
105729
106059
  continue;
105730
106060
  const versions = await readdir22(pluginDir, { withFileTypes: true }).catch(() => []);
105731
106061
  for (const version3 of versions) {
105732
106062
  if (!version3.isDirectory())
105733
106063
  continue;
105734
- const versionDir = join72(pluginDir, version3.name);
105735
- if (!existsSync45(join72(versionDir, ORPHAN_MARKER2)))
106064
+ const versionDir = join73(pluginDir, version3.name);
106065
+ if (!existsSync46(join73(versionDir, ORPHAN_MARKER2)))
105736
106066
  continue;
105737
106067
  removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
105738
106068
  if (!dryRun) {
@@ -105742,7 +106072,7 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
105742
106072
  if (!dryRun && await isEmptyDir2(pluginDir)) {
105743
106073
  await rm20(pluginDir, { recursive: true, force: true });
105744
106074
  }
105745
- const marketplaceDir = join72(cacheRoot, marketplace.name);
106075
+ const marketplaceDir = join73(cacheRoot, marketplace.name);
105746
106076
  if (!dryRun && await isEmptyDir2(marketplaceDir)) {
105747
106077
  await rm20(marketplaceDir, { recursive: true, force: true });
105748
106078
  }
@@ -105759,12 +106089,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
105759
106089
  if (LEGACY_PLUGIN_NAMES.length === 0)
105760
106090
  return;
105761
106091
  const cacheRoot = claudePluginCacheRoot();
105762
- if (!existsSync45(cacheRoot))
106092
+ if (!existsSync46(cacheRoot))
105763
106093
  return;
105764
106094
  const removed = [];
105765
106095
  for (const pluginName of LEGACY_PLUGIN_NAMES) {
105766
- const pluginDir = join72(cacheRoot, MARKETPLACE_NAME, pluginName);
105767
- if (!existsSync45(pluginDir))
106096
+ const pluginDir = join73(cacheRoot, MARKETPLACE_NAME, pluginName);
106097
+ if (!existsSync46(pluginDir))
105768
106098
  continue;
105769
106099
  removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
105770
106100
  if (!dryRun) {
@@ -105780,11 +106110,11 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
105780
106110
  }
105781
106111
  }
105782
106112
  async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
105783
- const manifest = await readFile55(join72(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
106113
+ const manifest = await readFile55(join73(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
105784
106114
  const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
105785
106115
  if (!currentVersion)
105786
106116
  return;
105787
- const pluginDir = join72(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
106117
+ const pluginDir = join73(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
105788
106118
  const staleVersions = (await readdir22(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
105789
106119
  if (staleVersions.length === 0)
105790
106120
  return;
@@ -105794,7 +106124,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
105794
106124
  status: dryRun ? "planned" : "ran"
105795
106125
  });
105796
106126
  if (!dryRun) {
105797
- await Promise.all(staleVersions.map((version3) => rm20(join72(pluginDir, version3), { recursive: true, force: true })));
106127
+ await Promise.all(staleVersions.map((version3) => rm20(join73(pluginDir, version3), { recursive: true, force: true })));
105798
106128
  }
105799
106129
  }
105800
106130
  function enableCodexPluginConfig(content3) {
@@ -105858,8 +106188,8 @@ source = ${JSON.stringify(root2)}
105858
106188
  `;
105859
106189
  }
105860
106190
  async function ensureCodexPluginEnabled() {
105861
- const configPath = join72(codexHome(), "config.toml");
105862
- await mkdir32(dirname41(configPath), { recursive: true });
106191
+ const configPath = join73(codexHome(), "config.toml");
106192
+ await mkdir32(dirname42(configPath), { recursive: true });
105863
106193
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105864
106194
  const next = enableCodexPluginConfig(current2);
105865
106195
  if (next !== current2) {
@@ -105867,8 +106197,8 @@ async function ensureCodexPluginEnabled() {
105867
106197
  }
105868
106198
  }
105869
106199
  async function ensureCodexLocalMarketplace(root2) {
105870
- const configPath = join72(codexHome(), "config.toml");
105871
- await mkdir32(dirname41(configPath), { recursive: true });
106200
+ const configPath = join73(codexHome(), "config.toml");
106201
+ await mkdir32(dirname42(configPath), { recursive: true });
105872
106202
  const current2 = await readFile55(configPath, "utf8").catch(() => "");
105873
106203
  const next = upsertCodexLocalMarketplaceConfig(current2, root2);
105874
106204
  if (next !== current2) {
@@ -105876,7 +106206,7 @@ async function ensureCodexLocalMarketplace(root2) {
105876
106206
  }
105877
106207
  }
105878
106208
  async function codexPluginVersion(root2) {
105879
- const manifestPath = join72(root2, "codex", ".codex-plugin", "plugin.json");
106209
+ const manifestPath = join73(root2, "codex", ".codex-plugin", "plugin.json");
105880
106210
  const manifest = JSON.parse(await readFile55(manifestPath, "utf8"));
105881
106211
  if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
105882
106212
  throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
@@ -105884,10 +106214,10 @@ async function codexPluginVersion(root2) {
105884
106214
  return manifest.version;
105885
106215
  }
105886
106216
  function codexPluginCacheDir(version3) {
105887
- return join72(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
106217
+ return join73(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
105888
106218
  }
105889
106219
  async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105890
- const source2 = join72(root2, "codex");
106220
+ const source2 = join73(root2, "codex");
105891
106221
  const target = codexPluginCacheDir(version3);
105892
106222
  steps.push({
105893
106223
  agent: "codex",
@@ -105896,12 +106226,12 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105896
106226
  });
105897
106227
  if (dryRun)
105898
106228
  return;
105899
- await mkdir32(dirname41(target), { recursive: true });
106229
+ await mkdir32(dirname42(target), { recursive: true });
105900
106230
  const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
105901
106231
  const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
105902
106232
  await rm20(temporary, { recursive: true, force: true });
105903
106233
  await cp(source2, temporary, { recursive: true, force: true });
105904
- const hadPrevious = existsSync45(target);
106234
+ const hadPrevious = existsSync46(target);
105905
106235
  try {
105906
106236
  if (hadPrevious)
105907
106237
  await rename5(target, previous3);
@@ -105910,7 +106240,7 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
105910
106240
  await rm20(previous3, { recursive: true, force: true });
105911
106241
  } catch (error) {
105912
106242
  await rm20(temporary, { recursive: true, force: true });
105913
- if (hadPrevious && !existsSync45(target) && existsSync45(previous3))
106243
+ if (hadPrevious && !existsSync46(target) && existsSync46(previous3))
105914
106244
  await rename5(previous3, target);
105915
106245
  throw error;
105916
106246
  }
@@ -105945,12 +106275,12 @@ async function installCodex(root2, dryRun, steps) {
105945
106275
  steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
105946
106276
  steps.push({
105947
106277
  agent: "codex",
105948
- command: `ensure ${shellQuote9(join72(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
106278
+ command: `ensure ${shellQuote9(join73(codexHome(), "config.toml"))} registers local marketplace ${shellQuote9(MARKETPLACE_NAME)}`,
105949
106279
  status: dryRun ? "planned" : "ran"
105950
106280
  });
105951
106281
  steps.push({
105952
106282
  agent: "codex",
105953
- command: `ensure ${shellQuote9(join72(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
106283
+ command: `ensure ${shellQuote9(join73(codexHome(), "config.toml"))} enables ${shellQuote9(PLUGIN_ID)}`,
105954
106284
  status: dryRun ? "planned" : "ran"
105955
106285
  });
105956
106286
  if (dryRun) {
@@ -106061,8 +106391,75 @@ function formatPluginInstallResult(result) {
106061
106391
  });
106062
106392
  }
106063
106393
 
106394
+ // src/registerPluginCommands.ts
106395
+ function registerPluginCommands(program2) {
106396
+ const plugin = program2.command("plugin").description("Install or inspect global Context agent plugins");
106397
+ plugin.command("path").description("Print the bundled plugin marketplace root used by `context plugin install`").action(async () => {
106398
+ process.stdout.write(formatPluginPathResult(await runPluginPathCommand()));
106399
+ });
106400
+ plugin.command("status").description("Inspect the bundled plugin marketplace root and global agent availability").option("--agent <agent>", "agent target: claude | codex | all", "all").action(async (options) => {
106401
+ const agent = pluginAgentOption(options.agent);
106402
+ process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
106403
+ });
106404
+ plugin.command("install").description("Install the bundled Context plugin globally for Claude and/or Codex").option("--agent <agent>", "agent target: claude | codex | all", "all").option("--dry-run", "Print install commands without mutating global agent config").action(async (options) => {
106405
+ const agent = pluginAgentOption(options.agent);
106406
+ const result = await runPluginInstallCommand({
106407
+ agent,
106408
+ dryRun: options.dryRun === true
106409
+ });
106410
+ process.stdout.write(formatPluginInstallResult(result));
106411
+ });
106412
+ }
106413
+
106414
+ // src/registerPackageCommands.ts
106415
+ init_cliFeedback();
106416
+ init_errors();
106417
+ init_packageTemplateReview();
106418
+ init_workspace();
106419
+ init_exitCode();
106420
+ function registerPackageCommands(program2) {
106421
+ const packageCommand = program2.command("package").description("Inspect or resolve package output configuration");
106422
+ const packageTemplate = packageCommand.command("template").description("Manage package template review state");
106423
+ packageTemplate.command("accept [package-name]").description("Explicitly accept an unchanged generated starter template").option("--all", "accept all unchanged generated starter templates").option("--format <format>", "output format: text | json", "text").action(async (packageName, options) => {
106424
+ if (packageName === undefined === (options.all !== true)) {
106425
+ throw new ContextError(ExitCode.UserError, "provide one package name or --all", { category: ErrorCategory.UserInputInvalid });
106426
+ }
106427
+ if (options.format !== "text" && options.format !== "json") {
106428
+ throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106429
+ category: ErrorCategory.UserInputInvalid
106430
+ });
106431
+ }
106432
+ const found = findContextProjectRoot(process.cwd());
106433
+ if (!found) {
106434
+ throw new ContextError(ExitCode.WorkspaceStateError, "package template acceptance requires a context project workspace", { category: ErrorCategory.WorkspaceNotFound });
106435
+ }
106436
+ const result = await acceptStarterPackageTemplates({
106437
+ projectRoot: found.projectRoot,
106438
+ ...packageName === undefined ? {} : { packageNames: [packageName] }
106439
+ });
106440
+ if (options.format === "json") {
106441
+ process.stdout.write(`${JSON.stringify({
106442
+ action: "package-template-accepted",
106443
+ ...result,
106444
+ next_action: {
106445
+ kind: "reevaluate-workspace",
106446
+ command: "context status --format json"
106447
+ }
106448
+ }, null, 2)}
106449
+ `);
106450
+ } else {
106451
+ process.stdout.write(formatFeedback({
106452
+ symbol: "✓",
106453
+ action: "accepted",
106454
+ subject: result.accepted.join(", ") || "package templates",
106455
+ headline: "starter package template",
106456
+ body: result.alreadyResolved.length === 0 ? [] : [`already resolved: ${result.alreadyResolved.join(", ")}`]
106457
+ }));
106458
+ }
106459
+ });
106460
+ }
106461
+
106064
106462
  // src/cli.ts
106065
- init_debugTrace();
106066
106463
  var TOP_LEVEL_COMMANDS = new Set([
106067
106464
  "init",
106068
106465
  "plugin",
@@ -106098,14 +106495,14 @@ function inferErrorCategory(message) {
106098
106495
  }
106099
106496
  function readPackageVersion() {
106100
106497
  try {
106101
- let dir = dirname42(fileURLToPath9(import.meta.url));
106498
+ let dir = dirname43(fileURLToPath10(import.meta.url));
106102
106499
  for (let i2 = 0;i2 < 8; i2++) {
106103
- const pkg = join73(dir, "package.json");
106104
- if (existsSync46(pkg)) {
106105
- const parsed = JSON.parse(readFileSync9(pkg, "utf8"));
106500
+ const pkg = join74(dir, "package.json");
106501
+ if (existsSync47(pkg)) {
106502
+ const parsed = JSON.parse(readFileSync10(pkg, "utf8"));
106106
106503
  return parsed.version ?? "unknown";
106107
106504
  }
106108
- const parent = dirname42(dir);
106505
+ const parent = dirname43(dir);
106109
106506
  if (parent === dir)
106110
106507
  break;
106111
106508
  dir = parent;
@@ -106115,21 +106512,21 @@ function readPackageVersion() {
106115
106512
  }
106116
106513
  function readQuickstartPath() {
106117
106514
  try {
106118
- let dir = dirname42(fileURLToPath9(import.meta.url));
106515
+ let dir = dirname43(fileURLToPath10(import.meta.url));
106119
106516
  for (let i2 = 0;i2 < 8; i2++) {
106120
- const candidate = join73(dir, "docs", "quickstart.md");
106121
- if (existsSync46(candidate))
106517
+ const candidate = join74(dir, "docs", "quickstart.md");
106518
+ if (existsSync47(candidate))
106122
106519
  return candidate;
106123
- const pkg = join73(dir, "package.json");
106124
- if (existsSync46(pkg))
106520
+ const pkg = join74(dir, "package.json");
106521
+ if (existsSync47(pkg))
106125
106522
  return candidate;
106126
- const parent = dirname42(dir);
106523
+ const parent = dirname43(dir);
106127
106524
  if (parent === dir)
106128
106525
  break;
106129
106526
  dir = parent;
106130
106527
  }
106131
106528
  } catch {}
106132
- return join73(dirname42(fileURLToPath9(import.meta.url)), "docs", "quickstart.md");
106529
+ return join74(dirname43(fileURLToPath10(import.meta.url)), "docs", "quickstart.md");
106133
106530
  }
106134
106531
  var GREEN = "\x1B[32m";
106135
106532
  var RESET = "\x1B[0m";
@@ -106214,94 +106611,12 @@ function createCliProgram() {
106214
106611
  });
106215
106612
  const baseHelpInformation = program2.helpInformation.bind(program2);
106216
106613
  program2.helpInformation = () => `${headerHelpText()}${baseHelpInformation()}${quickstartHelpText()}`;
106217
- 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) => {
106218
- const result = await initContextProject({
106219
- cwd: process.cwd(),
106220
- ...projectDir !== undefined ? { projectDir } : {},
106221
- ...typeof options.name === "string" ? { name: options.name } : {},
106222
- ...typeof options.language === "string" ? { language: projectLanguage(options.language) } : {},
106223
- ...options.dev === true ? { dev: true } : {},
106224
- ...options.debug === true ? { debug: true } : {},
106225
- ...options.allowNonempty === true ? { allowNonempty: true } : {}
106226
- });
106227
- process.stdout.write(formatProjectInitResult(result));
106228
- });
106229
- const plugin = program2.command("plugin").description("Install or inspect global Context agent plugins");
106614
+ registerProjectInitCommand(program2);
106615
+ registerPluginCommands(program2);
106230
106616
  registerDebugCommands(program2);
106231
- plugin.command("path").description("Print the bundled plugin marketplace root used by `context plugin install`").action(async () => {
106232
- process.stdout.write(formatPluginPathResult(await runPluginPathCommand()));
106233
- });
106234
- 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) => {
106235
- const agent = pluginAgentOption(options.agent);
106236
- process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
106237
- });
106238
- 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) => {
106239
- const agent = pluginAgentOption(options.agent);
106240
- const result = await runPluginInstallCommand({
106241
- agent,
106242
- dryRun: options.dryRun === true
106243
- });
106244
- process.stdout.write(formatPluginInstallResult(result));
106245
- });
106246
106617
  registerContextWorkflowResourceCommands(program2);
106247
- const packageCommand = program2.command("package").description("Inspect or resolve package output configuration");
106248
- const packageTemplate = packageCommand.command("template").description("Manage package template review state");
106249
- 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) => {
106250
- if (packageName === undefined === (options.all !== true)) {
106251
- throw new ContextError(ExitCode.UserError, "provide one package name or --all", { category: ErrorCategory.UserInputInvalid });
106252
- }
106253
- if (options.format !== "text" && options.format !== "json") {
106254
- throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106255
- category: ErrorCategory.UserInputInvalid
106256
- });
106257
- }
106258
- const found = findContextProjectRoot(process.cwd());
106259
- if (!found) {
106260
- throw new ContextError(ExitCode.WorkspaceStateError, "package template acceptance requires a context project workspace", { category: ErrorCategory.WorkspaceNotFound });
106261
- }
106262
- const result = await acceptStarterPackageTemplates({
106263
- projectRoot: found.projectRoot,
106264
- ...packageName === undefined ? {} : { packageNames: [packageName] }
106265
- });
106266
- if (options.format === "json") {
106267
- process.stdout.write(`${JSON.stringify({
106268
- action: "package-template-accepted",
106269
- ...result,
106270
- next_action: {
106271
- kind: "reevaluate-workspace",
106272
- command: "context status --format json"
106273
- }
106274
- }, null, 2)}
106275
- `);
106276
- } else {
106277
- process.stdout.write(formatFeedback({
106278
- symbol: "✓",
106279
- action: "accepted",
106280
- subject: result.accepted.join(", ") || "package templates",
106281
- headline: "starter package template",
106282
- body: result.alreadyResolved.length === 0 ? [] : [`already resolved: ${result.alreadyResolved.join(", ")}`]
106283
- }));
106284
- }
106285
- });
106286
- 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) => {
106287
- const rootOptions = program2.opts();
106288
- const resourceReceiptsReference = typeof options.resourceReceipts === "string" ? options.resourceReceipts : typeof rootOptions.workflowResourceReceipts === "string" ? rootOptions.workflowResourceReceipts : undefined;
106289
- const resourceReceipts = resourceReceiptsReference !== undefined ? await parseWorkflowResourceReceipts(resourceReceiptsReference, process.cwd()) : undefined;
106290
- if (await runProjectStatusCommand({
106291
- cwd: process.cwd(),
106292
- format: options.format === "json" ? "json" : "table",
106293
- view: options.view === "full" ? "full" : "summary",
106294
- managed: options.managed === true,
106295
- authorities: workflowAuthorities(options.authority),
106296
- ...resourceReceipts === undefined ? {} : { resourceReceipts },
106297
- ...resourceReceiptsReference === undefined ? {} : { resourceReceiptsReference }
106298
- })) {
106299
- return;
106300
- }
106301
- throw new ContextError(ExitCode.WorkspaceStateError, "status requires a context project workspace", {
106302
- category: ErrorCategory.WorkspaceNotFound
106303
- });
106304
- });
106618
+ registerPackageCommands(program2);
106619
+ registerProjectStatusCommand(program2);
106305
106620
  registerProjectRunCommand(program2, import.meta.url);
106306
106621
  const review = program2.command("review").description("Review draft project candidates and apply approval decisions");
106307
106622
  review.command("html [collection]").description("Render a self-contained local review HTML page").option("--all", "review all draft candidates across internal collections").option("--out <file>", "output HTML path, defaults to .tmp/context-runtime/review/<collection>.html").option("--open", "open the generated HTML with the system default browser").option("--format <format>", "output format: text | json", "text").action(async (collection, options) => {
@@ -106449,70 +106764,9 @@ function createCliProgram() {
106449
106764
  format: options.format === "json" ? "json" : "text"
106450
106765
  });
106451
106766
  });
106452
- 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) => {
106453
- if (options.format !== "text" && options.format !== "json") {
106454
- throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106455
- category: ErrorCategory.UserInputInvalid
106456
- });
106457
- }
106458
- if (await runProjectCloseCommand({
106459
- cwd: process.cwd(),
106460
- format: options.format === "json" ? "json" : "text"
106461
- })) {
106462
- return;
106463
- }
106464
- throw new ContextError(ExitCode.WorkspaceStateError, "close requires a context project workspace", {
106465
- category: ErrorCategory.WorkspaceNotFound
106466
- });
106467
- });
106468
- 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) => {
106469
- if (options.format !== "text" && options.format !== "json") {
106470
- throw new ContextError(ExitCode.UserError, "--format must be text or json", {
106471
- category: ErrorCategory.UserInputInvalid
106472
- });
106473
- }
106474
- if (await runProjectBuildCommand({
106475
- cwd: process.cwd(),
106476
- format: options.format === "json" ? "json" : "text",
106477
- verbose: options.verbose === true
106478
- })) {
106479
- return;
106480
- }
106481
- throw new ContextError(ExitCode.WorkspaceStateError, "build requires a context project workspace", {
106482
- category: ErrorCategory.WorkspaceNotFound
106483
- });
106484
- });
106767
+ registerProjectCloseAndBuildCommands(program2);
106485
106768
  registerProjectSourceCommands(program2);
106486
- 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) => {
106487
- if (options.format !== "table" && options.format !== "json") {
106488
- throw new ContextError(ExitCode.UserError, "--format must be table or json", {
106489
- category: ErrorCategory.UserInputInvalid
106490
- });
106491
- }
106492
- if (options.view !== undefined && options.view !== "diagnostics") {
106493
- throw new ContextError(ExitCode.UserError, "--view must be diagnostics", {
106494
- category: ErrorCategory.UserInputInvalid
106495
- });
106496
- }
106497
- if (options.view === "diagnostics" && options.format !== "json") {
106498
- throw new ContextError(ExitCode.UserError, "--view diagnostics requires --format json", {
106499
- category: ErrorCategory.UserInputInvalid
106500
- });
106501
- }
106502
- if (await runProjectVerifyCommand({
106503
- cwd: process.cwd(),
106504
- format: options.format === "json" ? "json" : "table",
106505
- ...options.compact === true ? { compact: true } : {},
106506
- ...options.view === "diagnostics" ? { view: "diagnostics" } : {},
106507
- ...typeof options.pageSize === "string" ? { pageSize: options.pageSize } : {},
106508
- ...typeof options.pageToken === "string" ? { pageToken: options.pageToken } : {}
106509
- })) {
106510
- return;
106511
- }
106512
- throw new ContextError(ExitCode.WorkspaceStateError, "verify requires a context project workspace", {
106513
- category: ErrorCategory.WorkspaceNotFound
106514
- });
106515
- });
106769
+ registerProjectVerifyCommand(program2);
106516
106770
  const cleanCacheAction = async (options) => {
106517
106771
  const dryRun = options.dryRun === true;
106518
106772
  await runDoctorCleanClaudePluginCache({ dryRun });
@@ -106544,10 +106798,12 @@ function createCliProgram() {
106544
106798
  return program2;
106545
106799
  }
106546
106800
  async function cli_main(argv = process.argv) {
106547
- await withDebugCliInvocation(argv, async () => {
106548
- assertKnownTopLevelCommand(argv);
106549
- const program2 = createCliProgram();
106550
- await program2.parseAsync(argv);
106801
+ await withContextRuntimeEventDelivery(async () => {
106802
+ await withDebugCliInvocation(argv, async () => {
106803
+ assertKnownTopLevelCommand(argv);
106804
+ const program2 = createCliProgram();
106805
+ await program2.parseAsync(argv);
106806
+ });
106551
106807
  });
106552
106808
  }
106553
106809
  function isDirectCliInvocation(metaUrl, argv1) {