@c4a/context-cli 0.7.16 → 0.7.17

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
@@ -64986,6 +64986,60 @@ var init_productionPlanning = __esm(() => {
64986
64986
  }).strict();
64987
64987
  });
64988
64988
 
64989
+ // src/project/siteTheme.ts
64990
+ import { mkdir as mkdir12, readFile as readFile26, writeFile as writeFile7 } from "node:fs/promises";
64991
+ import { dirname as dirname14, join as join26 } from "node:path";
64992
+ async function resolveSiteTheme(root, overrides, scaffold = false) {
64993
+ const path2 = join26(root, SITE_THEME_FILE);
64994
+ let file = {};
64995
+ try {
64996
+ file = siteThemeSchema.parse(JSON.parse(await readFile26(path2, "utf8")));
64997
+ } catch (error) {
64998
+ if (error.code !== "ENOENT") {
64999
+ throw new ContextError(ExitCode.UserError, `Invalid ${SITE_THEME_FILE}: ${error instanceof Error ? error.message : String(error)}. Fix the theme or remove the optional file to use defaults.`, { reason_code: "invalid-site-theme" });
65000
+ }
65001
+ if (scaffold) {
65002
+ await mkdir12(dirname14(path2), { recursive: true });
65003
+ try {
65004
+ await writeFile7(path2, JSON.stringify(DEFAULT_SITE_THEME, null, 2) + `
65005
+ `, { flag: "wx" });
65006
+ } catch (writeError) {
65007
+ if (writeError.code !== "EEXIST")
65008
+ throw writeError;
65009
+ }
65010
+ return resolveSiteTheme(root, overrides);
65011
+ }
65012
+ }
65013
+ const inline2 = siteThemeSchema.parse(overrides ?? {});
65014
+ return { light: { ...DEFAULT_SITE_THEME.light, ...file.light, ...inline2.light }, dark: { ...DEFAULT_SITE_THEME.dark, ...file.dark, ...inline2.dark } };
65015
+ }
65016
+ function isDefaultSiteTheme(content3) {
65017
+ try {
65018
+ const theme = siteThemeSchema.parse(JSON.parse(content3));
65019
+ return ["light", "dark"].every((mode) => Object.entries(theme[mode] ?? {}).every(([key, value]) => DEFAULT_SITE_THEME[mode][key] === value));
65020
+ } catch {
65021
+ return false;
65022
+ }
65023
+ }
65024
+ function siteThemeVariables(theme) {
65025
+ const rules = (c) => Object.entries(c).map(([key, value]) => `--context-${key.replace(/[A-Z]/gu, (x) => "-" + x.toLowerCase())}:${value};`).join("") + `
65026
+ --vp-c-brand-1:var(--context-brand);--vp-c-brand-2:var(--context-accent);--vp-c-brand-3:var(--context-brand);
65027
+ --vp-c-brand-soft:color-mix(in srgb,var(--context-brand) 8%,transparent);
65028
+ --vp-c-bg:var(--context-background);--vp-c-bg-alt:var(--context-surface);--vp-c-bg-soft:var(--context-surface);--vp-c-bg-elv:var(--context-background);
65029
+ --vp-sidebar-bg-color:var(--context-surface);--vp-nav-bg-color:var(--context-background);--vp-local-search-bg:var(--context-background);
65030
+ --vp-c-text-1:var(--context-text);--vp-c-text-2:var(--context-muted-text);--vp-c-text-3:var(--context-muted-text);--vp-c-divider:var(--context-border);--vp-c-border:var(--context-border);
65031
+ --bg:var(--context-background);--side:var(--context-surface);--text:var(--context-text);--muted:var(--context-muted-text);--line:var(--context-border);--blue:var(--context-brand);`;
65032
+ return `:root{${rules(theme.light)}}.dark{${rules(theme.dark)}}
65033
+ .node.selected,blockquote{background:color-mix(in srgb,var(--context-brand) 8%,transparent)}blockquote{border-left-color:var(--context-accent)}
65034
+ `;
65035
+ }
65036
+ var SITE_THEME_FILE = "src/site/theme.json";
65037
+ var init_siteTheme2 = __esm(() => {
65038
+ init_src2();
65039
+ init_errors3();
65040
+ init_exitCode();
65041
+ });
65042
+
64989
65043
  // src/project/workspaceVersionComparison.ts
64990
65044
  import { execFile as execFile5 } from "node:child_process";
64991
65045
  import { promisify as promisify5 } from "node:util";
