Reorganize Blender Web execution around capabilities
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions

This commit is contained in:
mes123456
2026-08-24 18:37:46 -04:00
parent 0b2c3ba0dd
commit a081c68c87
2530 changed files with 763976 additions and 79 deletions

View File

@@ -0,0 +1,90 @@
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const read = (relative) => fs.readFileSync(path.join(root, relative), "utf8");
const sha256 = (relative) => crypto.createHash("sha256").update(read(relative)).digest("hex");
const parseJson = (relative) => JSON.parse(read(relative));
const relative = (absolute) => path.relative(root, absolute).replaceAll(path.sep, "/");
function argument(name) {
const index = process.argv.indexOf(name);
return index >= 0 ? process.argv[index + 1] : undefined;
}
function queueCurrentTask() {
const source = read("docs/EXECUTION_QUEUE.md");
return source.match(/\|\s*当前任务\s*\|\s*`([^`]+)`/u)?.[1]
?? source.match(/当前任务\s*[:]\s*`([^`]+)`/u)?.[1];
}
function countLegacyEvidence() {
const rootPath = path.join(root, "tests/golden");
return fs.readdirSync(rootPath, { withFileTypes: true })
.filter((entry) => entry.isDirectory() && /^M16-GAP-\d{5}$/u.test(entry.name))
.length;
}
const task = argument("--task") ?? queueCurrentTask();
const output = argument("--output");
if (!task || !output) {
throw new Error("usage: node tools/web/capture-corrective-baseline.mjs --task M16-GAP-xxxxx --output path");
}
const queue = read("docs/EXECUTION_QUEUE.md");
const parentManifestPath = queue.match(/\|\s*parent manifest\s*\|\s*`([^`]+)`/iu)?.[1];
if (!parentManifestPath) throw new Error("EXECUTION_QUEUE.md does not declare parent manifest");
const parentManifest = parseJson(parentManifestPath);
if (queueCurrentTask() !== task) throw new Error(`queue current task mismatch: ${queueCurrentTask()} != ${task}`);
if (parentManifest.nextTask !== task) throw new Error(`parent nextTask mismatch: ${parentManifest.nextTask} != ${task}`);
const parentStatusPath = `docs/status/${parentManifest.task}.md`;
if (!fs.existsSync(path.join(root, parentStatusPath))) throw new Error(`missing parent status: ${parentStatusPath}`);
const plan = parseJson("tests/golden/M15-03A/next-task-plan.json");
const catalog = read("tests/golden/M15-03A/task-catalog.jsonl");
const activeIds = catalog.split("\n").filter(Boolean).map((line) => JSON.parse(line))
.filter((entry) => entry.state === "active").map((entry) => entry.id);
const sourcePaths = [
"docs/EXECUTION_QUEUE.md",
parentManifestPath,
parentStatusPath,
"tests/golden/M15-03A/completed-gap-tasks.json",
"tests/golden/M15-03A/task-catalog.jsonl",
"tests/golden/M15-03A/task-index.json",
"tests/golden/M15-03A/next-task-plan.json",
];
const baseline = {
schemaVersion: 1,
task,
queue: {
currentTask: queueCurrentTask(),
parentManifest: parentManifestPath,
parentNextTask: parentManifest.nextTask,
},
generatedState: {
catalogActiveTask: activeIds.length === 1 ? activeIds[0] : null,
catalogActiveIds: activeIds,
planFirstTask: plan.firstTask,
planNextTask: plan.nextTask,
completionCount: parseJson("tests/golden/M15-03A/completed-gap-tasks.json").length,
legacyEvidenceDirectoryCount: countLegacyEvidence(),
},
sourceHashes: Object.fromEntries(sourcePaths.map((sourcePath) => [sourcePath, sha256(sourcePath)])),
invariants: {
queueMutationAllowed: false,
parentPointerMatchesCurrent: parentManifest.nextTask === task,
exactlyOneCatalogActive: activeIds.length === 1,
catalogActiveMatchesPlan: activeIds[0] === plan.firstTask,
},
};
if (!baseline.invariants.parentPointerMatchesCurrent || !baseline.invariants.exactlyOneCatalogActive || !baseline.invariants.catalogActiveMatchesPlan) {
throw new Error(`generated state is inconsistent: ${JSON.stringify(baseline.invariants)}`);
}
const outputPath = path.resolve(root, output);
if (!outputPath.startsWith(`${root}${path.sep}`)) throw new Error("baseline output must stay inside the repository");
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
fs.writeFileSync(outputPath, `${JSON.stringify(baseline, null, 2)}\n`);
process.stdout.write(`corrective-baseline-ok task=${task} active=${activeIds[0]} parentNext=${parentManifest.nextTask} output=${relative(outputPath)}\n`);