@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 +365 -309
- package/indexers/contracts/profile-contract.json +245 -245
- package/indexers/release-manifest.json +1 -1
- package/package.json +12 -12
- package/plugins/VERSION +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/.codex-plugin/plugin.json +2 -2
- package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
- package/providers/context/manifest.json +5 -5
- package/providers/context/provider.yaml +1 -1
- package/providers/context/resources/procedures/work-start-report.md +9 -0
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
|
|
65040
|
-
import { join as
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
65147
|
+
if (!(await lstat5(join27(root, path2))).isFile())
|
|
65094
65148
|
continue;
|
|
65095
|
-
bytes = await
|
|
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
|
|
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(
|
|
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
|
|
65231
|
-
import { join as
|
|
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(
|
|
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(
|
|
65257
|
-
result.push(...await entries(root,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
65381
|
-
import { join as
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
65837
|
-
import { dirname as
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
65984
|
+
const sourcePath = join31(input.projectRoot, input.sourceMaterializedAt, asset.path);
|
|
65928
65985
|
let bytes;
|
|
65929
65986
|
try {
|
|
65930
|
-
bytes = await
|
|
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:
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
66013
|
-
const assetRoot =
|
|
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
|
|
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,
|
|
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
|
|
66058
|
-
import { dirname as
|
|
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
|
|
66129
|
+
return join32("sources", sourceType, normalizeDocumentSourceName(sourceName), "manifest.json");
|
|
66073
66130
|
}
|
|
66074
66131
|
function runtimeEvidenceIndexRelativePath(sourceType, sourceName) {
|
|
66075
|
-
return
|
|
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
|
|
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 =
|
|
66154
|
+
const absolutePath = join32(input.projectRoot, input.materializedAt, input.path);
|
|
66098
66155
|
try {
|
|
66099
|
-
return await
|
|
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 ??
|
|
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 =
|
|
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
|
|
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 =
|
|
66324
|
+
const absoluteRuntimeIndexPath = join32(input.projectRoot, runtimeIndexPath);
|
|
66268
66325
|
if (input.writeRuntimeIndex ?? true) {
|
|
66269
|
-
await
|
|
66270
|
-
await
|
|
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
|
|
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
|
|
66418
|
+
return join33("sources", sourceType, sourceName);
|
|
66362
66419
|
}
|
|
66363
66420
|
function defaultDocumentManifest(materializedAt) {
|
|
66364
|
-
return
|
|
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
|
|
66390
|
-
import { dirname as
|
|
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
|
|
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
|
|
66554
|
-
await
|
|
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
|
|
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
|
|
66657
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
66912
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
67040
|
-
import { join as
|
|
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
|
|
67108
|
+
return join36(INDEXER_MAIN_RUN_STORE_ROOT, "requests", `${digestName(requestDigest)}.json`);
|
|
67052
67109
|
}
|
|
67053
67110
|
function acceptedCachePath(requestDigest) {
|
|
67054
|
-
return
|
|
67111
|
+
return join36(INDEXER_MAIN_RUN_STORE_ROOT, "accepted", `${digestName(requestDigest)}.json`);
|
|
67055
67112
|
}
|
|
67056
67113
|
function partitionConvergencePath(attemptDigest) {
|
|
67057
|
-
return
|
|
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
|
|
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: [
|
|
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 =
|
|
67242
|
-
INDEXER_MAIN_RUN_CURRENT_PATH =
|
|
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
|
|
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) =>
|
|
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
|
|
67324
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
67386
|
-
import { join as
|
|
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 =
|
|
67389
|
-
const pointer = await
|
|
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(
|
|
67457
|
+
await remove(join39(directory, entry));
|
|
67401
67458
|
const targets = [];
|
|
67402
|
-
for (const path2 of [
|
|
67403
|
-
const content4 = path2 === pointerPath ? pointer : await
|
|
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
|
|
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
|
|
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(
|
|
67516
|
+
await rm9(join40(projectRoot, path2), { recursive: true, force: true });
|
|
67460
67517
|
}
|
|
67461
|
-
const indexer =
|
|
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(
|
|
67526
|
+
await rm9(join40(indexer, name2), { recursive: true, force: true });
|
|
67470
67527
|
}
|
|
67471
|
-
const 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(
|
|
67536
|
+
await rm9(join40(compile, name2), { recursive: true, force: true });
|
|
67480
67537
|
}
|
|
67481
|
-
await rm9(
|
|
67538
|
+
await rm9(join40(compile, "current.json"), { force: true });
|
|
67482
67539
|
await rm9(indexer, { recursive: true, force: true });
|
|
67483
|
-
await rm9(
|
|
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
|
|
67657
|
-
import { join as
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
67720
|
-
import { join as
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
67788
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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 =
|
|
68180
|
+
let dir = dirname19(fileURLToPath3(import.meta.url));
|
|
68124
68181
|
for (let index2 = 0;index2 < 8; index2++) {
|
|
68125
|
-
const packagePath =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
68689
|
-
import { dirname as
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
68744
|
-
await
|
|
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: `${
|
|
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 =
|
|
68805
|
-
const marker = await readMarker(
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
69186
|
+
return join48(dirname21(packageJsonPath), rootExport);
|
|
69130
69187
|
}
|
|
69131
69188
|
if (isRecord11(rootExport) && typeof rootExport.import === "string") {
|
|
69132
|
-
return
|
|
69189
|
+
return join48(dirname21(packageJsonPath), rootExport.import);
|
|
69133
69190
|
}
|
|
69134
69191
|
}
|
|
69135
69192
|
if (typeof parsed.module === "string") {
|
|
69136
|
-
return
|
|
69193
|
+
return join48(dirname21(packageJsonPath), parsed.module);
|
|
69137
69194
|
}
|
|
69138
69195
|
if (typeof parsed.main === "string") {
|
|
69139
|
-
return
|
|
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 =
|
|
69212
|
+
let dir = dirname21(fileURLToPath4(import.meta.url));
|
|
69156
69213
|
for (let index2 = 0;index2 < 8; index2++) {
|
|
69157
|
-
const packagePath =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
69333
|
-
await
|
|
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 =
|
|
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 =
|
|
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" ?
|
|
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(
|
|
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 =
|
|
69440
|
+
const root = join48(projectRoot, "src", "package-templates", templateKind);
|
|
69384
69441
|
if (await writeStarterTemplateReviewMarker(root)) {
|
|
69385
|
-
result.created.push(
|
|
69442
|
+
result.created.push(join48(root, PACKAGE_TEMPLATE_REVIEW_FILE));
|
|
69386
69443
|
} else {
|
|
69387
|
-
result.kept.push(
|
|
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:${
|
|
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
|
|
69534
|
+
await mkdir17(join48(projectRoot, dir), { recursive: true });
|
|
69478
69535
|
}
|
|
69479
69536
|
for (const dir of PROJECT_SCRATCH_DIRS) {
|
|
69480
|
-
await
|
|
69537
|
+
await mkdir17(join48(projectRoot, dir), { recursive: true });
|
|
69481
69538
|
}
|
|
69482
|
-
await
|
|
69483
|
-
await
|
|
69484
|
-
await
|
|
69485
|
-
await writeIfMissing(
|
|
69486
|
-
await writeIfMissing(
|
|
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(
|
|
69489
|
-
await writeIfMissing(
|
|
69490
|
-
await writeIfMissing(
|
|
69491
|
-
await writeIfMissing(
|
|
69492
|
-
await writeIfMissing(
|
|
69493
|
-
await writeIfMissing(
|
|
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 =
|
|
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 = [
|
|
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
|
|
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(
|
|
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
|
|
69886
|
-
import { dirname as
|
|
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 =
|
|
69951
|
-
await
|
|
69952
|
-
await
|
|
69953
|
-
await Promise.all(compactFiles.map((file) =>
|
|
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 =
|
|
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) =>
|
|
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 =
|
|
70019
|
-
await
|
|
70020
|
-
await
|
|
70021
|
-
await Promise.all(compactFiles.map((file) =>
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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="
|
|
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
|
|
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:['
|
|
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=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[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:'+(
|
|
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="
|
|
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:#
|
|
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 () => {
|