@@ -65036,11 +65090,11 @@ var init_workspaceVersionComparison = __esm(() => {
65036
65090
  import { createHash as createHash10 } from "node:crypto";
65037
65091
  import { execFile as execFile6 } from "node:child_process";
65038
65092
  import { promisify as promisify6 } from "node:util";
65039
- import { readFile as readFile26, lstat as lstat5, readdir as readdir7, realpath as realpath6 } from "node:fs/promises";
65040
- import { join as join26 } from "node:path";
65093
+ import { readFile as readFile27, lstat as lstat5, readdir as readdir7, realpath as realpath6 } from "node:fs/promises";
65094
+ import { join as join27 } from "node:path";
65041
65095
  async function optionalWorkspaceText(root, path2) {
65042
65096
  try {
65043
- return await readFile26(join26(root, path2), "utf8");
65097
+ return await readFile27(join27(root, path2), "utf8");
65044
65098
  } catch (error) {
65045
65099
  if (error.code === "ENOENT")
65046
65100
  return;
@@ -65052,7 +65106,7 @@ async function readWorkspaceChangelog(root) {
65052
65106
  return value === undefined ? [] : ledgerSchema.parse(import_yaml24.parse(value)).entries;
65053
65107
  }
65054
65108
  async function workspaceVersion(root) {
65055
- const manifest = JSON.parse(await readFile26(join26(root, "package.json"), "utf8"));
65109
+ const manifest = JSON.parse(await readFile27(join27(root, "package.json"), "utf8"));
65056
65110
  return semver.parse(manifest.version ?? "0.0.0");
65057
65111
  }
65058
65112
  function excluded(path2) {
@@ -65073,7 +65127,7 @@ async function workspaceContentSnapshot(root) {
65073
65127
  if (paths === undefined) {
65074
65128
  const discovered = [];
65075
65129
  const visit2 = async (dir) => {
65076
- for (const entry of await readdir7(join26(root, dir), { withFileTypes: true })) {
65130
+ for (const entry of await readdir7(join27(root, dir), { withFileTypes: true })) {
65077
65131
  const path2 = dir ? `${dir}/${entry.name}` : entry.name;
65078
65132
  if (excluded(path2))
65079
65133
  continue;
@@ -65090,14 +65144,16 @@ async function workspaceContentSnapshot(root) {
65090
65144
  for (const path2 of [...new Set(paths)].filter((path3) => !excluded(path3)).sort()) {
65091
65145
  let bytes;
65092
65146
  try {
65093
- if (!(await lstat5(join26(root, path2))).isFile())
65147
+ if (!(await lstat5(join27(root, path2))).isFile())
65094
65148
  continue;
65095
- bytes = await readFile26(join26(root, path2));
65149
+ bytes = await readFile27(join27(root, path2));
65096
65150
  } catch (error) {
65097
65151
  if (error.code === "ENOENT")
65098
65152
  continue;
65099
65153
  throw error;
65100
65154
  }
65155
+ if (path2 === SITE_THEME_FILE && isDefaultSiteTheme(bytes.toString("utf8")))
65156
+ continue;
65101
65157
  if (path2 === "package.json") {
65102
65158
  const value = JSON.parse(bytes.toString());
65103
65159
  delete value.version;
@@ -65175,7 +65231,7 @@ async function recordWorkspaceVersion(root, value) {
65175
65231
  const { expected_digest: _, base_ref: _base, ...fields } = input;
65176
65232
  const entry = changelogEntrySchema.parse({ ...fields, date: new Date().toISOString(), ...actor ? { actor } : {} });
65177
65233
  const entries = [entry, ...amend ? previousEntries.slice(1) : previousEntries];
65178
- const manifest = JSON.parse(await readFile26(join26(root, "package.json"), "utf8"));
65234
+ const manifest = JSON.parse(await readFile27(join27(root, "package.json"), "utf8"));
65179
65235
  manifest.version = entry.version;
65180
65236
  const writes = {
65181
65237
  "package.json": JSON.stringify(manifest, null, 2) + `
@@ -65190,7 +65246,7 @@ async function recordWorkspaceVersion(root, value) {
65190
65246
  targets.sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
65191
65247
  await runDurableMultiFileTransaction({ projectRoot: root, kind: "record-workspace-version", proposal_digest: hash2(writes), targets });
65192
65248
  try {
65193
- await atomicWriteFile(join26(root, VERSION_CHECKPOINT), JSON.stringify({ version: entry.version, digest: status.content_digest }) + `
65249
+ await atomicWriteFile(join27(root, VERSION_CHECKPOINT), JSON.stringify({ version: entry.version, digest: status.content_digest }) + `
65194
65250
  `);
65195
65251
  } catch {}
65196
65252
  return { version: entry.version, next_action: { command: "context status --format json" } };
@@ -65198,6 +65254,7 @@ async function recordWorkspaceVersion(root, value) {
65198
65254
  }
65199
65255
  var import_yaml24, exec2, semver, text6, changelogEntrySchema, changelogInputSchema, ledgerSchema, VERSION_CHECKPOINT = ".tmp/context-runtime/version-checkpoint.json", hash2 = (value) => createHash10("sha256").update(JSON.stringify(value)).digest("hex");
65200
65256
  var init_workspaceChangelog = __esm(() => {
65257
+ init_siteTheme2();
65201
65258
  init_atomicWrite();
65202
65259
  init_workspaceVersionComparison();
65203
65260
  init_zod();
@@ -65227,8 +65284,8 @@ __export(exports_workspacePreparation, {
65227
65284
  assertPreparationComplete: () => assertPreparationComplete,
65228
65285
  PREPARATION_ROOTS: () => PREPARATION_ROOTS
65229
65286
  });
65230
- import { lstat as lstat6, readFile as readFile27, readdir as readdir8 } from "node:fs/promises";
65231
- import { join as join27 } from "node:path";
65287
+ import { lstat as lstat6, readFile as readFile28, readdir as readdir8 } from "node:fs/promises";
65288
+ import { join as join28 } from "node:path";
65232
65289
  function failure(reason, message, next) {
65233
65290
  throw new ContextError(ExitCode.WorkspaceStateError, message, {
65234
65291
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -65240,7 +65297,7 @@ async function entries(root, path2) {
65240
65297
  await safeProjectTarget(root, path2);
65241
65298
  let stat6;
65242
65299
  try {
65243
- stat6 = await lstat6(join27(root, path2));
65300
+ stat6 = await lstat6(join28(root, path2));
65244
65301
  } catch (error) {
65245
65302
  if (error.code === "ENOENT")
65246
65303
  return [];
@@ -65253,8 +65310,8 @@ async function entries(root, path2) {
65253
65310
  if (!stat6.isDirectory())
65254
65311
  failure("preparation-file-type", `Unsupported task-state file: ${path2}`, "Inspect this file before preparing the workspace.");
65255
65312
  const result = [];
65256
- for (const name2 of (await readdir8(join27(root, path2))).sort())
65257
- result.push(...await entries(root, join27(path2, name2)));
65313
+ for (const name2 of (await readdir8(join28(root, path2))).sort())
65314
+ result.push(...await entries(root, join28(path2, name2)));
65258
65315
  return result;
65259
65316
  }
65260
65317
  async function pendingJournals(root) {
@@ -65262,7 +65319,7 @@ async function pendingJournals(root) {
65262
65319
  const result = [];
65263
65320
  for (const path2 of files.filter((path3) => path3.endsWith("/journal.json") || path3.endsWith(".journal.json"))) {
65264
65321
  try {
65265
- result.push({ ...JSON.parse(await readFile27(join27(root, path2), "utf8")), path: path2 });
65322
+ result.push({ ...JSON.parse(await readFile28(join28(root, path2), "utf8")), path: path2 });
65266
65323
  } catch {
65267
65324
  result.push({ path: path2 });
65268
65325
  }
@@ -65292,7 +65349,7 @@ async function prepareWorkspace(input) {
65292
65349
  const targets = [];
65293
65350
  for (const directory of PREPARATION_ROOTS)
65294
65351
  for (const path2 of await entries(input.projectRoot, directory)) {
65295
- const bytes = await readFile27(join27(input.projectRoot, path2));
65352
+ const bytes = await readFile28(join28(input.projectRoot, path2));
65296
65353
  let content3;
65297
65354
  try {
65298
65355
  content3 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
@@ -65304,7 +65361,7 @@ async function prepareWorkspace(input) {
65304
65361
  const markerContent = JSON.stringify(taskPreparationRecord("cleared"));
65305
65362
  let oldMarker;
65306
65363
  try {
65307
- oldMarker = await readFile27(join27(input.projectRoot, TASK_PREPARATION_PATH), "utf8");
65364
+ oldMarker = await readFile28(join28(input.projectRoot, TASK_PREPARATION_PATH), "utf8");
65308
65365
  } catch (error) {
65309
65366
  if (error.code !== "ENOENT")
65310
65367
  throw error;
@@ -65377,15 +65434,15 @@ __export(exports_taskResumption, {
65377
65434
  readTaskPreparation: () => readTaskPreparation,
65378
65435
  TASK_PREPARATION_PATH: () => TASK_PREPARATION_PATH
65379
65436
  });
65380
- import { readFile as readFile28 } from "node:fs/promises";
65381
- import { join as join28 } from "node:path";
65437
+ import { readFile as readFile29 } from "node:fs/promises";
65438
+ import { join as join29 } from "node:path";
65382
65439
  function taskPreparationRecord(state) {
65383
65440
  return { protocol: "context.task-preparation/v1", state };
65384
65441
  }
65385
65442
  async function readTaskPreparation(root) {
65386
65443
  let text7;
65387
65444
  try {
65388
- text7 = await readFile28(join28(root, TASK_PREPARATION_PATH), "utf8");
65445
+ text7 = await readFile29(join29(root, TASK_PREPARATION_PATH), "utf8");
65389
65446
  } catch (error) {
65390
65447
  if (error.code !== "ENOENT")
65391
65448
  throw error;
@@ -65555,7 +65612,7 @@ __export(exports_approvedRevisionPrograms, {
65555
65612
  });
65556
65613
  import { execFile as execFile7 } from "node:child_process";
65557
65614
  import { promisify as promisify7 } from "node:util";
65558
- import { extname as extname6, join as join29 } from "node:path";
65615
+ import { extname as extname6, join as join30 } from "node:path";
65559
65616
  import { createRequire as createRequire3 } from "node:module";
65560
65617
  import { pathToFileURL } from "node:url";
65561
65618
  async function prepareRevisionProgramBlocks(root, sourceRefs, scopes, references) {
@@ -65571,7 +65628,7 @@ async function prepareRevisionProgramBlocks(root, sourceRefs, scopes, references
65571
65628
  if (entries2.length !== 1)
65572
65629
  throw new TypeError(`Regeneration requires one registered source: ${source2}`);
65573
65630
  const entry = entries2[0];
65574
- const directory = join29(root, entry.materializedAt);
65631
+ const directory = join30(root, entry.materializedAt);
65575
65632
  const paths = [...new Set(references.filter((reference2) => reference2.source_ref === source2).map((reference2) => reference2.locator.path))];
65576
65633
  if (!paths.length)
65577
65634
  continue;
@@ -65833,8 +65890,8 @@ function selectDeliveryPages(input) {
65833
65890
 
65834
65891
  // src/project/knowledgeAssets.ts
65835
65892
  import { existsSync as existsSync5 } from "node:fs";
65836
- import { readFile as readFile29, readdir as readdir9, rm as rm7 } from "node:fs/promises";
65837
- import { dirname as dirname14, extname as extname7, join as join30, relative as relative12, resolve as resolve16, sep as sep3 } from "node:path";
65893
+ import { readFile as readFile30, readdir as readdir9, rm as rm7 } from "node:fs/promises";
65894
+ import { dirname as dirname15, extname as extname7, join as join31, relative as relative12, resolve as resolve16, sep as sep3 } from "node:path";
65838
65895
  function posixPath(value) {
65839
65896
  return value.split(sep3).join("/");
65840
65897
  }
@@ -65853,7 +65910,7 @@ function contentAddressedPath(asset) {
65853
65910
  return `knowledge/assets/${safeKind(asset)}/${withoutHashPrefix(asset.content_hash)}${suffix}`;
65854
65911
  }
65855
65912
  function relativeMarkdownTarget(fromPage, target) {
65856
- const rel = posixPath(relative12(dirname14(fromPage), target));
65913
+ const rel = posixPath(relative12(dirname15(fromPage), target));
65857
65914
  return rel.startsWith(".") ? rel : `./${rel}`;
65858
65915
  }
65859
65916
  function decodedTarget(value) {
@@ -65867,7 +65924,7 @@ function sourceAssetPath(documentPath, target) {
65867
65924
  const decoded = decodedTarget(target);
65868
65925
  if (/^[a-z][a-z0-9+.-]*:/iu.test(decoded) || decoded.startsWith("#") || decoded.startsWith("/"))
65869
65926
  return;
65870
- const normalized = posixPath(join30(dirname14(documentPath), decoded));
65927
+ const normalized = posixPath(join31(dirname15(documentPath), decoded));
65871
65928
  if (normalized === "assets" || normalized.startsWith("assets/"))
65872
65929
  return normalized;
65873
65930
  return;
@@ -65879,7 +65936,7 @@ function selectedAssets(input) {
65879
65936
  const selected = new Map;
65880
65937
  for (const link of markdownInlineLinks(input.content)) {
65881
65938
  const target = link.target;
65882
- const pageTarget = posixPath(join30(dirname14(input.pageRelPath), decodedTarget(target)));
65939
+ const pageTarget = posixPath(join31(dirname15(input.pageRelPath), decodedTarget(target)));
65883
65940
  const sourceRoot2 = posixPath(input.sourceMaterializedAt).replace(/\/$/u, "") + "/";
65884
65941
  const path2 = sourceAssetPath(input.documentPath, target) ?? (pageTarget.startsWith(sourceRoot2) ? pageTarget.slice(sourceRoot2.length) : undefined);
65885
65942
  if (path2 === undefined)
@@ -65924,10 +65981,10 @@ async function projectKnowledgeAssets(input) {
65924
65981
  next: "Rerun the source capture and resolve resource materialization errors before Review."
65925
65982
  });
65926
65983
  }
65927
- const sourcePath = join30(input.projectRoot, input.sourceMaterializedAt, asset.path);
65984
+ const sourcePath = join31(input.projectRoot, input.sourceMaterializedAt, asset.path);
65928
65985
  let bytes;
65929
65986
  try {
65930
- bytes = await readFile29(sourcePath);
65987
+ bytes = await readFile30(sourcePath);
65931
65988
  } catch {
65932
65989
  throw new ContextError(ExitCode.WorkspaceStateError, `source resource file is missing: ${asset.path}`, {
65933
65990
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -65940,7 +65997,7 @@ async function projectKnowledgeAssets(input) {
65940
65997
  knowledgePathBySourcePath.set(asset.path, relPath);
65941
65998
  assets.push({
65942
65999
  relPath,
65943
- absPath: join30(input.projectRoot, relPath),
66000
+ absPath: join31(input.projectRoot, relPath),
65944
66001
  bytes,
65945
66002
  contentHash: asset.content_hash
65946
66003
  });
@@ -65962,7 +66019,7 @@ function canonicalizeKnowledgeAssetLinks(input) {
65962
66019
  let rewritten = 0;
65963
66020
  const content3 = replaceMarkdownInlineLinkTargets(input.content, (link) => {
65964
66021
  const sourcePath = sourceAssetPath(input.documentPath, link.target);
65965
- const projectedPath = input.pageRelPath === undefined ? undefined : posixPath(join30(dirname14(input.pageRelPath), decodedTarget(link.target)));
66022
+ const projectedPath = input.pageRelPath === undefined ? undefined : posixPath(join31(dirname15(input.pageRelPath), decodedTarget(link.target)));
65966
66023
  const asset = (sourcePath === undefined ? undefined : bySourcePath.get(sourcePath)) ?? (projectedPath === undefined ? undefined : byKnowledgePath.get(projectedPath));
65967
66024
  if (asset?.content_hash === undefined)
65968
66025
  return;
@@ -65977,7 +66034,7 @@ function knowledgeAssetReferences(input) {
65977
66034
  const target = link.target;
65978
66035
  if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("#"))
65979
66036
  continue;
65980
- const resolved = posixPath(join30(dirname14(input.pageRelPath), decodedTarget(target)));
66037
+ const resolved = posixPath(join31(dirname15(input.pageRelPath), decodedTarget(target)));
65981
66038
  if (resolved.startsWith("knowledge/assets/"))
65982
66039
  references.add(resolved);
65983
66040
  }
@@ -65998,7 +66055,7 @@ async function walkFiles2(root) {
65998
66055
  const files = [];
65999
66056
  const visit2 = async (dir) => {
66000
66057
  for (const entry of await readdir9(dir, { withFileTypes: true })) {
66001
- const path2 = join30(dir, entry.name);
66058
+ const path2 = join31(dir, entry.name);
66002
66059
  if (entry.isDirectory())
66003
66060
  await visit2(path2);
66004
66061
  else if (entry.isFile())
@@ -66009,8 +66066,8 @@ async function walkFiles2(root) {
66009
66066
  return files;
66010
66067
  }
66011
66068
  async function removeOrphanKnowledgeAssets(projectRoot, currentReferences) {
66012
- const knowledgeRoot = join30(projectRoot, "knowledge");
66013
- const assetRoot = join30(knowledgeRoot, "assets");
66069
+ const knowledgeRoot = join31(projectRoot, "knowledge");
66070
+ const assetRoot = join31(knowledgeRoot, "assets");
66014
66071
  if (!existsSync5(assetRoot))
66015
66072
  return [];
66016
66073
  const referenced = new Set(currentReferences ?? []);
@@ -66019,7 +66076,7 @@ async function removeOrphanKnowledgeAssets(projectRoot, currentReferences) {
66019
66076
  if (!isApprovedKnowledgeMarkdownPath(relative12(knowledgeRoot, path2)) || path2.startsWith(`${assetRoot}${sep3}`))
66020
66077
  continue;
66021
66078
  const relPath = posixPath(relative12(projectRoot, path2));
66022
- const content3 = await readFile29(path2, "utf8");
66079
+ const content3 = await readFile30(path2, "utf8");
66023
66080
  for (const ref of knowledgeAssetReferences({ pageRelPath: relPath, content: content3 }))
66024
66081
  referenced.add(ref);
66025
66082
  }
@@ -66037,7 +66094,7 @@ async function removeOrphanKnowledgeAssets(projectRoot, currentReferences) {
66037
66094
  function resolveKnowledgeAssetPath(projectRoot, pageRelPath, target) {
66038
66095
  if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("#"))
66039
66096
  return;
66040
- const absolute = resolve16(projectRoot, dirname14(pageRelPath), decodedTarget(target));
66097
+ const absolute = resolve16(projectRoot, dirname15(pageRelPath), decodedTarget(target));
66041
66098
  const root = resolve16(projectRoot, "knowledge", "assets");
66042
66099
  if (absolute !== root && !absolute.startsWith(`${root}${sep3}`))
66043
66100
  return;
@@ -66054,8 +66111,8 @@ var init_knowledgeAssets = __esm(() => {
66054
66111
 
66055
66112
  // src/project/documentEvidenceIndex.ts
66056
66113
  import { Buffer as Buffer3 } from "node:buffer";
66057
- import { mkdir as mkdir12, readFile as readFile30, writeFile as writeFile7 } from "node:fs/promises";
66058
- import { dirname as dirname15, join as join31 } from "node:path";
66114
+ import { mkdir as mkdir13, readFile as readFile31, writeFile as writeFile8 } from "node:fs/promises";
66115
+ import { dirname as dirname16, join as join32 } from "node:path";
66059
66116
  function workspaceStateError(message, detail = {}) {
66060
66117
  return new ContextError(ExitCode.WorkspaceStateError, message, {
66061
66118
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -66069,14 +66126,14 @@ function userInputError(message, detail = {}) {
66069
66126
  });
66070
66127
  }
66071
66128
  function committedManifestRelativePath(sourceType, sourceName) {
66072
- return join31("sources", sourceType, normalizeDocumentSourceName(sourceName), "manifest.json");
66129
+ return join32("sources", sourceType, normalizeDocumentSourceName(sourceName), "manifest.json");
66073
66130
  }
66074
66131
  function runtimeEvidenceIndexRelativePath(sourceType, sourceName) {
66075
- return join31(".tmp", "context-runtime", "evidence", sourceType, normalizeDocumentSourceName(sourceName), "source-index.json");
66132
+ return join32(".tmp", "context-runtime", "evidence", sourceType, normalizeDocumentSourceName(sourceName), "source-index.json");
66076
66133
  }
66077
66134
  async function readJsonFile(path2, next) {
66078
66135
  try {
66079
- return JSON.parse(await readFile30(path2, "utf8"));
66136
+ return JSON.parse(await readFile31(path2, "utf8"));
66080
66137
  } catch (error) {
66081
66138
  const message = error instanceof Error ? error.message : String(error);
66082
66139
  throw workspaceStateError(`document snapshot metadata is unreadable: ${message}`, {
@@ -66094,9 +66151,9 @@ function assertManifestSource(input) {
66094
66151
  }
66095
66152
  }
66096
66153
  async function readCommittedSnapshotFile(input) {
66097
- const absolutePath = join31(input.projectRoot, input.materializedAt, input.path);
66154
+ const absolutePath = join32(input.projectRoot, input.materializedAt, input.path);
66098
66155
  try {
66099
- return await readFile30(absolutePath);
66156
+ return await readFile31(absolutePath);
66100
66157
  } catch (error) {
66101
66158
  const message = error instanceof Error ? error.message : String(error);
66102
66159
  throw workspaceStateError(`document snapshot file is unreadable: ${input.path}: ${message}`, {
@@ -66141,9 +66198,9 @@ async function buildCommittedEvidenceIndex(input) {
66141
66198
  });
66142
66199
  }
66143
66200
  const managed = input.sourceType === "note" || input.sourceType === "sessions" ? await (await Promise.resolve().then(() => (init_managedDocumentSnapshot(), exports_managedDocumentSnapshot))).readManagedDocumentSnapshot(input.projectRoot, input.sourceType, sourceName) : undefined;
66144
- const materializedAt = managed?.materializedAt ?? input.materializedAt ?? join31("sources", input.sourceType, sourceName);
66201
+ const materializedAt = managed?.materializedAt ?? input.materializedAt ?? join32("sources", input.sourceType, sourceName);
66145
66202
  const manifestRelPath = managed ? `sources/${input.sourceType}/${sourceName}` : input.manifestPath ?? committedManifestRelativePath(input.sourceType, sourceName);
66146
- const manifestAbsPath = join31(input.projectRoot, manifestRelPath);
66203
+ const manifestAbsPath = join32(input.projectRoot, manifestRelPath);
66147
66204
  let manifest;
66148
66205
  try {
66149
66206
  manifest = managed?.manifest ?? parseDocumentSnapshotForSource(await readJsonFile(manifestAbsPath, `rerun context run capture:${input.sourceType}:${sourceName} or restore ${manifestRelPath}`), sourceName);
@@ -66223,7 +66280,7 @@ async function buildCommittedEvidenceIndex(input) {
66223
66280
  continue;
66224
66281
  let bytes;
66225
66282
  try {
66226
- bytes = await readFile30(join31(input.projectRoot, materializedAt, asset.path));
66283
+ bytes = await readFile31(join32(input.projectRoot, materializedAt, asset.path));
66227
66284
  } catch (error) {
66228
66285
  const message = error instanceof Error ? error.message : String(error);
66229
66286
  throw workspaceStateError(`document snapshot audit asset is missing: ${asset.path}`, {
@@ -66264,10 +66321,10 @@ async function buildCommittedEvidenceIndex(input) {
66264
66321
  documents
66265
66322
  };
66266
66323
  const runtimeIndexPath = runtimeEvidenceIndexRelativePath(input.sourceType, sourceName);
66267
- const absoluteRuntimeIndexPath = join31(input.projectRoot, runtimeIndexPath);
66324
+ const absoluteRuntimeIndexPath = join32(input.projectRoot, runtimeIndexPath);
66268
66325
  if (input.writeRuntimeIndex ?? true) {
66269
- await mkdir12(dirname15(absoluteRuntimeIndexPath), { recursive: true });
66270
- await writeFile7(absoluteRuntimeIndexPath, `${JSON.stringify(index2, null, 2)}
66326
+ await mkdir13(dirname16(absoluteRuntimeIndexPath), { recursive: true });
66327
+ await writeFile8(absoluteRuntimeIndexPath, `${JSON.stringify(index2, null, 2)}
66271
66328
  `, "utf8");
66272
66329
  }
66273
66330
  return {
@@ -66288,7 +66345,7 @@ var init_documentEvidenceIndex = __esm(() => {
66288
66345
  });
66289
66346
 
66290
66347
  // src/project/assetSourceRegistry.ts
66291
- import { join as join32 } from "node:path";
66348
+ import { join as join33 } from "node:path";
66292
66349
  function emptySourceRegistryLookup(loaded) {
66293
66350
  return {
66294
66351
  loaded,
@@ -66358,10 +66415,10 @@ function registeredDocumentSource(registry2, sourceType, sourceName) {
66358
66415
  return registry2.documents[sourceType].get(sourceName);
66359
66416
  }
66360
66417
  function defaultDocumentMaterializedAt(sourceType, sourceName) {
66361
- return join32("sources", sourceType, sourceName);
66418
+ return join33("sources", sourceType, sourceName);
66362
66419
  }
66363
66420
  function defaultDocumentManifest(materializedAt) {
66364
- return join32(materializedAt, "manifest.json");
66421
+ return join33(materializedAt, "manifest.json");
66365
66422
  }
66366
66423
  async function getCommittedEvidenceIndex(input) {
66367
66424
  const key = `${input.sourceType}:${input.sourceName}:${input.materializedAt}:${input.manifestPath}`;
@@ -66386,8 +66443,8 @@ var init_assetSourceRegistry = __esm(() => {
66386
66443
 
66387
66444
  // src/project/knowledgeAssetRepair.ts
66388
66445
  import { existsSync as existsSync6 } from "node:fs";
66389
- import { mkdir as mkdir13, readFile as readFile31, writeFile as writeFile8 } from "node:fs/promises";
66390
- import { dirname as dirname16 } from "node:path";
66446
+ import { mkdir as mkdir14, readFile as readFile32, writeFile as writeFile9 } from "node:fs/promises";
66447
+ import { dirname as dirname17 } from "node:path";
66391
66448
  function moduleSourceIdentity(source2) {
66392
66449
  const match = /^(file|lark|note|sessions):(.+)$/u.exec(source2);
66393
66450
  if (match?.[1] === undefined || match[2] === undefined)
@@ -66477,7 +66534,7 @@ async function canonicalizeApprovedKnowledgeAssetPair(input) {
66477
66534
  async function bytesEqual(path2, expected) {
66478
66535
  if (!existsSync6(path2))
66479
66536
  return false;
66480
- const actual = await readFile31(path2);
66537
+ const actual = await readFile32(path2);
66481
66538
  return actual.length === expected.length && actual.equals(Buffer.from(expected));
66482
66539
  }
66483
66540
  async function repairApprovedKnowledgeAssetProjections(projectRoot) {
@@ -66550,12 +66607,12 @@ async function repairApprovedKnowledgeAssetProjections(projectRoot) {
66550
66607
  for (const asset of assets.values()) {
66551
66608
  if (await bytesEqual(asset.absPath, asset.bytes))
66552
66609
  continue;
66553
- await mkdir13(dirname16(asset.absPath), { recursive: true });
66554
- await writeFile8(asset.absPath, asset.bytes);
66610
+ await mkdir14(dirname17(asset.absPath), { recursive: true });
66611
+ await writeFile9(asset.absPath, asset.bytes);
66555
66612
  writtenAssets.push(asset.relPath);
66556
66613
  }
66557
66614
  for (const page of pages)
66558
- await writeFile8(page.absPath, page.content, "utf8");
66615
+ await writeFile9(page.absPath, page.content, "utf8");
66559
66616
  const removedAssets = await removeOrphanKnowledgeAssets(projectRoot);
66560
66617
  return {
66561
66618
  repairedPages: pages.map((page) => page.relPath).sort(),
@@ -66653,8 +66710,8 @@ __export(exports_approvedRevisionBatch, {
66653
66710
  observeApprovedRevisionBatch: () => observeApprovedRevisionBatch,
66654
66711
  approvedRevisionCandidateApplied: () => approvedRevisionCandidateApplied
66655
66712
  });
66656
- import { readFile as readFile32 } from "node:fs/promises";
66657
- import { join as join33 } from "node:path";
66713
+ import { readFile as readFile33 } from "node:fs/promises";
66714
+ import { join as join34 } from "node:path";
66658
66715
  async function prepareRevisionBatchContinuation(root, request, batch) {
66659
66716
  const [next, ...remaining] = request.pending_targets ?? [];
66660
66717
  if (!next)
@@ -66734,13 +66791,13 @@ async function observeApprovedRevisionBatch(root, request) {
66734
66791
  for (const original of expected) {
66735
66792
  const candidate = rows.find((row) => row.candidate_id === original.candidate_id);
66736
66793
  const revision = original.approved_revision;
66737
- const bytes = await readFile32(join33(root, "knowledge", revision.previous_path ?? original.path), "utf8").catch((error) => {
66794
+ const bytes = await readFile33(join34(root, "knowledge", revision.previous_path ?? original.path), "utf8").catch((error) => {
66738
66795
  if (error.code === "ENOENT")
66739
66796
  return;
66740
66797
  throw error;
66741
66798
  });
66742
66799
  if (!candidate) {
66743
- const applied = await readFile32(join33(root, "knowledge", original.path), "utf8").catch(() => {
66800
+ const applied = await readFile33(join34(root, "knowledge", original.path), "utf8").catch(() => {
66744
66801
  return;
66745
66802
  });
66746
66803
  if (await approvedRevisionCandidateApplied(root, original, applied))
@@ -66908,15 +66965,15 @@ var init_verifyFrontmatter = __esm(() => {
66908
66965
  });
66909
66966
 
66910
66967
  // src/project/indexerTemplateSnapshots.ts
66911
- import { readFile as readFile33, mkdir as mkdir14 } from "node:fs/promises";
66912
- import { join as join34 } from "node:path";
66968
+ import { readFile as readFile34, mkdir as mkdir15 } from "node:fs/promises";
66969
+ import { join as join35 } from "node:path";
66913
66970
  function object3(value) {
66914
66971
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
66915
66972
  }
66916
66973
  function snapshotPath(root, digest3) {
66917
66974
  if (!/^sha256:[a-f0-9]{64}$/u.test(digest3))
66918
66975
  throw new TypeError("Invalid template snapshot digest");
66919
- return join34(root, ...ROOT, `${digest3.slice(7)}.json`);
66976
+ return join35(root, ...ROOT, `${digest3.slice(7)}.json`);
66920
66977
  }
66921
66978
  async function encodeTemplateSnapshots(root, value) {
66922
66979
  const spec = object3(value);
@@ -66946,7 +67003,7 @@ async function encodeTemplateSnapshots(root, value) {
66946
67003
  const path2 = snapshotPath(root, digest3);
66947
67004
  let existing;
66948
67005
  try {
66949
- existing = await readFile33(path2, "utf8");
67006
+ existing = await readFile34(path2, "utf8");
66950
67007
  } catch (error) {
66951
67008
  if (error.code !== "ENOENT")
66952
67009
  throw error;
@@ -66955,7 +67012,7 @@ async function encodeTemplateSnapshots(root, value) {
66955
67012
  if (indexerProtocolDigest(JSON.parse(existing)) !== digest3)
66956
67013
  throw new TypeError("Template snapshot integrity mismatch");
66957
67014
  } else {
66958
- await mkdir14(join34(root, ...ROOT), { recursive: true });
67015
+ await mkdir15(join35(root, ...ROOT), { recursive: true });
66959
67016
  await atomicWriteFile(path2, canonicalIndexerJson(shared));
66960
67017
  }
66961
67018
  return { protocol: REF, digest: digest3, ...binding ? { binding } : {} };
@@ -66981,7 +67038,7 @@ async function hydrateTemplateSnapshots(root, value) {
66981
67038
  throw new TypeError("Template snapshot has no digest");
66982
67039
  let raw;
66983
67040
  try {
66984
- raw = await readFile33(snapshotPath(root, ref.digest), "utf8");
67041
+ raw = await readFile34(snapshotPath(root, ref.digest), "utf8");
66985
67042
  } catch (error) {
66986
67043
  if (error.code !== "ENOENT")
66987
67044
  throw error;
@@ -67036,8 +67093,8 @@ __export(exports_indexerMainRunStoreRecords, {
67036
67093
  INDEXER_MAIN_RUN_STORE_ROOT: () => INDEXER_MAIN_RUN_STORE_ROOT,
67037
67094
  INDEXER_MAIN_RUN_CURRENT_PATH: () => INDEXER_MAIN_RUN_CURRENT_PATH
67038
67095
  });
67039
- import { readFile as readFile34 } from "node:fs/promises";
67040
- import { join as join35 } from "node:path";
67096
+ import { readFile as readFile35 } from "node:fs/promises";
67097
+ import { join as join36 } from "node:path";
67041
67098
  function isRecord8(value) {
67042
67099
  return value !== null && typeof value === "object" && !Array.isArray(value);
67043
67100
  }
@@ -67048,13 +67105,13 @@ function digestName(digest3) {
67048
67105
  return digest3.slice("sha256:".length);
67049
67106
  }
67050
67107
  function runSpecPath(requestDigest) {
67051
- return join35(INDEXER_MAIN_RUN_STORE_ROOT, "requests", `${digestName(requestDigest)}.json`);
67108
+ return join36(INDEXER_MAIN_RUN_STORE_ROOT, "requests", `${digestName(requestDigest)}.json`);
67052
67109
  }
67053
67110
  function acceptedCachePath(requestDigest) {
67054
- return join35(INDEXER_MAIN_RUN_STORE_ROOT, "accepted", `${digestName(requestDigest)}.json`);
67111
+ return join36(INDEXER_MAIN_RUN_STORE_ROOT, "accepted", `${digestName(requestDigest)}.json`);
67055
67112
  }
67056
67113
  function partitionConvergencePath(attemptDigest) {
67057
- return join35(INDEXER_MAIN_RUN_STORE_ROOT, "partition-convergence", `${digestName(attemptDigest)}.json`);
67114
+ return join36(INDEXER_MAIN_RUN_STORE_ROOT, "partition-convergence", `${digestName(attemptDigest)}.json`);
67058
67115
  }
67059
67116
  function jsonContent(value) {
67060
67117
  const canonical = canonicalIndexerJson(value);
@@ -67065,7 +67122,7 @@ function jsonContent(value) {
67065
67122
  }
67066
67123
  async function readMaybe3(projectRoot, path2) {
67067
67124
  try {
67068
- return await readFile34(join35(projectRoot, path2), "utf8");
67125
+ return await readFile35(join36(projectRoot, path2), "utf8");
67069
67126
  } catch (error) {
67070
67127
  if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
67071
67128
  return;
@@ -67150,7 +67207,7 @@ async function currentLedger(projectRoot) {
67150
67207
  async function currentSpec(input) {
67151
67208
  return reuseCommandFileRead({
67152
67209
  key: "validated-main-run-spec",
67153
- paths: [join35(input.projectRoot, runSpecPath(input.request_digest))],
67210
+ paths: [join36(input.projectRoot, runSpecPath(input.request_digest))],
67154
67211
  read: async () => {
67155
67212
  const value = await readJsonMaybe(input.projectRoot, runSpecPath(input.request_digest));
67156
67213
  if (value === undefined)
@@ -67238,8 +67295,8 @@ var init_indexerMainRunStoreRecords = __esm(() => {
67238
67295
  init_src2();
67239
67296
  init_durableSingleFileTransaction();
67240
67297
  init_durableMultiFileTransaction();
67241
- INDEXER_MAIN_RUN_STORE_ROOT = join35(".tmp", "context-runtime", "indexer", "main-index");
67242
- INDEXER_MAIN_RUN_CURRENT_PATH = join35(INDEXER_MAIN_RUN_STORE_ROOT, "current.json");
67298
+ INDEXER_MAIN_RUN_STORE_ROOT = join36(".tmp", "context-runtime", "indexer", "main-index");
67299
+ INDEXER_MAIN_RUN_CURRENT_PATH = join36(INDEXER_MAIN_RUN_STORE_ROOT, "current.json");
67243
67300
  });
67244
67301
 
67245
67302
  // src/project/indexerPartitionConvergenceStore.ts
@@ -67257,7 +67314,7 @@ var init_indexerMainRunBatchStore = __esm(() => {
67257
67314
  });
67258
67315
 
67259
67316
  // src/project/indexerMainRunStore.ts
67260
- import { join as join36 } from "node:path";
67317
+ import { join as join37 } from "node:path";
67261
67318
  async function readAcceptedMainResultRecordsUnlocked(projectRoot, stage, allowPending = false) {
67262
67319
  await recoverDurableMultiFileTransactions(projectRoot);
67263
67320
  const ledger = await currentLedger(projectRoot);
@@ -67274,7 +67331,7 @@ async function readAcceptedMainResultRecordsUnlocked(projectRoot, stage, allowPe
67274
67331
  paths: [INDEXER_MAIN_RUN_CURRENT_PATH, ...ledger.entries.filter((entry) => entry.state === "accepted").flatMap((entry) => [
67275
67332
  runSpecPath(entry.execution_request_digest),
67276
67333
  acceptedCachePath(entry.execution_request_digest)
67277
- ])].map((path2) => join36(projectRoot, path2)),
67334
+ ])].map((path2) => join37(projectRoot, path2)),
67278
67335
  read: async () => {
67279
67336
  const records = [];
67280
67337
  for (const entry of ledger.entries) {
@@ -67320,8 +67377,8 @@ var init_indexerMainRunStore = __esm(() => {
67320
67377
  });
67321
67378
 
67322
67379
  // src/project/productionDeliveryScope.ts
67323
- import { readFile as readFile35 } from "node:fs/promises";
67324
- import { join as join37, posix as posix2 } from "node:path";
67380
+ import { readFile as readFile36 } from "node:fs/promises";
67381
+ import { join as join38, posix as posix2 } from "node:path";
67325
67382
  async function productionDeliverableArticles(root, phase = "delivery") {
67326
67383
  return withProductionFeedback({ operation: "delivery-scope" }, async () => {
67327
67384
  const stage = await readProductionStage(root);
@@ -67348,7 +67405,7 @@ async function productionDeliverableArticles(root, phase = "delivery") {
67348
67405
  if (phase === "review")
67349
67406
  return [...selected.values()];
67350
67407
  for (const article of selected.values()) {
67351
- const markdown = await readFile35(await safeProjectTarget(root, join37("knowledge", article.path)), "utf8");
67408
+ const markdown = await readFile36(await safeProjectTarget(root, join38("knowledge", article.path)), "utf8");
67352
67409
  for (const link of markdownReaderLinks(markdown)) {
67353
67410
  if (link.image || /^(?:[a-z][a-z\d+.-]*:|\/|#)/iu.test(link.target))
67354
67411
  continue;
@@ -67364,7 +67421,7 @@ async function productionDeliverableArticles(root, phase = "delivery") {
67364
67421
  if (path2.startsWith("../") || unresolved.has(path2) || !formal.byPath.has(path2)) {
67365
67422
  throw new TypeError(`Partial delivery needs its linked approved article: ${article.path} → ${path2}. Finish that article's Review before delivery.`);
67366
67423
  }
67367
- await readFile35(await safeProjectTarget(root, join37("knowledge", path2)), "utf8");
67424
+ await readFile36(await safeProjectTarget(root, join38("knowledge", path2)), "utf8");
67368
67425
  }
67369
67426
  }
67370
67427
  return [...selected.values()];
@@ -67382,11 +67439,11 @@ var init_productionDeliveryScope = __esm(() => {
67382
67439
  });
67383
67440
 
67384
67441
  // src/project/productionCleanup.ts
67385
- import { readFile as readFile36, readdir as readdir10, rm as rm8 } from "node:fs/promises";
67386
- import { join as join38 } from "node:path";
67442
+ import { readFile as readFile37, readdir as readdir10, rm as rm8 } from "node:fs/promises";
67443
+ import { join as join39 } from "node:path";
67387
67444
  async function clearCompletedProduction(root, stage) {
67388
- const pointerPath = join38(PRODUCTION_STAGES_ROOT, "current.json");
67389
- const pointer = await readFile36(await safeProjectTarget(root, pointerPath), "utf8");
67445
+ const pointerPath = join39(PRODUCTION_STAGES_ROOT, "current.json");
67446
+ const pointer = await readFile37(await safeProjectTarget(root, pointerPath), "utf8");
67390
67447
  const current = JSON.parse(pointer);
67391
67448
  if (!current || typeof current !== "object" || !("stage" in current) || current.stage !== stage.id) {
67392
67449
  throw new TypeError("Production stage changed before cleanup; inspect the current stage without clearing its files or task state.");
@@ -67397,15 +67454,15 @@ async function clearCompletedProduction(root, stage) {
67397
67454
  const entries2 = await readdir10(await safeProjectTarget(root, directory));
67398
67455
  for (const entry of entries2)
67399
67456
  if (entry !== "manifest.json")
67400
- await remove(join38(directory, entry));
67457
+ await remove(join39(directory, entry));
67401
67458
  const targets = [];
67402
- for (const path2 of [join38(directory, "manifest.json"), pointerPath]) {
67403
- const content4 = path2 === pointerPath ? pointer : await readFile36(await safeProjectTarget(root, path2), "utf8");
67459
+ for (const path2 of [join39(directory, "manifest.json"), pointerPath]) {
67460
+ const content4 = path2 === pointerPath ? pointer : await readFile37(await safeProjectTarget(root, path2), "utf8");
67404
67461
  targets.push({ path: path2, operation: "delete", base_digest: durableContentDigest(content4), target_digest: null });
67405
67462
  }
67406
67463
  let previous2;
67407
67464
  try {
67408
- previous2 = await readFile36(await safeProjectTarget(root, TASK_PREPARATION_PATH), "utf8");
67465
+ previous2 = await readFile37(await safeProjectTarget(root, TASK_PREPARATION_PATH), "utf8");
67409
67466
  } catch (error) {
67410
67467
  if (error.code !== "ENOENT")
67411
67468
  throw error;
@@ -67439,7 +67496,7 @@ __export(exports_lifecycleCleanup, {
67439
67496
  clearCompletedLifecycle: () => clearCompletedLifecycle
67440
67497
  });
67441
67498
  import { readdir as readdir11, rm as rm9 } from "node:fs/promises";
67442
- import { join as join39 } from "node:path";
67499
+ import { join as join40 } from "node:path";
67443
67500
  async function clearCompletedLifecycle(projectRoot) {
67444
67501
  const production = await readProductionStage(projectRoot);
67445
67502
  if (production) {
@@ -67456,9 +67513,9 @@ async function clearCompletedLifecycle(projectRoot) {
67456
67513
  }
67457
67514
  for (const path2 of COMPLETED_RUNTIME_PATHS) {
67458
67515
  if (path2 !== INDEXER_RUNTIME_ROOT)
67459
- await rm9(join39(projectRoot, path2), { recursive: true, force: true });
67516
+ await rm9(join40(projectRoot, path2), { recursive: true, force: true });
67460
67517
  }
67461
- const indexer = join39(projectRoot, INDEXER_RUNTIME_ROOT);
67518
+ const indexer = join40(projectRoot, INDEXER_RUNTIME_ROOT);
67462
67519
  const entries2 = await readdir11(indexer).catch((error) => {
67463
67520
  if (error.code === "ENOENT")
67464
67521
  return [];
@@ -67466,9 +67523,9 @@ async function clearCompletedLifecycle(projectRoot) {
67466
67523
  });
67467
67524
  for (const name2 of entries2)
67468
67525
  if (name2 !== "candidate-compile") {
67469
- await rm9(join39(indexer, name2), { recursive: true, force: true });
67526
+ await rm9(join40(indexer, name2), { recursive: true, force: true });
67470
67527
  }
67471
- const compile = join39(indexer, "candidate-compile");
67528
+ const compile = join40(indexer, "candidate-compile");
67472
67529
  const compiled = await readdir11(compile).catch((error) => {
67473
67530
  if (error.code === "ENOENT")
67474
67531
  return [];
@@ -67476,11 +67533,11 @@ async function clearCompletedLifecycle(projectRoot) {
67476
67533
  });
67477
67534
  for (const name2 of compiled)
67478
67535
  if (name2 !== "current.json") {
67479
- await rm9(join39(compile, name2), { recursive: true, force: true });
67536
+ await rm9(join40(compile, name2), { recursive: true, force: true });
67480
67537
  }
67481
- await rm9(join39(compile, "current.json"), { force: true });
67538
+ await rm9(join40(compile, "current.json"), { force: true });
67482
67539
  await rm9(indexer, { recursive: true, force: true });
67483
- await rm9(join39(projectRoot, APPROVED_REVISION_PATH), { force: true });
67540
+ await rm9(join40(projectRoot, APPROVED_REVISION_PATH), { force: true });
67484
67541
  if (production)
67485
67542
  await clearCompletedProduction(projectRoot, production);
67486
67543
  }
@@ -67653,8 +67710,8 @@ var init_indexerRequiredArticleReview = __esm(() => {
67653
67710
 
67654
67711
  // src/project/partialDelivery.ts
67655
67712
  import { existsSync as existsSync7 } from "node:fs";
67656
- import { readFile as readFile37 } from "node:fs/promises";
67657
- import { join as join40, posix as posix3 } from "node:path";
67713
+ import { readFile as readFile38 } from "node:fs/promises";
67714
+ import { join as join41, posix as posix3 } from "node:path";
67658
67715
  async function selectPartialDelivery(root) {
67659
67716
  const candidates = await readCandidateRecords(root);
67660
67717
  if (!candidates.some((item) => item.status === "draft"))
@@ -67668,7 +67725,7 @@ async function selectPartialDelivery(root) {
67668
67725
  }
67669
67726
  const pages = [...revision.batch_candidates ?? [], ...revision.candidate ? [revision.candidate] : []].map((item) => ({ path: `knowledge/${item.path}`, ref: item.article_id }));
67670
67727
  const unresolved = new Set(candidates.map((item) => `knowledge/${item.path}`));
67671
- const approved = pages.filter((item) => !unresolved.has(item.path) && existsSync7(join40(root, item.path)));
67728
+ const approved = pages.filter((item) => !unresolved.has(item.path) && existsSync7(join41(root, item.path)));
67672
67729
  if (approved.length === 0)
67673
67730
  return;
67674
67731
  await assertIndependentPages(root, approved.map((item) => item.path), unresolved);
@@ -67678,7 +67735,7 @@ async function assertIndependentPages(root, paths, unresolved) {
67678
67735
  for (const path2 of paths) {
67679
67736
  if (unresolved.has(path2))
67680
67737
  throw new TypeError(`Selected delivery page now needs Review: ${path2}. Return to the current Route.`);
67681
- const markdown = await readFile37(join40(root, path2), "utf8");
67738
+ const markdown = await readFile38(join41(root, path2), "utf8");
67682
67739
  for (const link of markdownReaderLinks(markdown)) {
67683
67740
  if (link.image || /^(?:[a-z][a-z\d+.-]*:|\/|#)/iu.test(link.target))
67684
67741
  continue;
@@ -67689,7 +67746,7 @@ async function assertIndependentPages(root, paths, unresolved) {
67689
67746
  continue;
67690
67747
  }
67691
67748
  const target = posix3.normalize(posix3.join(posix3.dirname(path2), href));
67692
- if (target.startsWith("knowledge/") && /\.md$/iu.test(target) && (unresolved.has(target) || !existsSync7(join40(root, target)))) {
67749
+ if (target.startsWith("knowledge/") && /\.md$/iu.test(target) && (unresolved.has(target) || !existsSync7(join41(root, target)))) {
67693
67750
  throw new TypeError(`Partial delivery must include its linked page: ${path2} → ${target}. Finish that page's Review/repair, then request delivery again; existing approvals remain.`);
67694
67751
  }
67695
67752
  }
@@ -67716,11 +67773,11 @@ var init_partialDelivery = __esm(() => {
67716
67773
  });
67717
67774
 
67718
67775
  // src/project/revisionDelivery.ts
67719
- import { readFile as readFile38, rm as rm10 } from "node:fs/promises";
67720
- import { join as join41 } from "node:path";
67776
+ import { readFile as readFile39, rm as rm10 } from "node:fs/promises";
67777
+ import { join as join42 } from "node:path";
67721
67778
  async function readRevisionDelivery(root) {
67722
67779
  try {
67723
- return stateSchema2.parse(JSON.parse(await readFile38(join41(root, FILE), "utf8")));
67780
+ return stateSchema2.parse(JSON.parse(await readFile39(join42(root, FILE), "utf8")));
67724
67781
  } catch (error) {
67725
67782
  if (error.code === "ENOENT")
67726
67783
  return;
@@ -67731,7 +67788,7 @@ function requestRevisionDelivery(root) {
67731
67788
  return withProjectWriteLock(root, "request-revision-delivery", async () => {
67732
67789
  const partial = await selectPartialDelivery(root);
67733
67790
  if (partial) {
67734
- await atomicWriteFile(join41(root, FILE), JSON.stringify(stateSchema2.parse({ partial, closed: false })) + `
67791
+ await atomicWriteFile(join42(root, FILE), JSON.stringify(stateSchema2.parse({ partial, closed: false })) + `
67735
67792
  `);
67736
67793
  return;
67737
67794
  }
@@ -67749,7 +67806,7 @@ function closeRevisionDelivery(root) {
67749
67806
  const state = await readRevisionDelivery(root);
67750
67807
  if (!state)
67751
67808
  return false;
67752
- await atomicWriteFile(join41(root, FILE), JSON.stringify({ ...state, closed: true }) + `
67809
+ await atomicWriteFile(join42(root, FILE), JSON.stringify({ ...state, closed: true }) + `
67753
67810
  `);
67754
67811
  return true;
67755
67812
  });
@@ -67757,7 +67814,7 @@ function closeRevisionDelivery(root) {
67757
67814
  function completeRevisionDelivery(root) {
67758
67815
  return withProjectWriteLock(root, "complete-revision-delivery", async () => {
67759
67816
  if ((await readRevisionDelivery(root))?.closed)
67760
- await rm10(join41(root, FILE), { force: true });
67817
+ await rm10(join42(root, FILE), { force: true });
67761
67818
  });
67762
67819
  }
67763
67820
  var FILE, stateSchema2;
@@ -67772,7 +67829,7 @@ var init_revisionDelivery = __esm(() => {
67772
67829
  init_partialDelivery();
67773
67830
  init_approvedRevision();
67774
67831
  init_candidateLedger();
67775
- FILE = join41(LIFECYCLE_ROOT, "revision-delivery.json");
67832
+ FILE = join42(LIFECYCLE_ROOT, "revision-delivery.json");
67776
67833
  stateSchema2 = exports_external.object({
67777
67834
  partial: exports_external.object({
67778
67835
  kind: exports_external.literal("revision"),
@@ -67784,8 +67841,8 @@ var init_revisionDelivery = __esm(() => {
67784
67841
  });
67785
67842
 
67786
67843
  // src/project/approvedKnowledgeSnapshots.ts
67787
- import { readFile as readFile39 } from "node:fs/promises";
67788
- import { join as join42 } from "node:path";
67844
+ import { readFile as readFile40 } from "node:fs/promises";
67845
+ import { join as join43 } from "node:path";
67789
67846
  function approvedKnowledgeSnapshotsFromStructure(structure) {
67790
67847
  return validateArticleStructureEntries(structure?.articles ?? []);
67791
67848
  }
@@ -67794,7 +67851,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
67794
67851
  return;
67795
67852
  let before;
67796
67853
  try {
67797
- before = await readFile39(join42(input.projectRoot, STRUCTURE_PATH2), "utf8");
67854
+ before = await readFile40(join43(input.projectRoot, STRUCTURE_PATH2), "utf8");
67798
67855
  } catch (error) {
67799
67856
  if (error.code !== "ENOENT")
67800
67857
  throw error;
@@ -67857,7 +67914,7 @@ import {
67857
67914
  unlinkSync,
67858
67915
  writeFileSync as writeFileSync2
67859
67916
  } from "node:fs";
67860
- import { dirname as dirname17, join as join43 } from "node:path";
67917
+ import { dirname as dirname18, join as join44 } from "node:path";
67861
67918
  function isRecord9(value) {
67862
67919
  return value !== null && typeof value === "object" && !Array.isArray(value);
67863
67920
  }
@@ -67875,7 +67932,7 @@ function parseEvent(value) {
67875
67932
  };
67876
67933
  }
67877
67934
  function runtimeEventOutboxPath(projectRoot) {
67878
- return join43(projectRoot, OUTBOX_RELATIVE_PATH);
67935
+ return join44(projectRoot, OUTBOX_RELATIVE_PATH);
67879
67936
  }
67880
67937
  function readRuntimeEventOutboxFile(path2) {
67881
67938
  if (!existsSync8(path2))
@@ -67925,7 +67982,7 @@ function sleepSync(durationMs) {
67925
67982
  }
67926
67983
  function withOutboxLock(projectRoot, work) {
67927
67984
  const path2 = runtimeEventOutboxPath(projectRoot);
67928
- mkdirSync2(dirname17(path2), { recursive: true });
67985
+ mkdirSync2(dirname18(path2), { recursive: true });
67929
67986
  const lockPath = `${path2}.lock`;
67930
67987
  let lockFd;
67931
67988
  for (let attempt = 0;attempt < OUTBOX_LOCK_RETRIES; attempt++) {
@@ -68006,7 +68063,7 @@ function acknowledgeRuntimeEventOutbox(projectRoot, eventIds) {
68006
68063
  }
68007
68064
  var OUTBOX_EVENT_SCHEMA = "context.runtime-event-outbox.event.v1", OUTBOX_ACK_SCHEMA = "context.runtime-event-outbox.ack.v1", OUTBOX_RELATIVE_PATH, OUTBOX_LOCK_STALE_MS = 30000, OUTBOX_LOCK_RETRY_MS = 10, OUTBOX_LOCK_RETRIES = 100;
68008
68065
  var init_runtimeEventOutbox = __esm(() => {
68009
- OUTBOX_RELATIVE_PATH = join43(".tmp", "context-runtime", "logs", "outbox.jsonl");
68066
+ OUTBOX_RELATIVE_PATH = join44(".tmp", "context-runtime", "logs", "outbox.jsonl");
68010
68067
  });
68011
68068
 
68012
68069
  // src/runtimeEvents.ts
@@ -68019,7 +68076,7 @@ import {
68019
68076
  writeFileSync as writeFileSync3
68020
68077
  } from "node:fs";
68021
68078
  import { spawn as spawn2 } from "node:child_process";
68022
- import { dirname as dirname18, join as join44 } from "node:path";
68079
+ import { dirname as dirname19, join as join45 } from "node:path";
68023
68080
  import { fileURLToPath as fileURLToPath3 } from "node:url";
68024
68081
  function isRecord10(value) {
68025
68082
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -68120,9 +68177,9 @@ async function describeRuntimeEventSink(sink, cwd) {
68120
68177
  }
68121
68178
  function readRuntimePackageMetadata() {
68122
68179
  try {
68123
- let dir = dirname18(fileURLToPath3(import.meta.url));
68180
+ let dir = dirname19(fileURLToPath3(import.meta.url));
68124
68181
  for (let index2 = 0;index2 < 8; index2++) {
68125
- const packagePath = join44(dir, "package.json");
68182
+ const packagePath = join45(dir, "package.json");
68126
68183
  if (existsSync9(packagePath)) {
68127
68184
  const parsed = JSON.parse(readFileSync4(packagePath, "utf8"));
68128
68185
  if (isRecord10(parsed)) {
@@ -68132,7 +68189,7 @@ function readRuntimePackageMetadata() {
68132
68189
  };
68133
68190
  }
68134
68191
  }
68135
- const parent = dirname18(dir);
68192
+ const parent = dirname19(dir);
68136
68193
  if (parent === dir)
68137
68194
  break;
68138
68195
  dir = parent;
@@ -68259,7 +68316,7 @@ function dispatchCommand(sink, batch, cwd) {
68259
68316
  });
68260
68317
  }
68261
68318
  function runtimeEventStatePath(cwd) {
68262
- return join44(cwd, ".tmp", "context-runtime", RUNTIME_EVENT_STATE_FILE);
68319
+ return join45(cwd, ".tmp", "context-runtime", RUNTIME_EVENT_STATE_FILE);
68263
68320
  }
68264
68321
  function readRuntimeEventState(cwd) {
68265
68322
  try {
@@ -68309,7 +68366,7 @@ function persistDeliveredWorkspaceActive(cwd, events) {
68309
68366
  return;
68310
68367
  try {
68311
68368
  const statePath = runtimeEventStatePath(cwd);
68312
- const stateDir = dirname18(statePath);
68369
+ const stateDir = dirname19(statePath);
68313
68370
  const temporaryPath = `${statePath}.${process.pid}.tmp`;
68314
68371
  mkdirSync3(stateDir, { recursive: true });
68315
68372
  writeFileSync3(temporaryPath, `${JSON.stringify({
@@ -68615,10 +68672,10 @@ var init_approvedStructureInputHash = () => {};
68615
68672
 
68616
68673
  // src/project/verifyApprovedStructure.ts
68617
68674
  import { existsSync as existsSync10 } from "node:fs";
68618
- import { join as join45 } from "node:path";
68675
+ import { join as join46 } from "node:path";
68619
68676
  async function validateApprovedStructure(input) {
68620
68677
  const issue = (code, path3, message) => input.issues.push({ severity: "error", code, path: path3, message });
68621
- const path2 = join45(input.projectRoot, STRUCTURE_PATH3);
68678
+ const path2 = join46(input.projectRoot, STRUCTURE_PATH3);
68622
68679
  if (!input.structureOverride && !existsSync10(path2))
68623
68680
  return;
68624
68681
  let parsed;
@@ -68685,8 +68742,8 @@ var init_verifyApprovedStructure = __esm(() => {
68685
68742
  // src/project/packageTemplateReview.ts
68686
68743
  import { createHash as createHash12 } from "node:crypto";
68687
68744
  import { existsSync as existsSync11 } from "node:fs";
68688
- import { mkdir as mkdir15, readFile as readFile40, readdir as readdir12, writeFile as writeFile9 } from "node:fs/promises";
68689
- import { dirname as dirname19, join as join46, relative as relative13, resolve as resolve17 } from "node:path";
68745
+ import { mkdir as mkdir16, readFile as readFile41, readdir as readdir12, writeFile as writeFile10 } from "node:fs/promises";
68746
+ import { dirname as dirname20, join as join47, relative as relative13, resolve as resolve17 } from "node:path";
68690
68747
  async function templateFiles(root) {
68691
68748
  if (!existsSync11(root))
68692
68749
  return [];
@@ -68694,7 +68751,7 @@ async function templateFiles(root) {
68694
68751
  const visit2 = async (dir) => {
68695
68752
  const entries2 = await readdir12(dir, { withFileTypes: true });
68696
68753
  for (const entry of entries2) {
68697
- const absolutePath = join46(dir, entry.name);
68754
+ const absolutePath = join47(dir, entry.name);
68698
68755
  if (entry.isDirectory()) {
68699
68756
  await visit2(absolutePath);
68700
68757
  continue;
@@ -68703,7 +68760,7 @@ async function templateFiles(root) {
68703
68760
  continue;
68704
68761
  files.push({
68705
68762
  path: relative13(root, absolutePath).split(/[/\\]+/u).join("/"),
68706
- content: await readFile40(absolutePath, "utf8")
68763
+ content: await readFile41(absolutePath, "utf8")
68707
68764
  });
68708
68765
  }
68709
68766
  };
@@ -68721,18 +68778,18 @@ function isMarker(value) {
68721
68778
  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");
68722
68779
  }
68723
68780
  async function readMarker(templateRoot) {
68724
- const markerPath = join46(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
68781
+ const markerPath = join47(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
68725
68782
  if (!existsSync11(markerPath))
68726
68783
  return null;
68727
68784
  try {
68728
- const parsed = JSON.parse(await readFile40(markerPath, "utf8"));
68785
+ const parsed = JSON.parse(await readFile41(markerPath, "utf8"));
68729
68786
  return isMarker(parsed) ? parsed : "invalid";
68730
68787
  } catch {
68731
68788
  return "invalid";
68732
68789
  }
68733
68790
  }
68734
68791
  async function writeStarterTemplateReviewMarker(templateRoot) {
68735
- const markerPath = join46(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
68792
+ const markerPath = join47(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
68736
68793
  if (existsSync11(markerPath))
68737
68794
  return false;
68738
68795
  const marker = {
@@ -68740,8 +68797,8 @@ async function writeStarterTemplateReviewMarker(templateRoot) {
68740
68797
  starter_digest: await templateDigest(templateRoot),
68741
68798
  disposition: "review-required"
68742
68799
  };
68743
- await mkdir15(dirname19(markerPath), { recursive: true });
68744
- await writeFile9(markerPath, `${JSON.stringify(marker, null, 2)}
68800
+ await mkdir16(dirname20(markerPath), { recursive: true });
68801
+ await writeFile10(markerPath, `${JSON.stringify(marker, null, 2)}
68745
68802
  `, "utf8");
68746
68803
  return true;
68747
68804
  }
@@ -68760,7 +68817,7 @@ async function inspectPackageTemplateReview(projectRoot, pkg) {
68760
68817
  packageName: pkg.name,
68761
68818
  templatePath: pkg.template.path,
68762
68819
  state: "invalid",
68763
- diagnostic: `${join46(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
68820
+ diagnostic: `${join47(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
68764
68821
  };
68765
68822
  }
68766
68823
  const currentDigest2 = await templateDigest(templateRoot);
@@ -68801,15 +68858,15 @@ async function acceptStarterPackageTemplates(input) {
68801
68858
  alreadyResolved.push(pkg.name);
68802
68859
  continue;
68803
68860
  }
68804
- const markerPath = join46(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
68805
- const marker = await readMarker(join46(input.projectRoot, pkg.template.path));
68861
+ const markerPath = join47(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
68862
+ const marker = await readMarker(join47(input.projectRoot, pkg.template.path));
68806
68863
  if (marker === null || marker === "invalid") {
68807
68864
  throw new ContextError(ExitCode.WorkspaceStateError, "package template review marker changed before acceptance", {
68808
68865
  category: ErrorCategory.WorkspaceStateInvalid,
68809
68866
  packageName: pkg.name
68810
68867
  });
68811
68868
  }
68812
- await writeFile9(markerPath, `${JSON.stringify({
68869
+ await writeFile10(markerPath, `${JSON.stringify({
68813
68870
  ...marker,
68814
68871
  disposition: "starter-accepted"
68815
68872
  }, null, 2)}
@@ -69088,16 +69145,16 @@ __export(exports_workspace, {
69088
69145
  PROJECT_LANGUAGES: () => PROJECT_LANGUAGES
69089
69146
  });
69090
69147
  import { existsSync as existsSync12, readFileSync as readFileSync5, statSync as statSync3 } from "node:fs";
69091
- import { mkdir as mkdir16, readFile as readFile41, readdir as readdir13, writeFile as writeFile10 } from "node:fs/promises";
69148
+ import { mkdir as mkdir17, readFile as readFile42, readdir as readdir13, writeFile as writeFile11 } from "node:fs/promises";
69092
69149
  import { createRequire as createRequire4 } from "node:module";
69093
- import { basename as basename6, dirname as dirname20, isAbsolute as isAbsolute11, join as join47, parse as parse7, relative as relative14, resolve as resolve18 } from "node:path";
69150
+ import { basename as basename6, dirname as dirname21, isAbsolute as isAbsolute11, join as join48, parse as parse7, relative as relative14, resolve as resolve18 } from "node:path";
69094
69151
  import { fileURLToPath as fileURLToPath4 } from "node:url";
69095
69152
  import { createJiti } from "jiti";
69096
69153
  function isRecord11(value) {
69097
69154
  return value !== null && typeof value === "object" && !Array.isArray(value);
69098
69155
  }
69099
69156
  function readPackageJson(root) {
69100
- const packagePath = join47(root, "package.json");
69157
+ const packagePath = join48(root, "package.json");
69101
69158
  if (!existsSync12(packagePath))
69102
69159
  return null;
69103
69160
  try {
@@ -69121,22 +69178,22 @@ function resolveExportImportTarget(packageJsonPath) {
69121
69178
  return null;
69122
69179
  const exportsField = parsed.exports;
69123
69180
  if (typeof exportsField === "string") {
69124
- return join47(dirname20(packageJsonPath), exportsField);
69181
+ return join48(dirname21(packageJsonPath), exportsField);
69125
69182
  }
69126
69183
  if (isRecord11(exportsField)) {
69127
69184
  const rootExport = exportsField["."];
69128
69185
  if (typeof rootExport === "string") {
69129
- return join47(dirname20(packageJsonPath), rootExport);
69186
+ return join48(dirname21(packageJsonPath), rootExport);
69130
69187
  }
69131
69188
  if (isRecord11(rootExport) && typeof rootExport.import === "string") {
69132
- return join47(dirname20(packageJsonPath), rootExport.import);
69189
+ return join48(dirname21(packageJsonPath), rootExport.import);
69133
69190
  }
69134
69191
  }
69135
69192
  if (typeof parsed.module === "string") {
69136
- return join47(dirname20(packageJsonPath), parsed.module);
69193
+ return join48(dirname21(packageJsonPath), parsed.module);
69137
69194
  }
69138
69195
  if (typeof parsed.main === "string") {
69139
- return join47(dirname20(packageJsonPath), parsed.main);
69196
+ return join48(dirname21(packageJsonPath), parsed.main);
69140
69197
  }
69141
69198
  return null;
69142
69199
  }
@@ -69152,16 +69209,16 @@ function resolveContextSdkImportAlias(entryPath) {
69152
69209
  return "@c4a/context";
69153
69210
  }
69154
69211
  function readCurrentPackageVersion() {
69155
- let dir = dirname20(fileURLToPath4(import.meta.url));
69212
+ let dir = dirname21(fileURLToPath4(import.meta.url));
69156
69213
  for (let index2 = 0;index2 < 8; index2++) {
69157
- const packagePath = join47(dir, "package.json");
69214
+ const packagePath = join48(dir, "package.json");
69158
69215
  if (existsSync12(packagePath)) {
69159
69216
  const parsed = readPackageJson(dir);
69160
69217
  if (typeof parsed?.version === "string" && parsed.version.trim().length > 0) {
69161
69218
  return parsed.version;
69162
69219
  }
69163
69220
  }
69164
- const parent = dirname20(dir);
69221
+ const parent = dirname21(dir);
69165
69222
  if (parent === dir)
69166
69223
  break;
69167
69224
  dir = parent;
@@ -69216,7 +69273,7 @@ function findContextWorkspaceExpectation(startDir = process.cwd()) {
69216
69273
  }
69217
69274
  if (dir === root)
69218
69275
  return null;
69219
- const parent = dirname20(dir);
69276
+ const parent = dirname21(dir);
69220
69277
  if (parent === dir)
69221
69278
  return null;
69222
69279
  dir = parent;
@@ -69250,7 +69307,7 @@ function findContextProjectRoot(startDir = process.cwd()) {
69250
69307
  return { projectRoot: dir };
69251
69308
  if (dir === root)
69252
69309
  return null;
69253
- const parent = dirname20(dir);
69310
+ const parent = dirname21(dir);
69254
69311
  if (parent === dir)
69255
69312
  return null;
69256
69313
  dir = parent;
@@ -69262,7 +69319,7 @@ function normalizeProjectDir(cwd, projectDir) {
69262
69319
  if (resolved.endsWith(".code-workspace") && existsSync12(resolved)) {
69263
69320
  try {
69264
69321
  if (statSync3(resolved).isFile())
69265
- return dirname20(resolved);
69322
+ return dirname21(resolved);
69266
69323
  } catch {}
69267
69324
  }
69268
69325
  return resolved;
@@ -69329,15 +69386,15 @@ async function writeIfMissing(path2, content3, result) {
69329
69386
  result.kept.push(path2);
69330
69387
  return;
69331
69388
  }
69332
- await mkdir16(dirname20(path2), { recursive: true });
69333
- await writeFile10(path2, content3, "utf8");
69389
+ await mkdir17(dirname21(path2), { recursive: true });
69390
+ await writeFile11(path2, content3, "utf8");
69334
69391
  result.created.push(path2);
69335
69392
  }
69336
69393
  async function listStaticTemplateFiles(root, dir = root) {
69337
69394
  const entries2 = await readdir13(dir, { withFileTypes: true });
69338
69395
  const files = [];
69339
69396
  for (const entry of entries2) {
69340
- const absolutePath = join47(dir, entry.name);
69397
+ const absolutePath = join48(dir, entry.name);
69341
69398
  if (entry.isDirectory()) {
69342
69399
  files.push(...await listStaticTemplateFiles(root, absolutePath));
69343
69400
  continue;
@@ -69354,7 +69411,7 @@ async function listStaticTemplateFiles(root, dir = root) {
69354
69411
  function resolveContextPackageTemplatesRoot() {
69355
69412
  try {
69356
69413
  const packageJsonPath = createRequire4(import.meta.url).resolve("@c4a/context/package.json");
69357
- const templateRoot = join47(dirname20(packageJsonPath), "templates", "package-templates");
69414
+ const templateRoot = join48(dirname21(packageJsonPath), "templates", "package-templates");
69358
69415
  if (existsSync12(templateRoot))
69359
69416
  return templateRoot;
69360
69417
  } catch {}
@@ -69366,7 +69423,7 @@ function resolveContextPackageTemplatesRoot() {
69366
69423
  }
69367
69424
  async function writeDefaultPackageTemplates(projectRoot, result, language) {
69368
69425
  const defaultRoot = resolveContextPackageTemplatesRoot();
69369
- const templateRoot = language === "zh-CN" ? join47(dirname20(defaultRoot), "package-templates.zh-CN") : defaultRoot;
69426
+ const templateRoot = language === "zh-CN" ? join48(dirname21(defaultRoot), "package-templates.zh-CN") : defaultRoot;
69370
69427
  if (!existsSync12(templateRoot)) {
69371
69428
  throw new ContextError(ExitCode.WorkspaceStateError, `missing ${language} @c4a/context package templates`, {
69372
69429
  category: ErrorCategory.WorkspaceStateInvalid,
@@ -69376,21 +69433,21 @@ async function writeDefaultPackageTemplates(projectRoot, result, language) {
69376
69433
  }
69377
69434
  const files = await listStaticTemplateFiles(templateRoot);
69378
69435
  for (const file of files) {
69379
- await writeIfMissing(join47(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile41(file.absolutePath, "utf8"), result);
69436
+ await writeIfMissing(join48(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile42(file.absolutePath, "utf8"), result);
69380
69437
  }
69381
69438
  const templateKinds = [...new Set(files.map((file) => file.relativePath.split("/")[0]).filter((value) => value !== undefined && value.length > 0))];
69382
69439
  for (const templateKind of templateKinds) {
69383
- const root = join47(projectRoot, "src", "package-templates", templateKind);
69440
+ const root = join48(projectRoot, "src", "package-templates", templateKind);
69384
69441
  if (await writeStarterTemplateReviewMarker(root)) {
69385
- result.created.push(join47(root, PACKAGE_TEMPLATE_REVIEW_FILE));
69442
+ result.created.push(join48(root, PACKAGE_TEMPLATE_REVIEW_FILE));
69386
69443
  } else {
69387
- result.kept.push(join47(root, PACKAGE_TEMPLATE_REVIEW_FILE));
69444
+ result.kept.push(join48(root, PACKAGE_TEMPLATE_REVIEW_FILE));
69388
69445
  }
69389
69446
  }
69390
69447
  }
69391
69448
  function resolveLocalSdkDependency() {
69392
69449
  const packageJsonPath = createRequire4(import.meta.url).resolve("@c4a/context/package.json");
69393
- return `file:${dirname20(packageJsonPath)}`;
69450
+ return `file:${dirname21(packageJsonPath)}`;
69394
69451
  }
69395
69452
  function resolveSdkDependency(dev, version2) {
69396
69453
  return dev === true ? resolveLocalSdkDependency() : version2;
@@ -69474,23 +69531,23 @@ async function initContextProject(input) {
69474
69531
  kept: []
69475
69532
  };
69476
69533
  for (const dir of PROJECT_DIRS) {
69477
- await mkdir16(join47(projectRoot, dir), { recursive: true });
69534
+ await mkdir17(join48(projectRoot, dir), { recursive: true });
69478
69535
  }
69479
69536
  for (const dir of PROJECT_SCRATCH_DIRS) {
69480
- await mkdir16(join47(projectRoot, dir), { recursive: true });
69537
+ await mkdir17(join48(projectRoot, dir), { recursive: true });
69481
69538
  }
69482
- await mkdir16(join47(projectRoot, "sources", "repo"), { recursive: true });
69483
- await mkdir16(join47(projectRoot, "sources", "file"), { recursive: true });
69484
- await mkdir16(join47(projectRoot, "sources", "lark"), { recursive: true });
69485
- await writeIfMissing(join47(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
69486
- await writeIfMissing(join47(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
69539
+ await mkdir17(join48(projectRoot, "sources", "repo"), { recursive: true });
69540
+ await mkdir17(join48(projectRoot, "sources", "file"), { recursive: true });
69541
+ await mkdir17(join48(projectRoot, "sources", "lark"), { recursive: true });
69542
+ await writeIfMissing(join48(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
69543
+ await writeIfMissing(join48(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
69487
69544
  await writeDefaultPackageTemplates(projectRoot, result, language);
69488
- await writeIfMissing(join47(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
69489
- await writeIfMissing(join47(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
69490
- await writeIfMissing(join47(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
69491
- await writeIfMissing(join47(projectRoot, ".gitignore"), renderGitignore(), result);
69492
- await writeIfMissing(join47(projectRoot, "README.md"), renderReadme(projectName, language), result);
69493
- await writeIfMissing(join47(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
69545
+ await writeIfMissing(join48(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
69546
+ await writeIfMissing(join48(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
69547
+ await writeIfMissing(join48(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
69548
+ await writeIfMissing(join48(projectRoot, ".gitignore"), renderGitignore(), result);
69549
+ await writeIfMissing(join48(projectRoot, "README.md"), renderReadme(projectName, language), result);
69550
+ await writeIfMissing(join48(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
69494
69551
  if (input.debug === true)
69495
69552
  await enableContextDebug(projectRoot, "init");
69496
69553
  return result;
@@ -69504,7 +69561,7 @@ async function loadContextProjectModule(root) {
69504
69561
  next: "Ensure package.json declares context.project=true and context.entry points to src/index.ts, then rerun the command."
69505
69562
  });
69506
69563
  }
69507
- const entryPath = join47(root, projectConfig.entry);
69564
+ const entryPath = join48(root, projectConfig.entry);
69508
69565
  const jiti = createJiti(entryPath, {
69509
69566
  alias: {
69510
69567
  "@c4a/context": resolveContextSdkImportAlias(entryPath)
@@ -69574,7 +69631,7 @@ var init_workspace = __esm(() => {
69574
69631
  init_debugTrace();
69575
69632
  init_projectModulePolicy();
69576
69633
  PROJECT_DIRS = ["src", "sources", "knowledge", "dist"];
69577
- PROJECT_SCRATCH_DIRS = [join47(".tmp", "agent-payloads")];
69634
+ PROJECT_SCRATCH_DIRS = [join48(".tmp", "agent-payloads")];
69578
69635
  PROJECT_LANGUAGES = ["en", "zh-CN"];
69579
69636
  });
69580
69637
 
@@ -69672,7 +69729,7 @@ var init_verifyDiagnostics = __esm(() => {
69672
69729
 
69673
69730
  // src/project/verify.ts
69674
69731
  import { existsSync as existsSync13 } from "node:fs";
69675
- import { join as join48 } from "node:path";
69732
+ import { join as join49 } from "node:path";
69676
69733
  function evidenceStatusForIssues(issues) {
69677
69734
  if (issues.some((issue) => issue.severity === "error"))
69678
69735
  return "fail";
@@ -69746,7 +69803,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
69746
69803
  pageRelPath: `knowledge/${file.relPath}`,
69747
69804
  content: content3
69748
69805
  })) {
69749
- if (!existsSync13(join48(projectRoot, assetPath))) {
69806
+ if (!existsSync13(join49(projectRoot, assetPath))) {
69750
69807
  issues.push({
69751
69808
  severity: "error",
69752
69809
  code: "approved-resource-missing",
@@ -69882,8 +69939,8 @@ __export(exports_close, {
69882
69939
  approvedKnowledgeInputHash: () => approvedKnowledgeInputHash
69883
69940
  });
69884
69941
  import { existsSync as existsSync14 } from "node:fs";
69885
- import { mkdir as mkdir17, writeFile as writeFile11 } from "node:fs/promises";
69886
- import { dirname as dirname21, join as join49 } from "node:path";
69942
+ import { mkdir as mkdir18, writeFile as writeFile12 } from "node:fs/promises";
69943
+ import { dirname as dirname22, join as join50 } from "node:path";
69887
69944
  function parseFrontmatter4(content3) {
69888
69945
  const match = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(content3);
69889
69946
  if (match?.[1] === undefined)
@@ -69947,10 +70004,10 @@ async function deriveApprovedStructure(projectRoot) {
69947
70004
  }
69948
70005
  async function writeApprovedStructureProjection(projectRoot) {
69949
70006
  const { inputHash, structure, compactFiles } = await deriveApprovedStructure(projectRoot);
69950
- const outputPath = join49(projectRoot, STRUCTURE_PATH4);
69951
- await mkdir17(dirname21(outputPath), { recursive: true });
69952
- await writeFile11(outputPath, import_yaml30.default.stringify(structure), "utf8");
69953
- await Promise.all(compactFiles.map((file) => writeFile11(file.absPath, file.content, "utf8")));
70007
+ const outputPath = join50(projectRoot, STRUCTURE_PATH4);
70008
+ await mkdir18(dirname22(outputPath), { recursive: true });
70009
+ await writeFile12(outputPath, import_yaml30.default.stringify(structure), "utf8");
70010
+ await Promise.all(compactFiles.map((file) => writeFile12(file.absPath, file.content, "utf8")));
69954
70011
  return { inputHash, articles: structure.articles.length, structure: STRUCTURE_PATH4 };
69955
70012
  }
69956
70013
  function referencesReceipt() {
@@ -69958,7 +70015,7 @@ function referencesReceipt() {
69958
70015
  }
69959
70016
  async function readProjectCloseStatus(projectRoot) {
69960
70017
  const approved = await approvedKnowledgeFiles(projectRoot);
69961
- const structurePath = join49(projectRoot, STRUCTURE_PATH4);
70018
+ const structurePath = join50(projectRoot, STRUCTURE_PATH4);
69962
70019
  if (approved.length === 0 && !existsSync14(structurePath))
69963
70020
  return { state: "missing", diagnostics: [] };
69964
70021
  const inputHash = await approvedKnowledgeInputHash(projectRoot);
@@ -70003,7 +70060,7 @@ async function closeProjectWorkspace(projectRoot) {
70003
70060
  const content3 = ensureApprovedKnowledgePresentation(file.content);
70004
70061
  return content3 === file.content ? [] : [{ ...file, content: content3 }];
70005
70062
  });
70006
- await Promise.all(descriptionRepairs.map((file) => writeFile11(file.absPath, file.content, "utf8")));
70063
+ await Promise.all(descriptionRepairs.map((file) => writeFile12(file.absPath, file.content, "utf8")));
70007
70064
  const { inputHash, structure, compactFiles } = await deriveApprovedStructure(projectRoot);
70008
70065
  const verify = await verifyProjectWorkspace(projectRoot, { approvedStructureOverride: structure });
70009
70066
  const verifyErrors = verify.issues.filter((issue) => issue.severity === "error").length;
@@ -70015,10 +70072,10 @@ async function closeProjectWorkspace(projectRoot) {
70015
70072
  next: "Fix context verify errors, then rerun context close --format json."
70016
70073
  });
70017
70074
  }
70018
- const outputPath = join49(projectRoot, STRUCTURE_PATH4);
70019
- await mkdir17(dirname21(outputPath), { recursive: true });
70020
- await writeFile11(outputPath, `${import_yaml30.default.stringify(structure)}`, "utf8");
70021
- await Promise.all(compactFiles.map((file) => writeFile11(file.absPath, file.content, "utf8")));
70075
+ const outputPath = join50(projectRoot, STRUCTURE_PATH4);
70076
+ await mkdir18(dirname22(outputPath), { recursive: true });
70077
+ await writeFile12(outputPath, `${import_yaml30.default.stringify(structure)}`, "utf8");
70078
+ await Promise.all(compactFiles.map((file) => writeFile12(file.absPath, file.content, "utf8")));
70022
70079
  const { readTaskRollback } = await Promise.resolve().then(() => (init_taskRollback(), exports_taskRollback));
70023
70080
  if (!production && !await readTaskRollback(projectRoot))
70024
70081
  await closeRevisionDelivery(projectRoot);
@@ -70092,53 +70149,7 @@ var init_close = __esm(() => {
70092
70149
  init_knowledgeAssetRepair();
70093
70150
  init_approvedKnowledgeMetadata();
70094
70151
  import_yaml30 = __toESM(require_dist(), 1);
70095
- STRUCTURE_PATH4 = join49(KNOWLEDGE_ROOT, "structure.yaml");
70096
- });
70097
-
70098
- // src/project/siteTheme.ts
70099
- import { mkdir as mkdir18, readFile as readFile42, writeFile as writeFile12 } from "node:fs/promises";
70100
- import { dirname as dirname22, join as join50 } from "node:path";
70101
- async function resolveSiteTheme(root, overrides, scaffold = false) {
70102
- const path2 = join50(root, SITE_THEME_FILE);
70103
- let file = {};
70104
- try {
70105
- file = siteThemeSchema.parse(JSON.parse(await readFile42(path2, "utf8")));
70106
- } catch (error) {
70107
- if (error.code !== "ENOENT") {
70108
- throw new ContextError(ExitCode.UserError, `Invalid ${SITE_THEME_FILE}: ${error instanceof Error ? error.message : String(error)}. Fix the theme or remove the optional file to use defaults.`, { reason_code: "invalid-site-theme" });
70109
- }
70110
- if (scaffold) {
70111
- await mkdir18(dirname22(path2), { recursive: true });
70112
- try {
70113
- await writeFile12(path2, JSON.stringify(DEFAULT_SITE_THEME, null, 2) + `
70114
- `, { flag: "wx" });
70115
- } catch (writeError) {
70116
- if (writeError.code !== "EEXIST")
70117
- throw writeError;
70118
- }
70119
- return resolveSiteTheme(root, overrides);
70120
- }
70121
- }
70122
- const inline2 = siteThemeSchema.parse(overrides ?? {});
70123
- return { light: { ...DEFAULT_SITE_THEME.light, ...file.light, ...inline2.light }, dark: { ...DEFAULT_SITE_THEME.dark, ...file.dark, ...inline2.dark } };
70124
- }
70125
- function siteThemeVariables(theme) {
70126
- const rules = (c) => Object.entries(c).map(([key, value]) => `--context-${key.replace(/[A-Z]/gu, (x) => "-" + x.toLowerCase())}:${value};`).join("") + `
70127
- --vp-c-brand-1:var(--context-brand);--vp-c-brand-2:var(--context-accent);--vp-c-brand-3:var(--context-brand);
70128
- --vp-c-brand-soft:color-mix(in srgb,var(--context-brand) 8%,transparent);
70129
- --vp-c-bg:var(--context-background);--vp-c-bg-alt:var(--context-surface);--vp-c-bg-soft:var(--context-surface);--vp-c-bg-elv:var(--context-background);
70130
- --vp-sidebar-bg-color:var(--context-surface);--vp-nav-bg-color:var(--context-background);--vp-local-search-bg:var(--context-background);
70131
- --vp-c-text-1:var(--context-text);--vp-c-text-2:var(--context-muted-text);--vp-c-text-3:var(--context-muted-text);--vp-c-divider:var(--context-border);--vp-c-border:var(--context-border);
70132
- --bg:var(--context-background);--side:var(--context-surface);--text:var(--context-text);--muted:var(--context-muted-text);--line:var(--context-border);--blue:var(--context-brand);`;
70133
- return `:root{${rules(theme.light)}}.dark{${rules(theme.dark)}}
70134
- .node.selected,blockquote{background:color-mix(in srgb,var(--context-brand) 8%,transparent)}blockquote{border-left-color:var(--context-accent)}
70135
- `;
70136
- }
70137
- var SITE_THEME_FILE = "src/site/theme.json";
70138
- var init_siteTheme2 = __esm(() => {
70139
- init_src2();
70140
- init_errors3();
70141
- init_exitCode();
70152
+ STRUCTURE_PATH4 = join50(KNOWLEDGE_ROOT, "structure.yaml");
70142
70153
  });
70143
70154
 
70144
70155
  // src/project/packageOutputPaths.ts
@@ -70227,6 +70238,50 @@ var init_packageSiteAddress = __esm(() => {
70227
70238
  init_writeLock();
70228
70239
  });
70229
70240
 
70241
+ // src/project/productionReviewCandidates.ts
70242
+ async function readProductionReviewCandidates(projectRoot) {
70243
+ return withProductionFeedback({ operation: "review" }, async () => {
70244
+ if ((await readMaintenance(projectRoot)).active)
70245
+ return;
70246
+ const stage = await readProductionStage(projectRoot);
70247
+ if (!stage)
70248
+ return;
70249
+ await assertProductionPlanRequirementsCurrent(projectRoot, stage);
70250
+ if (!stage.delivery && dispatchProductionStage(stage, productionCapabilitiesSchema.parse({})).state !== "ended") {
70251
+ throw new TypeError("Complete the current production stage before reviewing its candidates");
70252
+ }
70253
+ const result = await readAcceptedProductionCandidates(projectRoot);
70254
+ return result && { ...result, candidates: result.candidates.map((candidate) => ({ ...candidate, status: "draft" })) };
70255
+ });
70256
+ }
70257
+ async function readAcceptedProductionCandidates(projectRoot) {
70258
+ const stage = await readProductionStage(projectRoot);
70259
+ if (!stage)
70260
+ return;
70261
+ await assertProductionPlanRequirementsCurrent(projectRoot, stage);
70262
+ const candidates = await readCandidateRecords(projectRoot);
70263
+ for (const candidate of candidates) {
70264
+ const task = stage.tasks.find((task2) => task2.status === "accepted" && task2.accepted?.receipt === candidate.candidate_id);
70265
+ if (!task || task.article_id !== candidate.article_id || task.path !== candidate.path || candidate.approved_revision?.request_digest !== task.input) {
70266
+ throw new TypeError(`Candidate does not belong to an accepted current production task: ${candidate.candidate_id}`);
70267
+ }
70268
+ const fingerprint = indexerProtocolDigest({ input: task.input, markdown: candidate.body, sections: candidate.indexer_candidate.sections });
70269
+ if (candidate.fingerprint !== fingerprint || candidate.candidate_id !== indexerCandidateId(fingerprint) || candidate.indexer_candidate.file_digest !== fingerprint || candidate.indexer_candidate.compile_digest !== task.input) {
70270
+ throw new TypeError(`Accepted candidate content changed before Review: ${candidate.candidate_id}`);
70271
+ }
70272
+ }
70273
+ return { revision: stage.id, candidates };
70274
+ }
70275
+ var init_productionReviewCandidates = __esm(() => {
70276
+ init_src2();
70277
+ init_productionStageStore();
70278
+ init_productionStage();
70279
+ init_candidateLedger();
70280
+ init_productionPlanning();
70281
+ init_maintenanceStorage();
70282
+ init_productionFeedback();
70283
+ });
70284
+
70230
70285
  // src/project/packageBuildReceipt.ts
70231
70286
  import { createHash as createHash13 } from "node:crypto";
70232
70287
  import { existsSync as existsSync15 } from "node:fs";
@@ -70484,7 +70539,13 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
70484
70539
  const previewText = await optionalText(projectRoot, ".tmp/context-runtime/indexer/structure-review/preview.json");
70485
70540
  const preview = previewText === undefined ? undefined : JSON.parse(previewText);
70486
70541
  const planned = preview?.topics?.flatMap((topic) => topic.article_targets ?? []) ?? [];
70487
- assertKnowledgeMapCoverage(next, approved, { known: [...approved, ...planned], current_revision: current?.revision ?? null });
70542
+ const production = await readAcceptedProductionCandidates(projectRoot);
70543
+ const accepted = production?.candidates.filter((candidate) => candidate.status === "draft").map((candidate) => ({
70544
+ artifact_ref: candidate.article_id,
70545
+ title: candidate.review.title,
70546
+ section_keys: candidate.indexer_candidate.sections.map((section) => section.section_key)
70547
+ })) ?? [];
70548
+ assertKnowledgeMapCoverage(next, approved, { known: [...approved, ...planned, ...accepted], current_revision: current?.revision ?? null });
70488
70549
  const content3 = import_yaml31.stringify(next);
70489
70550
  const previous2 = await optionalText(projectRoot, KNOWLEDGE_MAP_PATH);
70490
70551
  await runDurableMultiFileTransaction({
@@ -70508,6 +70569,7 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
70508
70569
  }
70509
70570
  var import_yaml31, KNOWLEDGE_MAP_PATH = "src/knowledge-map.yaml";
70510
70571
  var init_knowledgeMap2 = __esm(() => {
70572
+ init_productionReviewCandidates();
70511
70573
  init_knowledgeMapCoverage();
70512
70574
  init_src2();
70513
70575
  init_durableSingleFileTransaction();
@@ -70768,6 +70830,33 @@ function siteArticleSources(article, registry2) {
70768
70830
  }
70769
70831
  var encodedPath = (value) => value.split("/").map(encodeURIComponent).join("/");
70770
70832
 
70833
+ // src/project/readerContentStyles.ts
70834
+ function readerContentStyles(selector) {
70835
+ return String.raw`
70836
+ .vp-doc { font-size: 16px; line-height: 1.8; color: var(--vp-c-text-1); }
70837
+ .vp-doc hr { margin: 28px 0; border: 0; border-top: 1px solid var(--vp-c-divider); height: 0; }
70838
+ .vp-doc p, .vp-doc li { line-height: 1.8; }
70839
+ .vp-doc h1 { font-size: 36px; font-weight: 700; line-height: 1.3; letter-spacing: -.025em; margin-bottom: 28px; }
70840
+ .vp-doc h2 { font-size: 25px; font-weight: 650; line-height: 1.4; margin: 46px 0 22px; padding: 0 0 14px; border-top: 0; border-bottom: 1px solid var(--vp-c-divider); }
70841
+ .vp-doc h3 { font-size: 19px; font-weight: 600; line-height: 1.5; margin: 30px 0 14px; }
70842
+ .vp-doc a { color: inherit; font-weight: 500; text-decoration: none; border-bottom: 1px solid transparent; transition: color .15s, border-color .15s; }
70843
+ .vp-doc a:hover { color: var(--vp-c-brand-1); border-bottom-color: currentColor; }
70844
+ .vp-doc a.header-anchor { top: -0.06em !important; line-height: inherit; border: 0; color: var(--vp-c-brand-1); }
70845
+ .vp-doc blockquote { margin: 24px 0; padding: 16px 20px; border-left: 3px solid var(--context-accent); border-radius: 0 5px 5px 0; background: var(--vp-c-brand-soft); color: var(--vp-c-text-2); }
70846
+ .vp-doc blockquote p { margin: 0; font-size: 15px; }
70847
+ .vp-doc blockquote a { color: var(--vp-c-brand-1); }
70848
+ .vp-doc table { width: 100%; overflow-x: auto; font-size: 14px; border-collapse: collapse; margin: 24px 0; }
70849
+ .vp-doc th { background: var(--vp-sidebar-bg-color); font-weight: 600; }
70850
+ .vp-doc th, .vp-doc td { padding: 11px 14px; border-color: var(--vp-c-divider); line-height: 1.7; }
70851
+ .vp-doc tr:nth-child(2n) { background: var(--vp-c-bg); }
70852
+ .vp-doc :not(pre) > code { font-size: .88em; color: var(--vp-c-text-1); background: var(--vp-sidebar-bg-color); border: 1px solid var(--vp-c-divider); border-radius: 4px; }
70853
+ .vp-doc div[class*='language-'] { border: 1px solid var(--vp-c-divider); border-radius: 6px; }
70854
+ .vp-doc details { margin: 20px 0; border: 1px solid var(--vp-c-divider); border-radius: 6px; padding: 12px 16px; }
70855
+ .vp-doc summary { cursor: pointer; font-size: 14px; font-weight: 550; }
70856
+ .vp-doc img { max-width: 100%; height: auto; }
70857
+ `.replaceAll(".vp-doc", selector);
70858
+ }
70859
+
70771
70860
  // src/project/diagramViewer.ts
70772
70861
  function createDiagramViewer(load) {
70773
70862
  const states = new Map;
@@ -71524,26 +71613,7 @@ export default {
71524
71613
  .VPDocAsideOutline .content { padding: 0 0 0 16px; }
71525
71614
  .VPDocAsideOutline .outline-title { font-size: 11px; font-weight: 600; letter-spacing: .03em; color: var(--vp-c-text-2); }
71526
71615
  .VPDocAsideOutline .outline-link { font-size: 12px !important; line-height: 20px !important; padding: 5px 0; white-space: normal; }
71527
- .vp-doc { font-size: 16px; line-height: 1.8; color: var(--vp-c-text-1); }
71528
- .vp-doc p, .vp-doc li { line-height: 1.8; }
71529
- .vp-doc h1 { font-size: 36px; font-weight: 700; line-height: 1.3; letter-spacing: -.025em; margin-bottom: 28px; }
71530
- .vp-doc h2 { font-size: 25px; font-weight: 650; line-height: 1.4; margin: 46px 0 22px; padding: 0 0 14px; border-top: 0; border-bottom: 1px solid var(--vp-c-divider); }
71531
- .vp-doc h3 { font-size: 19px; font-weight: 600; line-height: 1.5; margin: 30px 0 14px; }
71532
- .vp-doc a { color: inherit; font-weight: 500; text-decoration: none; border-bottom: 1px solid transparent; transition: color .15s, border-color .15s; }
71533
- .vp-doc a:hover { color: var(--vp-c-brand-1); border-bottom-color: currentColor; }
71534
- .vp-doc a.header-anchor { top: -0.06em !important; line-height: inherit; border: 0; color: var(--vp-c-brand-1); }
71535
- .vp-doc blockquote { margin: 24px 0; padding: 16px 20px; border-left: 3px solid var(--context-accent); border-radius: 0 5px 5px 0; background: var(--vp-c-brand-soft); color: var(--vp-c-text-2); }
71536
- .vp-doc blockquote p { margin: 0; font-size: 15px; }
71537
- .vp-doc blockquote a { color: var(--vp-c-brand-1); }
71538
- .vp-doc table { width: 100%; overflow-x: auto; font-size: 14px; border-collapse: collapse; margin: 24px 0; }
71539
- .vp-doc th { background: var(--vp-sidebar-bg-color); font-weight: 600; }
71540
- .vp-doc th, .vp-doc td { padding: 11px 14px; border-color: var(--vp-c-divider); line-height: 1.7; }
71541
- .vp-doc tr:nth-child(2n) { background: var(--vp-c-bg); }
71542
- .vp-doc :not(pre) > code { font-size: .88em; color: var(--vp-c-text-1); background: var(--vp-sidebar-bg-color); border: 1px solid var(--vp-c-divider); border-radius: 4px; }
71543
- .vp-doc div[class*='language-'] { border: 1px solid var(--vp-c-divider); border-radius: 6px; }
71544
- .vp-doc details { margin: 20px 0; border: 1px solid var(--vp-c-divider); border-radius: 6px; padding: 12px 16px; }
71545
- .vp-doc summary { cursor: pointer; font-size: 14px; font-weight: 550; }
71546
- .vp-doc img { max-width: 100%; height: auto; }
71616
+ ${readerContentStyles(".vp-doc")}
71547
71617
  .context-home { max-width: 100%; min-width: 0; overflow-x: clip; }
71548
71618
  .context-home .VPContent, .context-home .VPHome, .context-home .VPHero { max-width: 100%; min-width: 0; }
71549
71619
  .context-home .VPHome { padding-bottom: 0; }
@@ -73530,7 +73600,7 @@ async function packageInputFingerprint(input) {
73530
73600
  ...input.pkg.assets === undefined ? {} : { definition: input.pkg.assets }
73531
73601
  }) : null;
73532
73602
  const siteRegistry = await loadSourcesRegistry({ rootDir: input.projectRoot });
73533
- const siteTheme = input.pkg.kind === "package.kb" && input.pkg.site ? await resolveSiteTheme(input.projectRoot, input.pkg.site.theme, true) : null;
73603
+ const siteTheme = input.pkg.kind === "package.kb" && input.pkg.site ? await resolveSiteTheme(input.projectRoot, input.pkg.site.theme) : null;
73534
73604
  return stableHash2({
73535
73605
  siteExtensions: input.pkg.kind === "package.kb" && input.pkg.site ? (await readSiteExtensions(input.projectRoot, input.pkg.site.extensions)).digest : null,
73536
73606
  siteTheme,
@@ -83050,7 +83120,7 @@ async function productionWorkflowRoute(input) {
83050
83120
  revision,
83051
83121
  reason_code: resolved.reasonCode,
83052
83122
  availability: resolved.availability,
83053
- summary: report ? `Present the report and wait. After approval, write {stage: ${stage.id}, decision: approved} to ${path2}.` : writing ? "Read the issued task directories. Coordinate them sequentially unless this caller supports independent Agents; only the coordinator submits shared state." : repair ? "Add revision tasks for rejected articles using the Review feedback; accepted production responsibilities remain unchanged." : investigate ? `Review pending configured scopes: ${stage.pending_scopes.filter((scope2) => !stage.gaps.some((gap2) => gap2.scope === scope2)).join(", ")}. Check their relevance to the current request and existing approved content before assigning investigation. Submit supported article tasks and remaining pending_scopes; do not infer missing articles from this list or repeat accepted work.` : resolved.node === "resolve-production-gap" ? `Source availability gaps: ${stage.gaps.map((gap2) => `${gap2.scope}: ${gap2.reason}`).join("; ")}. These failures do not establish missing knowledge or a new investigation assignment. Identify which sources the current task actually depends on; report unrelated configured-source failures separately. Preserve the configuration and follow the current resolution action.` : "Prepare the current stage's eligible task directories.",
83123
+ summary: report ? `Present the report and wait. After approval, write {stage: ${stage.id}, decision: approved} to ${path2}.` : writing ? "Read the issued task directories. Coordinate them sequentially unless this caller supports independent Agents; only the coordinator submits shared state." : repair ? "Add revision tasks for rejected articles using the Review feedback; accepted production responsibilities remain unchanged." : investigate ? `Review pending configured scopes: ${stage.pending_scopes.filter((scope2) => !stage.gaps.some((gap2) => gap2.scope === scope2)).join(", ")}. Check their relevance to the current request and existing approved content before assigning investigation. Submit supported article tasks and remaining pending_scopes; do not infer missing articles from this list or repeat accepted work. If the requested articles are already accepted, context run --deliver --format json enters their Review while retaining unrelated pending scopes.` : resolved.node === "resolve-production-gap" ? `Source availability gaps: ${stage.gaps.map((gap2) => `${gap2.scope}: ${gap2.reason}`).join("; ")}. These failures do not establish missing knowledge or a new investigation assignment. Identify which sources the current task actually depends on; report unrelated configured-source failures separately. Preserve the configuration. To review completed articles independently, use context run --deliver --format json; this retains pending scopes and does not approve or publish content. If these sources are required, use context source recovery-plan --format json and context source restore with explicit local or clone decisions before preparation.` : "Prepare the current stage's eligible task directories.",
83054
83124
  commands: report || prepare || writing || repair || investigate || gap ? [{
83055
83125
  command: command2,
83056
83126
  effect: "write",
@@ -104639,18 +104709,18 @@ function reviewBodyDiff(previous3, next) {
104639
104709
  remaining.splice(exact, 1);
104640
104710
  if (/^<h[1-6]>/u.test(block)) {
104641
104711
  omitted = false;
104642
- return block;
104712
+ return block.replace(/^(<h[1-6])>/u, '$1 class="review-unchanged-heading">');
104643
104713
  }
104644
104714
  if (omitted)
104645
104715
  return "";
104646
104716
  omitted = true;
104647
- return '<div class="unchanged" data-label="unchanged">Unchanged content omitted.</div>';
104717
+ return '<div class="review-omitted" data-label="unchanged">Unchanged content omitted.</div>';
104648
104718
  }
104649
104719
  omitted = false;
104650
104720
  return `<section class="changed"><span class="badge modify">Modify</span>${block}</section>`;
104651
104721
  });
104652
104722
  if (remaining.length)
104653
- result.push(`<section class="changed"><span class="badge modify">Modify</span><details open><summary data-label="removed">Previous or removed content</summary>${remaining.join(`
104723
+ result.push(`<section class="changed removed"><span class="badge removed">Remove</span><details open><summary data-label="removed">Previous or removed content</summary>${remaining.join(`
104654
104724
  `)}</details></section>`);
104655
104725
  return result.join(`
104656
104726
  `);
@@ -104828,29 +104898,29 @@ ${lines.join(`
104828
104898
  var REVIEW_SITE_CLIENT = String.raw`
104829
104899
  const $=id=>document.getElementById(id);
104830
104900
  let language=(navigator.languages?.[0]||navigator.language||'en').startsWith('zh')?'zh':'en';
104831
- const words={newRoots:['新增一级目录','New top-level categories'],ackRoots:['我已知晓本次新增一级目录','I acknowledge the new top-level categories'],home:['待审核内容','Pages to review'],unchanged:['本次未变更内容略。','Unchanged content omitted.'],previous:['查看旧文本','Previous text'],removed:['删除的内容','Removed content'],unplaced:['待落位文章','Unplaced articles'],approve:['批准这篇','Approve page'],reject:['拒绝这篇','Reject page'],revise:['修订','Revise'],approved:['已批准','Approved'],rejected:['已拒绝','Rejected'],revised:['已修订','Revision requested'],cancel:['取消','Cancel'],copy:['复制审核码','Copy review code'],allApprove:['全部批准','Approve all'],allReject:['全部拒绝','Reject all'],note:['输入修订意见','Enter revision instructions'],guide:['逐篇阅读并批准或拒绝后,复制审核码回复给 Agent。需要修改的文章请填写修订意见。','Read each page, approve or reject, then copy the review code back to your Agent. Enter instructions for pages needing revision.'],known:['知道了','Got it'],close:['关闭','Close'],notReviewed:['尚未完成审核','Not yet reviewed'],confirmAll:['建议逐篇阅读并确认。除非已读完所有待审核文章,否则请勿一次性全部批准。已有拒绝和修订意见将保留。','Read and confirm each page. Approve all only after reading every pending page. Existing rejections and revisions are preserved.'],confirm:['已阅读,全部批准','Read all, approve'],copied:['审核码已复制','Review code copied'],failed:['复制失败,请手动复制下方完整内容','Copy failed. Copy the complete text below manually.'],instructions:['请回到和 Agent 的会话窗口粘贴已复制内容进行回复即可继续~','Return to your conversation with the Agent and reply with the copied content to continue.'],long:['超过 1000 字符,飞书表单可能不接受。飞书场景下建议 @Bot 后粘贴回复。','Over 1,000 characters: a Feishu form may reject it. Mention @Bot and paste it in a reply instead.'],files:['预期工作区变化','Expected workspace changes'],navigate:['目录与文章','Directories and articles'],pendingNew:['未审批的新增文章','Pending new pages'],pendingModify:['未审批的修改文章','Pending modified pages'],processed:['已经审核和修订的文章','Reviewed or revision requested'],noSelection:['请先选择审核结果或填写修订意见','Select a decision or enter revision instructions first'],baseline:['无 Git 导航基线,目录沿用当前工作区;未推断历史目录变化。','No Git navigation baseline. Current navigation is shown without inferred historic changes.'],placement:['待落位文章不是新的站点栏目;请先按既有分类完成导航规划。','Unplaced articles are not a new site category. Finish their placement in the existing navigation first.']};
104901
+ const words={newRoots:['新增一级目录','New top-level categories'],ackRoots:['我已知晓本次新增一级目录','I acknowledge the new top-level categories'],home:['待审核内容','Pages to review'],unchanged:['本次未变更内容略。','Unchanged content omitted.'],previous:['查看旧文本','Previous text'],removed:['移除或替换的旧内容','Removed or replaced content'],removedNav:['移除的目录条目','Removed navigation entries'],unplaced:['待落位文章','Unplaced articles'],approve:['批准这篇','Approve page'],reject:['拒绝这篇','Reject page'],revise:['修订','Revise'],approved:['已批准','Approved'],rejected:['已拒绝','Rejected'],revised:['已修订','Revision requested'],cancel:['取消','Cancel'],copy:['复制审核码','Copy review code'],allApprove:['全部批准','Approve all'],allReject:['全部拒绝','Reject all'],note:['输入修订意见','Enter revision instructions'],guide:['逐篇阅读并批准或拒绝后,复制审核码回复给 Agent。需要修改的文章请填写修订意见。','Read each page, approve or reject, then copy the review code back to your Agent. Enter instructions for pages needing revision.'],known:['知道了','Got it'],close:['关闭','Close'],notReviewed:['尚未完成审核','Not yet reviewed'],confirmAll:['建议逐篇阅读并确认。除非已读完所有待审核文章,否则请勿一次性全部批准。已有拒绝和修订意见将保留。','Read and confirm each page. Approve all only after reading every pending page. Existing rejections and revisions are preserved.'],confirm:['已阅读,全部批准','Read all, approve'],copied:['审核码已复制','Review code copied'],failed:['复制失败,请手动复制下方完整内容','Copy failed. Copy the complete text below manually.'],instructions:['请回到和 Agent 的会话窗口粘贴已复制内容进行回复即可继续~','Return to your conversation with the Agent and reply with the copied content to continue.'],long:['超过 1000 字符,飞书表单可能不接受。飞书场景下建议 @Bot 后粘贴回复。','Over 1,000 characters: a Feishu form may reject it. Mention @Bot and paste it in a reply instead.'],files:['预期工作区变化','Expected workspace changes'],navigate:['目录与文章','Directories and articles'],pendingNew:['未审批的新增文章','Pending new pages'],pendingModify:['未审批的修改文章','Pending modified pages'],processed:['已经审核和修订的文章','Reviewed or revision requested'],noSelection:['请先选择审核结果或填写修订意见','Select a decision or enter revision instructions first'],baseline:['无 Git 导航基线,目录沿用当前工作区;未推断历史目录变化。','No Git navigation baseline. Current navigation is shown without inferred historic changes.'],placement:['待落位文章不是新的站点栏目;请先按既有分类完成导航规划。','Unplaced articles are not a new site category. Finish their placement in the existing navigation first.']};
104832
104902
  const t=k=>words[k]?.[language==='zh'?0:1]||k;
104833
104903
  const escape=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
104834
104904
  const decisions=new Map(),notes=new Map(),expanded=new Set();let selected=null,active=null;
104835
104905
  const candidates=DATA.pages.filter(p=>p.candidate_id),ordered=[...candidates].sort((a,b)=>a.candidate_id<b.candidate_id?-1:1);
104836
104906
  for(const p of candidates)if(p.revisionInstruction){decisions.set(p.candidate_id,'revised');notes.set(p.candidate_id,p.revisionInstruction)}
104837
- const badge=change=>change==='unchanged'?'':'<span class="badge '+change+'">'+(change==='new'?'New':change==='modify'?'Modify':t(change))+'</span>';
104907
+ const badge=change=>change==='unchanged'?'':'<span class="badge '+change+'">'+(change==='new'?'New':change==='modify'?'Modify':change==='removed'?'Remove':t(change))+'</span>';
104838
104908
  const state=p=>decisions.get(p.candidate_id)||'pending';
104839
104909
  function descendants(key,seen=new Set()){if(seen.has(key))return[];seen.add(key);return DATA.nodes.filter(n=>n.parent===key).flatMap(n=>[n,...descendants(n.key,seen)])}
104840
- function nodeChange(n){const changes=[n.change,...[n,...descendants(n.key)].flatMap(v=>{const p=DATA.pages.find(p=>p.id===v.page);return p?[p.change]:[]}),...descendants(n.key).map(v=>v.change)];return changes.includes('modify')?'modify':changes.includes('new')?'new':'unchanged'}
104910
+ function nodeChange(n){if(n.removed)return 'removed';const changes=[n.change,...[n,...descendants(n.key)].flatMap(v=>{const p=DATA.pages.find(p=>p.id===v.page);return p?[p.change]:[]}),...descendants(n.key).map(v=>v.change)];return descendants(n.key).some(v=>v.removed)||changes.includes('modify')?'modify':changes.includes('new')?'new':'unchanged'}
104841
104911
  function nodeTitle(n){return n.key==='review-unplaced'?t('unplaced'):n.title}
104842
104912
  function nodeLabel(n){return (n.removed?'<del>':'')+escape(nodeTitle(n))+(n.removed?'</del>':'')+(n.oldTitle?'<small class="old-title"> ← '+escape(n.oldTitle)+'</small>':'')}
104843
104913
  function totals(){const result={new:0,modify:0,approved:0,rejected:0,revised:0,pending:0};for(const p of candidates){const s=state(p);result[s]++;if(s==='pending')result[p.change==='new'?'new':'modify']++}return result}
104844
104914
  function updateCounts(){const c=totals();$('counts').textContent=c.new+' New / '+c.modify+' Modify / '+(c.approved+c.rejected+c.revised)+' Confirm';$('counter-pop').innerHTML='<div class="counter-grid"><div><b>'+c.new+'</b>'+t('pendingNew')+'</div><div><b>'+c.modify+'</b>'+t('pendingModify')+'</div></div><p>'+t('processed')+': '+(c.approved+c.rejected+c.revised)+'</p><small>'+t('approved')+' '+c.approved+' · '+t('rejected')+' '+c.rejected+' · '+t('revised')+' '+c.revised+'</small>'}
104845
- function button(n,depth){const change=nodeChange(n),page=DATA.pages.find(p=>p.id===n.page);return '<button data-node="'+escape(n.key)+'" class="node '+change+(selected===n.page?' selected':'')+'" style="padding-left:'+(16+14*depth)+'px">'+nodeLabel(n)+badge(change)+(page&&page.candidate_id&&state(page)!=='pending'?badge(state(page)):'')+(DATA.nodes.some(c=>c.parent===n.key)?'<span class="caret">›</span>':'')+'</button>'}
104915
+ function button(n,depth){const change=nodeChange(n),page=DATA.pages.find(p=>p.id===n.page);return '<button data-node="'+escape(n.key)+'" class="node '+(DATA.nodes.some(c=>c.parent===n.key)?'directory ':'')+change+(selected===n.page?' selected':'')+'" style="padding-left:'+(26+14*depth)+'px">'+nodeLabel(n)+badge(change)+(page&&page.candidate_id&&state(page)!=='pending'?badge(state(page)):'')+(DATA.nodes.some(c=>c.parent===n.key)?'<span class="caret">›</span>':'')+'</button>'}
104846
104916
  function renderNav(){const roots=DATA.nodes.filter(n=>!n.parent).sort((a,b)=>a.order-b.order);$('top').innerHTML=roots.map(n=>'<button data-root="'+escape(n.key)+'" class="'+nodeChange(n)+(active===n.key?' active':'')+'">'+nodeLabel(n)+badge(nodeChange(n))+'</button>').join('');let html='';function walk(key,depth,seen=new Set()){if(seen.has(key))return;seen.add(key);for(const n of DATA.nodes.filter(n=>n.parent===key).sort((a,b)=>a.order-b.order)){html+=button(n,depth);if(expanded.has(n.key)||n.page===selected||descendants(n.key).some(d=>d.page===selected))walk(n.key,depth+1,seen)}}if(active)walk(active,0);else html=roots.map(n=>button(n,0)).join('');$('tree').innerHTML=html}
104847
104917
  function rootFor(page){let node=DATA.nodes.find(n=>n.page===page);const seen=new Set();while(node?.parent&&!seen.has(node.key)){seen.add(node.key);node=DATA.nodes.find(n=>n.key===node.parent)}return node?.key||null}
104848
104918
  function showPage(id){selected=id;active=rootFor(id)||active;render()}
104849
104919
  function localizeBody(){document.querySelectorAll('[data-label]').forEach(el=>{el.textContent=t(el.dataset.label)})}
104850
104920
  function workspaceTree(){const tree={};for(const p of candidates){let node=tree;for(const part of ('knowledge/'+p.path).split('/'))node=node[part]??=( {} );node.$page=p}function lines(node,level=0){return Object.entries(node).filter(([k])=>k!=='$page').sort(([a],[b])=>a.localeCompare(b)).map(([k,v])=>'<div style="padding-left:'+level*18+'px">'+(v.$page?'<button data-page="'+escape(v.$page.id)+'">'+escape(k)+'</button>'+badge(v.$page.change)+(state(v.$page)!=='pending'?badge(state(v.$page)):''):escape(k)+'/')+'</div>'+lines(v,level+1)).join('')}return '<div class="workspace-tree">'+lines(tree)+'</div>'}
104851
- function renderHome(){const c=totals();$('article').innerHTML='<h1>'+t('home')+'</h1><p class="stats">'+candidates.length+' '+(language==='zh'?'篇候选正文':'candidate pages')+' · '+c.approved+' '+t('approved')+' '+badge('new')+' '+badge('modify')+'</p>'+(DATA.navigationBaseline==='current'?'<p class="note">'+t('baseline')+'</p>':'')+(DATA.nodes.some(n=>n.key==='review-unplaced')?'<p class="note">'+t('placement')+'</p>':'')+'<h2>'+t('navigate')+'</h2>'+DATA.nodes.filter(n=>!n.parent).map(n=>{const ids=new Set([n,...descendants(n.key)].map(x=>x.page));const pages=candidates.filter(p=>ids.has(p.id));return pages.length?'<section class="home-group"><h3>'+nodeLabel(n)+badge(nodeChange(n))+'</h3><div class="cards">'+pages.map(p=>'<button data-page="'+escape(p.id)+'">'+escape(p.title)+badge(p.change)+(state(p)!=='pending'?badge(state(p)):'')+'</button>').join('')+'</div></section>':''}).join('')+'<h2>'+t('files')+'</h2>'+workspaceTree()}
104921
+ function renderHome(){const c=totals();$('article').innerHTML='<h1>'+t('home')+'</h1><p class="stats">'+candidates.length+' '+(language==='zh'?'篇候选正文':'candidate pages')+' · '+c.approved+' '+t('approved')+' '+badge('new')+' '+badge('modify')+' '+badge('removed')+'</p>'+(DATA.navigationBaseline==='current'?'<p class="note">'+t('baseline')+'</p>':'')+(DATA.nodes.some(n=>n.key==='review-unplaced')?'<p class="note">'+t('placement')+'</p>':'')+'<h2>'+t('navigate')+'</h2>'+DATA.nodes.filter(n=>!n.parent).map(n=>{const ids=new Set([n,...descendants(n.key)].map(x=>x.page));const pages=candidates.filter(p=>ids.has(p.id));return pages.length?'<section class="home-group"><h3>'+nodeLabel(n)+badge(nodeChange(n))+'</h3><div class="cards">'+pages.map(p=>'<button data-page="'+escape(p.id)+'">'+escape(p.title)+badge(p.change)+(state(p)!=='pending'?badge(state(p)):'')+'</button>').join('')+'</div></section>':''}).join('')+(DATA.nodes.some(n=>n.removed)?'<h2>'+t('removedNav')+'</h2><ul>'+DATA.nodes.filter(n=>n.removed).map(n=>'<li class="removed">'+nodeLabel(n)+badge('removed')+'</li>').join('')+'</ul>':'')+'<h2>'+t('files')+'</h2>'+workspaceTree()}
104852
104922
  function controls(){const p=DATA.pages.find(p=>p.id===selected),s=p?state(p):'pending';$('footer').hidden=!p?.candidate_id;if(!p?.candidate_id)return;$('revision-note').value=notes.get(p.candidate_id)||'';$('revision-note').placeholder=t('note');$('revision-note').disabled=s==='approved'||s==='rejected';for(const [id,v,label]of[['revise-btn','revised','revise'],['reject-btn','rejected','reject'],['approve-btn','approved','approve']]){const b=$(id);b.disabled=s!=='pending'&&s!==v;b.className='btn '+(s===v?'chosen':v==='approved'?'primary':'');b.innerHTML=s===v?'<span class="normal">'+t(v)+'</span><span class="hover-label">'+t('cancel')+'</span>':t(label);b.title=s===v?t('cancel'):''}}
104853
- function render(){document.body.classList.toggle('home',selected===null);renderNav();updateCounts();if(selected===null)renderHome();else{const p=DATA.pages.find(p=>p.id===selected);$('article').innerHTML=p?'<h1>'+escape(p.title)+badge(p.change)+(p.candidate_id&&state(p)!=='pending'?badge(state(p)):'')+'</h1>'+(p.previousPath?'<p class="note">'+escape(p.previousPath)+' → '+escape(p.path)+'</p>':'')+(p.candidate_id?p.html:'<div class="unchanged">'+t('unchanged')+'</div>')+(p.sources.length?'<details><summary>'+(language==='zh'?'来源引用':'Sources')+'</summary><ul>'+p.sources.map(s=>'<li>'+escape(s)+'</li>').join('')+'</ul></details>':''):''}controls();localizeBody();globalThis.contextDiagramViewer?.render($('article'),{dark:document.body.classList.contains('dark'),language})}
104923
+ function render(){document.body.classList.toggle('home',selected===null);$('article').classList.toggle('review-new-page',DATA.pages.some(p=>p.id===selected&&p.change==='new'));renderNav();updateCounts();if(selected===null)renderHome();else{const p=DATA.pages.find(p=>p.id===selected);$('article').innerHTML=p?'<h1>'+escape(p.title)+badge(p.change)+(p.candidate_id&&state(p)!=='pending'?badge(state(p)):'')+'</h1>'+(p.previousPath?'<p class="note">'+escape(p.previousPath)+' → '+escape(p.path)+'</p>':'')+(p.candidate_id?p.html:'<div class="review-omitted">'+t('unchanged')+'</div>')+(p.sources.length?'<details><summary>'+(language==='zh'?'来源引用':'Sources')+'</summary><ul>'+p.sources.map(s=>'<li>'+escape(s)+'</li>').join('')+'</ul></details>':''):''}controls();localizeBody();globalThis.contextDiagramViewer?.render($('article'),{dark:document.body.classList.contains('dark'),language})}
104854
104924
  function setDecision(id,value){const current=decisions.get(id);if(current===value){decisions.delete(id);notes.delete(id)}else if(!current){if(value==='revised'){$('revision-note').focus();return}decisions.set(id,value)}render()}
104855
104925
  function setAllDecision(value){for(const p of candidates)if(!decisions.has(p.candidate_id))decisions.set(p.candidate_id,value);render()}
104856
104926
  function payloadText(){const statuses=ordered.map(p=>state(p));return feedbackCodec.encode({scope:SCOPE.label,idsHash:SCOPE.ids_sha256,contentHash:SCOPE.candidates_sha256,baselineHash:DATA.baselineHash,statuses,repairs:ordered.flatMap((p,index)=>state(p)==='revised'?[{index,instruction:notes.get(p.candidate_id)}]:[])})}
@@ -104874,8 +104944,29 @@ labels();render();const deadline=Date.now()+10000;guideTimer=setInterval(()=>{co
104874
104944
  // src/project/reviewSiteStyles.ts
104875
104945
  init_diagramStyles();
104876
104946
  var REVIEW_SITE_STYLES = String.raw`
104877
- :root{--blue:#2563eb;--text:#161e2e;--muted:#646b7c;--line:#e7e9ef;--bg:#fff;--side:#f8f9fc;--red:#c63848;--amber:#a4660a}*{box-sizing:border-box}body{margin:0;color:var(--text);background:var(--bg);font:14px/1.75 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC",sans-serif}button,input,textarea{font:inherit}button{cursor:pointer}button:disabled{opacity:.35;cursor:not-allowed}[hidden]{display:none!important}header{height:64px;padding:0 24px;display:flex;align-items:center;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--bg);z-index:5}#home{border:0;background:none;color:var(--text);width:280px;flex-shrink:0;text-align:left;font-size:15px;font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nav{display:flex;flex:1;min-width:0;overflow:auto;align-self:stretch}nav button{border:0;background:none;color:var(--text);padding:0 16px;font-size:13px;font-weight:550;white-space:nowrap}nav .active{box-shadow:inset 0 -2px var(--blue)}.new,nav .new{color:var(--red)}.modify,nav .modify{color:var(--amber)}.badge{display:inline-block;margin-left:7px;padding:1px 6px;font-size:10px;line-height:18px;vertical-align:middle;border-radius:4px;font-weight:600;letter-spacing:0}.badge.new{background:#fff0f1}.badge.modify,.badge.revised{background:#fff4dd;color:var(--amber)}.badge.approved{background:#e9f7ef;color:#258451}.badge.rejected{background:#f4edf0;color:#9e4458}.tools{display:flex;align-items:center;gap:8px;position:relative;margin-left:12px}.btn{border:1px solid var(--line);border-radius:6px;background:var(--bg);color:var(--text);padding:5px 10px;font-size:12px;line-height:22px;white-space:nowrap}.primary{color:white;background:var(--blue);border-color:var(--blue)}#theme,#language{margin-left:8px;flex-shrink:0}.counter{position:relative;padding:8px;white-space:nowrap;font-size:12px;font-weight:700;color:var(--blue)}.counter-pop{display:none;position:absolute;top:100%;right:0;min-width:320px;padding:15px;background:var(--bg);border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 30px #17244220;color:var(--text);font-weight:400}.counter:hover .counter-pop,.counter:focus .counter-pop{display:block}.counter-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;font-size:11px}.counter-grid b{display:block;font-size:20px}.counter-pop p{border-top:1px solid var(--line);padding-top:10px}.layout{display:grid;grid-template-columns:280px minmax(0,1fr)}aside{height:calc(100vh - 64px);position:sticky;top:64px;overflow:auto;background:var(--side);border-right:1px solid var(--line);padding:12px 0 80px}.node{display:block;width:100%;text-align:left;border:0;background:none;min-height:32px;padding:6px 16px;font-size:13px;font-weight:450;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--muted)}.node.new{color:var(--red)}.node.modify{color:var(--amber)}.node.selected{background:#2563eb14}.caret{float:right}.node:hover{background:#8e96aa1a}main{min-width:0;padding:44px 60px 100px 36px}h1{font-size:36px;line-height:1.3;letter-spacing:-.025em;margin:0 0 28px}h2{font-size:25px;line-height:1.4;font-weight:650;margin:46px 0 22px;border-bottom:1px solid var(--line);padding-bottom:14px}h3{font-size:19px;margin:30px 0 14px}article{font-size:16px;line-height:1.8}article>h1>.badge{margin-left:12px}article a{color:inherit}article a:hover{color:var(--blue)}article table{border-collapse:collapse;font-size:14px;display:block;overflow:auto}article th,article td{border:1px solid var(--line);padding:11px 14px}article th{background:var(--side)}pre{overflow:auto;background:var(--side);padding:16px}blockquote{padding:16px 20px;margin:24px 0;border-left:3px solid #00bec8;background:#2563eb14;color:var(--muted)}.home .layout{display:block}.home aside{display:none}.home main{width:1120px;max-width:calc(100% - 280px);margin-left:280px;padding-top:32px}.home article{font-size:14px}.home h1{font-size:28px;margin-bottom:12px}.home h2{font-size:19px;margin:24px 0 12px;padding-bottom:10px}.home h3{font-size:15px;margin:16px 0 10px}.stats{font-size:12px;color:var(--muted)}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));gap:8px}.cards button{border:1px solid var(--line);border-radius:7px;background:var(--bg);color:var(--text);text-align:left;font-size:13px;line-height:20px;padding:10px 14px}.cards button:hover{border-color:var(--blue)}.unchanged{border:1px dashed var(--line);border-radius:8px;padding:24px;text-align:center;color:var(--muted);font-size:13px}.changed{position:relative;border-left:3px solid #e8b051;background:#fffaf0;color:#8f5607;padding:24px 18px 12px;margin:20px 0}.changed>.badge{position:absolute;right:12px;top:6px}.changed details{color:var(--muted)}.workspace-tree{font:12px/1.9 ui-monospace,monospace;border:1px solid var(--line);border-radius:8px;padding:16px;background:var(--side);overflow:auto}.workspace-tree button{border:0;background:none;color:var(--text);padding:0;font:inherit;white-space:nowrap}.note{font-size:12px;color:var(--muted)}footer{position:fixed;bottom:0;left:280px;right:0;background:var(--bg);border-top:1px solid var(--line);padding:12px 35px;display:flex;gap:10px;z-index:4}footer input{flex:1;min-width:0;border:0;outline:0;background:transparent;color:var(--text);font-size:14px;padding:8px 0}footer .btn{min-width:76px}.chosen{color:var(--blue);border-color:var(--blue);background:var(--bg)}.hover-label{display:none}.chosen:hover .normal{display:none}.chosen:hover .hover-label{display:inline}dialog{width:560px;max-width:90vw;background:var(--bg);color:var(--text);border:1px solid var(--line);border-radius:10px;padding:20px;font-size:13px;line-height:1.65}dialog::backdrop{background:#131b3255}dialog h2{font-size:17px;margin:0 0 12px;border:0;padding:0}dialog textarea{width:100%;height:130px;border:1px solid var(--line);border-radius:6px;padding:10px;font:11px/1.6 monospace;background:var(--side);color:var(--text)}#copy-warning{color:var(--amber)}.bulk-ack{display:flex;align-items:center;gap:8px;font-size:13px}.bulk-ack input{accent-color:var(--blue)}#bulk-roots-list{margin:8px 0 12px;padding-left:22px;color:var(--red)}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}.guide{position:absolute;right:0;top:calc(100% + 18px);width:300px;background:var(--bg);border:1px solid var(--line);border-radius:10px;padding:15px;box-shadow:0 10px 35px #17244224;font-size:12px}.guide:before{content:'';position:absolute;top:-7px;right:42px;width:12px;height:12px;background:var(--bg);border-top:1px solid var(--line);border-left:1px solid var(--line);transform:rotate(45deg)}#guide-countdown{float:right;color:var(--muted);font-size:11px}.dark{--bg:#171b24;--side:#1b1d24;--text:#e2e4ed;--muted:#a1a6b7;--line:#303440;--blue:#8eb7ff}.dark .changed{background:#302919;color:#f2cf85}@media(min-width:1600px){main,.home main{padding-left:52px}}@media(max-width:1250px){#home{width:190px}nav button{padding:0 8px}.tools{gap:4px}}@media(max-width:1050px){header{height:auto;flex-wrap:wrap;min-height:64px}nav{order:3;flex-basis:100%;height:44px}.tools{margin-left:auto}}@media(max-width:700px){.layout{display:block}aside{position:relative;top:0;height:200px}main,.home main{width:100%;max-width:100%;margin:0;padding:24px 20px 90px}footer{left:0;padding:10px;flex-wrap:wrap}footer input{flex-basis:100%}.tools{flex-wrap:wrap}h1{font-size:28px}}
104947
+ :root{--blue:#2563eb;--text:#161e2e;--muted:#646b7c;--line:#e7e9ef;--bg:#fff;--side:#f8f9fc;--green:#28734f;--red:#b7444c;--amber:#93651d}*{box-sizing:border-box}body{margin:0;color:var(--text);background:var(--bg);font:14px/1.75 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif}button,input,textarea{font:inherit}button{cursor:pointer}button:disabled{opacity:.35;cursor:not-allowed}[hidden]{display:none!important}header{height:64px;padding:0 24px;display:flex;align-items:center;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--bg);z-index:5}#home{border:0;background:none;color:var(--text);width:280px;flex-shrink:0;text-align:left;font-size:15px;font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}nav{display:flex;flex:1;min-width:0;overflow:auto;align-self:stretch}nav button{border:0;background:none;color:var(--text);padding:0 16px;font-size:13px;font-weight:550;white-space:nowrap}nav .active{color:var(--blue);box-shadow:inset 0 -2px var(--blue)}.new,nav .new{color:var(--green)}.modify,nav .modify{color:var(--amber)}.badge{display:inline-block;margin-left:7px;padding:1px 6px;font-size:10px;line-height:18px;vertical-align:middle;border-radius:4px;font-weight:600;letter-spacing:0}.badge.new,.badge.approved{color:var(--green);background:color-mix(in srgb,var(--green) 10%,var(--bg))}.badge.modify,.badge.revised{color:var(--amber);background:color-mix(in srgb,var(--amber) 10%,var(--bg))}.badge.removed,.badge.rejected{color:var(--red);background:color-mix(in srgb,var(--red) 10%,var(--bg))}.removed,nav .removed,.node.removed{color:var(--red)}.badge{border:1px solid color-mix(in srgb,currentColor 18%,transparent)}.tools{display:flex;align-items:center;gap:8px;position:relative;margin-left:12px}.btn{border:1px solid var(--line);border-radius:6px;background:var(--bg);color:var(--text);padding:5px 10px;font-size:12px;line-height:22px;white-space:nowrap}.primary{color:var(--bg);background:var(--blue);border-color:var(--blue)}#theme,#language{margin-left:8px;flex-shrink:0}.counter{position:relative;padding:8px;white-space:nowrap;font-size:12px;font-weight:700;color:var(--blue)}.counter-pop{display:none;position:absolute;top:100%;right:0;min-width:320px;padding:15px;background:var(--bg);border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 30px #17244220;color:var(--text);font-weight:400}.counter:hover .counter-pop,.counter:focus .counter-pop{display:block}.counter-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;font-size:11px}.counter-grid b{display:block;font-size:20px}.counter-pop p{border-top:1px solid var(--line);padding-top:10px}.layout{display:grid;grid-template-columns:280px minmax(0,1fr)}aside{height:calc(100vh - 64px);position:sticky;top:64px;overflow:auto;background:var(--side);border-right:1px solid var(--line);padding:12px 0 80px}.node{display:block;width:100%;text-align:left;border:0;background:none;height:38px;min-height:38px;padding:9px 16px 9px 26px;font-size:13px;font-weight:450;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--muted)}.node.directory{color:var(--text)}.node.selected.unchanged{color:var(--blue);font-weight:550}.node.new{color:var(--green)}.node.modify{color:var(--amber)}.node.selected{background:color-mix(in srgb,var(--blue) 8%,transparent)}.caret{float:right}.node:hover{background:#8e96aa1a}main{min-width:0;padding:44px 60px 100px 36px}h1{font-size:36px;line-height:1.3;letter-spacing:-.025em;margin:0 0 28px}h2{font-size:25px;line-height:1.4;font-weight:650;margin:46px 0 22px;border-bottom:1px solid var(--line);padding-bottom:14px}h3{font-size:19px;font-weight:600;line-height:1.5;margin:30px 0 14px}article{font-size:16px;line-height:1.8}article>h1>.badge{margin-left:12px}article a{color:inherit}article a:hover{color:var(--blue)}article table{border-collapse:collapse;font-size:14px;display:block;overflow:auto}article th,article td{border:1px solid var(--line);padding:11px 14px}article th{background:var(--side)}pre{overflow:auto;background:var(--side);padding:16px}blockquote{padding:16px 20px;margin:24px 0;border-left:3px solid var(--context-accent);background:color-mix(in srgb,var(--blue) 8%,transparent);color:var(--muted)}.home .layout{display:block}.home aside{display:none}.home main{width:1120px;max-width:calc(100% - 280px);margin-left:280px;padding-top:32px}.home article{font-size:14px}.home h1{font-size:28px;margin-bottom:12px}.home h2{font-size:19px;margin:24px 0 12px;padding-bottom:10px}.home h3{font-size:15px;margin:16px 0 10px}.stats{font-size:12px;color:var(--muted)}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));gap:8px}.cards button{border:1px solid var(--line);border-radius:7px;background:var(--bg);color:var(--text);text-align:left;font-size:13px;line-height:20px;padding:10px 14px}.cards button:hover{border-color:var(--blue)}.review-unchanged-heading{color:var(--muted)}.review-omitted{margin:20px 0;padding:18px 20px;border:1px dashed var(--line);border-radius:8px;color:var(--muted);font-size:13px}.changed{position:relative;display:flow-root;color:var(--amber);padding:0 76px 0 0;margin:20px 0}.changed>.badge{position:absolute;right:0;top:4px}.changed>:nth-child(2){margin-top:0}.changed>:last-child{margin-bottom:0}.changed.removed>.badge{right:12px;top:6px}.changed details{color:inherit}.changed.removed{border-left:3px solid;padding:24px 18px 12px;border-left-color:color-mix(in srgb,var(--red) 55%,var(--line));background:color-mix(in srgb,var(--red) 6%,var(--bg));color:var(--red)}.workspace-tree{font:12px/1.9 ui-monospace,monospace;border:1px solid var(--line);border-radius:8px;padding:16px;background:var(--side);overflow:auto}.workspace-tree button{border:0;background:none;color:var(--text);padding:0;font:inherit;white-space:nowrap}.note{font-size:12px;color:var(--muted)}footer{position:fixed;bottom:0;left:280px;right:0;background:var(--bg);border-top:1px solid var(--line);padding:12px 35px;display:flex;gap:10px;z-index:4}footer input{flex:1;min-width:0;border:0;outline:0;background:transparent;color:var(--text);font-size:14px;padding:8px 0}footer .btn{min-width:76px}.chosen{color:var(--blue);border-color:var(--blue);background:var(--bg)}.hover-label{display:none}.chosen:hover .normal{display:none}.chosen:hover .hover-label{display:inline}dialog{width:560px;max-width:90vw;background:var(--bg);color:var(--text);border:1px solid var(--line);border-radius:10px;padding:20px;font-size:13px;line-height:1.65}dialog::backdrop{background:#131b3255}dialog h2{font-size:17px;margin:0 0 12px;border:0;padding:0}dialog textarea{width:100%;height:130px;border:1px solid var(--line);border-radius:6px;padding:10px;font:11px/1.6 monospace;background:var(--side);color:var(--text)}#copy-warning{color:var(--amber)}.bulk-ack{display:flex;align-items:center;gap:8px;font-size:13px}.bulk-ack input{accent-color:var(--blue)}#bulk-roots-list{margin:8px 0 12px;padding-left:22px;color:var(--red)}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}.guide{position:absolute;right:0;top:calc(100% + 18px);width:300px;background:var(--bg);border:1px solid var(--line);border-radius:10px;padding:15px;box-shadow:0 10px 35px #17244224;font-size:12px}.guide:before{content:'';position:absolute;top:-7px;right:42px;width:12px;height:12px;background:var(--bg);border-top:1px solid var(--line);border-left:1px solid var(--line);transform:rotate(45deg)}#guide-countdown{float:right;color:var(--muted);font-size:11px}.dark{--bg:#171b24;--side:#1b1d24;--text:#e2e4ed;--muted:#a1a6b7;--line:#303440;--blue:#8eb7ff;--green:#83c9a0;--amber:#dab779;--red:#e49a9e}@media(min-width:1600px){main,.home main{padding-left:52px}}@media(max-width:1279px){#home{width:220px}nav button{padding:0 9px}.tools{gap:4px}}@media(max-width:1050px){header{height:auto;flex-wrap:wrap;min-height:64px}nav{order:3;flex-basis:100%;height:44px}.tools{margin-left:auto}}@media(max-width:700px){.layout{display:block}aside{position:relative;top:0;height:200px}main,.home main{width:100%;max-width:100%;margin:0;padding:24px 20px 90px}footer{left:0;padding:10px;flex-wrap:wrap}footer input{flex-basis:100%}.tools{flex-wrap:wrap}h1{font-size:28px}}
104948
+ ${readerContentStyles("article")}
104949
+ article code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
104950
+ article :not(pre)>code{padding:3px 6px;overflow-wrap:break-word}
104951
+ article p{margin:16px 0}article strong{font-weight:600}
104952
+ article ul,article ol{padding-left:1.25rem;margin:16px 0}
104953
+ article li+li{margin-top:8px}article li>p{margin:0}
104954
+ article pre{border:1px solid var(--line);border-radius:6px;padding:20px 24px;line-height:1.7}
104955
+ article pre code{font-size:14px;color:var(--text)}
104956
+ article .review-unchanged-heading{color:var(--muted)}
104957
+ article .changed{color:var(--amber)}
104958
+ article .changed pre code,article .changed blockquote{color:inherit}
104959
+ article .changed.removed{color:var(--red)}
104960
+ article .changed :not(pre)>code{color:inherit;background:color-mix(in srgb,currentColor 5%,var(--bg))}
104961
+ .old-title{color:var(--muted);margin-left:6px}
104962
+ article.review-new-page{color:var(--green)}
104963
+ article.review-new-page :not(pre)>code,article.review-new-page pre code,article.review-new-page blockquote{color:inherit}
104964
+ article.review-new-page :not(pre)>code{background:color-mix(in srgb,var(--green) 6%,var(--bg))}
104878
104965
  ${DIAGRAM_STYLES}
104966
+ article.review-new-page .language-mermaid{--context-text:var(--green);--context-muted-text:var(--green)}
104967
+ article .changed .language-mermaid{--context-text:var(--amber);--context-muted-text:var(--amber)}
104968
+ article .changed.removed .language-mermaid{--context-text:var(--red);--context-muted-text:var(--red)}
104969
+ article.review-new-page .context-diagram-shell,article .changed .context-diagram-shell{--diagram-text:var(--context-text)}
104879
104970
  `;
104880
104971
 
104881
104972
  // src/project/reviewHtml.ts
@@ -106745,42 +106836,7 @@ import { join as join95 } from "node:path";
106745
106836
  init_src2();
106746
106837
  init_approvedRevision();
106747
106838
  init_approvedRevisionBatch();
106748
-
106749
- // src/project/productionReviewCandidates.ts
106750
- init_src2();
106751
- init_productionStageStore();
106752
- init_productionStage();
106753
- init_candidateLedger();
106754
- init_productionPlanning();
106755
- init_maintenanceStorage();
106756
- init_productionFeedback();
106757
- async function readProductionReviewCandidates(projectRoot) {
106758
- return withProductionFeedback({ operation: "review" }, async () => {
106759
- if ((await readMaintenance(projectRoot)).active)
106760
- return;
106761
- const stage = await readProductionStage(projectRoot);
106762
- if (!stage)
106763
- return;
106764
- await assertProductionPlanRequirementsCurrent(projectRoot, stage);
106765
- if (!stage.delivery && dispatchProductionStage(stage, productionCapabilitiesSchema.parse({})).state !== "ended") {
106766
- throw new TypeError("Complete the current production stage before reviewing its candidates");
106767
- }
106768
- const candidates = await readCandidateRecords(projectRoot);
106769
- for (const candidate of candidates) {
106770
- const task = stage.tasks.find((task2) => task2.status === "accepted" && task2.accepted?.receipt === candidate.candidate_id);
106771
- if (!task || task.article_id !== candidate.article_id || task.path !== candidate.path || candidate.approved_revision?.request_digest !== task.input) {
106772
- throw new TypeError(`Candidate does not belong to an accepted current production task: ${candidate.candidate_id}`);
106773
- }
106774
- const fingerprint = indexerProtocolDigest({ input: task.input, markdown: candidate.body, sections: candidate.indexer_candidate.sections });
106775
- if (candidate.fingerprint !== fingerprint || candidate.candidate_id !== indexerCandidateId(fingerprint) || candidate.indexer_candidate.file_digest !== fingerprint || candidate.indexer_candidate.compile_digest !== task.input) {
106776
- throw new TypeError(`Accepted candidate content changed before Review: ${candidate.candidate_id}`);
106777
- }
106778
- }
106779
- return { revision: stage.id, candidates: candidates.map((candidate) => ({ ...candidate, status: "draft" })) };
106780
- });
106781
- }
106782
-
106783
- // src/project/reviewCandidateAuthority.ts
106839
+ init_productionReviewCandidates();
106784
106840
  init_productionFeedback();
106785
106841
  async function loadReviewCandidateAuthority(projectRoot) {
106786
106842
  return withProductionFeedback({ operation: "review" }, async () => {