68 lines
9.7 KiB
JavaScript
68 lines
9.7 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
const relative = (file) => path.relative(root, file).replaceAll(path.sep, "/");
|
|
const absolute = (file) => path.join(root, file);
|
|
const readJson = (file) => JSON.parse(fs.readFileSync(absolute(file), "utf8"));
|
|
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
|
const outputRoot = "tests/golden/WBV2-P8-000";
|
|
const recoveryPlanPath = `${outputRoot}/recovery-task-plan.json`;
|
|
const reportPath = `${outputRoot}/recovery-root-report.json`;
|
|
const statusPath = "docs/status/WBV2-P8-000.md";
|
|
const manifestPath = `${outputRoot}/manifest.json`;
|
|
|
|
const p7ManifestPath = "tests/golden/WBV2-P7-003/manifest.json";
|
|
const p7StatusPath = "docs/status/WBV2-P7-003.md";
|
|
const p7Manifest = readJson(p7ManifestPath);
|
|
assert.equal(p7Manifest.task, "WBV2-P7-003");
|
|
assert.equal(p7Manifest.status, "blocked");
|
|
assert.equal(p7Manifest.nextTask, null);
|
|
for (const artifact of Object.values(p7Manifest.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
|
|
|
const sourcePlan = readJson("docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json");
|
|
const existing = new Set(sourcePlan.tasks.map((task) => task.id));
|
|
for (const id of ["WBV2-P8-000", "WBV2-P8-001", "WBV2-P8-002", "WBV2-P8-003", "WBV2-P8-004"]) {
|
|
assert.equal(existing.has(id), false, `${id} already exists in the source plan`);
|
|
}
|
|
const tasks = sourcePlan.tasks.map((task) => task.id === "WBV2-P7-003" ? { ...task, status: "blocked", ready: false } : { ...task, ready: false });
|
|
tasks.push(
|
|
{ id: "WBV2-P8-000", phase: "P8", title: "authorize_recovery_capability_root", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P7-003"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p8-governance", gate: "G5", card: "docs/tasks/WBV2-P8-000.md", behavior: "Authorize a recovery epoch without rewriting the blocked P7 manifest.", outputs: ["recovery plan", "root manifest", "queue authorization"], acceptance: ["P7 evidence remains hash exact", "recovery scope is explicit", "one recovery task is active"], status: "done", ready: false, queueMutationAllowed: true },
|
|
{ id: "WBV2-P8-001", phase: "P8", title: "rebaseline_mutable_inventories", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P8-000"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p8-governance", gate: "G5", card: "docs/tasks/WBV2-P8-001.md", behavior: "Rebaseline mutable WBV2 plan and dependency inventory inputs while preserving historical manifests.", outputs: ["semantic drift report", "current inventory baseline", "manifest"], acceptance: ["only expected mutable hashes drift", "dependency closure is unchanged", "historical manifests remain unmodified"], status: "in_progress", ready: true, queueMutationAllowed: false },
|
|
{ id: "WBV2-P8-002", phase: "P8", title: "close_atomic_chromium_receipts", kind: "enabling", owner: "PARITY", dependsOn: ["WBV2-P8-001"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p8-receipts", gate: "G5", card: "docs/tasks/WBV2-P8-002.md", behavior: "Produce and bind all 45 atomic Chromium family receipts.", outputs: ["Chromium report", "45 receipt index", "receipt manifests"], acceptance: ["45 receipts are manifest-bound", "desktop/WASM/save-reopen behaviors are explicit", "Chromium is the only browser"], status: "planned", ready: false, queueMutationAllowed: false },
|
|
{ id: "WBV2-P8-003", phase: "P8", title: "authorize_m12_provenance_epoch", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P8-002"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p8-provenance", gate: "G5", card: "docs/tasks/WBV2-P8-003.md", behavior: "Bind restored M12 sources and explicitly rebaseline unavailable originals in a new provenance epoch.", outputs: ["provenance epoch", "replacement bindings", "manifest"], acceptance: ["22 restored originals stay exact", "62 unavailable entries are not called restored", "all replacements are hash-bound"], status: "planned", ready: false, queueMutationAllowed: false },
|
|
{ id: "WBV2-P8-004", phase: "P8", title: "recompute_recovery_release_gate", kind: "enabling", owner: "RELEASE", dependsOn: ["WBV2-P8-003"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p8-release", gate: "G5", card: "docs/tasks/WBV2-P8-004.md", behavior: "Recompute the release decision from the recovery epoch and atomic receipts.", outputs: ["release gate", "known limitations", "final manifest"], acceptance: ["all receipts bind to manifests", "provenance epoch is explicit", "all governance gates pass"], status: "planned", ready: false, queueMutationAllowed: false },
|
|
);
|
|
|
|
const recoveryPlan = { ...sourcePlan, planId: "BLENDER_WEB_PARITY_V2_RECOVERY_EPOCH_1", parentPlan: { path: "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", sha256: sha256("docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json") }, recoveryRoot: "WBV2-P8-000", tasks };
|
|
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
|
fs.writeFileSync(absolute(recoveryPlanPath), `${JSON.stringify(recoveryPlan, null, 2)}\n`);
|
|
|
|
const report = { schemaVersion: 1, task: "WBV2-P8-000", operation: "AUTHORIZE_RECOVERY_CAPABILITY_ROOT", status: "PASS", parent: { task: p7Manifest.task, manifest: p7ManifestPath, manifestSha256: sha256(p7ManifestPath), status: p7Manifest.status, nextTask: p7Manifest.nextTask }, recovery: { epoch: 1, root: "WBV2-P8-000", firstTask: "WBV2-P8-001", terminalTask: "WBV2-P8-004", taskCount: 5 }, invariants: { historicalP7Rewritten: false, oneActiveTask: tasks.filter((task) => task.ready && task.status === "in_progress").length === 1, chromiumOnly: true }, nextTask: "WBV2-P8-001" };
|
|
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
|
|
|
const rootCard = `# WBV2-P8-000: recovery capability root\n\n- task: WBV2-P8-000\n- parent: WBV2-P7-003\n- status: done\n- gap: workflow:authorize_recovery_capability_root\n- ownerFamily: PROGRAM\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nAuthorize an explicit recovery epoch without changing the blocked P7 evidence.\n\n## 验收\n\nnode tools/web/generate-wbv2-recovery-root.mjs\nnode tools/web/check-execution-control-plane.mjs\nnode tools/web/check-v2-task-index.mjs\n`;
|
|
fs.mkdirSync(absolute("docs/tasks"), { recursive: true });
|
|
fs.writeFileSync(absolute("docs/tasks/WBV2-P8-000.md"), rootCard);
|
|
const activeCard = `# WBV2-P8-001: mutable inventory recovery baseline\n\n- task: WBV2-P8-001\n- parent: WBV2-P8-000\n- status: in_progress\n- gap: workflow:rebaseline_mutable_inventories\n- ownerFamily: PROGRAM\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nRebaseline the mutable WBV2 plan and npm dependency inventory without rewriting historical manifests.\n\n## 输入与范围\n\n- Checker: \`tools/web/check-wbv2-recovery-baseline.mjs\`\n- Historical WBV2 inventory: \`tests/golden/WBV2-P0-002/\`\n- Historical dependency inventory: \`tests/golden/M13-05C/\`\n\n## 验收\n\nnode tools/web/check-wbv2-recovery-baseline.mjs --write\nnode tools/web/check-execution-control-plane.mjs\nnode tools/web/check-v2-task-index.mjs\nnode tools/web/check-task-context.mjs --task WBV2-P8-001 --write\n\nUnexpected dependency closure drift, unsupported plan transitions, missing files, or hash failures must keep the task in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P8-001/\`\n- Status: \`docs/status/WBV2-P8-001.md\`\n- Manifest: \`tests/golden/WBV2-P8-001/manifest.json\`\n- Rollback: restore the recovery root as the queue parent without changing P7 evidence.\n`;
|
|
fs.writeFileSync(absolute("docs/tasks/WBV2-P8-001.md"), activeCard);
|
|
const status = `# WBV2-P8-000 status\n\n- task: \`WBV2-P8-000\`; parent: \`WBV2-P7-003\`; status: \`done\`\n- recovery epoch: 1\n- nextTask: \`WBV2-P8-001\`\n\nThe blocked P7 manifest remains unchanged. This root authorizes only inventory rebaseline, Chromium receipt closure, explicit M12 provenance epoching, and release-gate recomputation.\n`;
|
|
fs.writeFileSync(absolute(statusPath), status);
|
|
|
|
const artifactPaths = { parentManifest: p7ManifestPath, parentStatus: p7StatusPath, sourcePlan: "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", recoveryPlan: recoveryPlanPath, generator: "tools/web/generate-wbv2-recovery-root.mjs", report: reportPath, status: statusPath, rootCard: "docs/tasks/WBV2-P8-000.md", activeCard: "docs/tasks/WBV2-P8-001.md" };
|
|
const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
|
|
const manifest = { schemaVersion: 1, task: "WBV2-P8-000", parentTask: "WBV2-P7-003", operation: "AUTHORIZE_RECOVERY_CAPABILITY_ROOT", status: "done", enablingTask: true, parityStateChange: false, queueMutationAllowed: true, artifacts, nextTask: "WBV2-P8-001" };
|
|
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
|
|
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", recoveryPlanPath], { cwd: root, stdio: "inherit" });
|
|
let queue = fs.readFileSync(absolute("docs/EXECUTION_QUEUE.md"), "utf8");
|
|
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P8-001` |")
|
|
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P8-000/manifest.json` |")
|
|
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P8-001.md`](tasks/WBV2-P8-001.md) |");
|
|
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
|
process.stdout.write(`wbv2-recovery-root-ok root=WBV2-P8-000 next=WBV2-P8-001 plan=${relative(absolute(recoveryPlanPath))}\n`);
|