Files
workinf_Blender_Wasm/tools/web/reactivate-legacy-queue.mjs
mes123456 a081c68c87
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
Reorganize Blender Web execution around capabilities
2026-08-24 18:37:46 -04:00

103 lines
6.5 KiB
JavaScript

import assert from "node:assert/strict";
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 queuePath = path.join(root, "docs/EXECUTION_QUEUE.md");
const reviewPath = path.join(root, "tests/golden/corrective/C6-003/owner-review.json");
const dryRunPath = path.join(root, "tests/golden/corrective/C6-003/queue-reactivation-dry-run.json");
const writePreviewPath = path.join(root, "tests/golden/corrective/C6-003/queue-reactivation-write-preview.json");
const currentManifestPath = path.join(root, "tests/golden/M16-GAP-00276/manifest.json");
const currentStatusPath = path.join(root, "docs/status/M16-GAP-00276.md");
const completionPath = path.join(root, "tests/golden/M15-03A/completed-gap-tasks.json");
const nextPlanPath = path.join(root, "tests/golden/M15-03A/next-task-plan.json");
const catalogPath = path.join(root, "tests/golden/M15-03A/task-catalog.jsonl");
const indexPath = path.join(root, "tests/golden/M15-03A/task-index.json");
const evidenceRoot = path.join(root, "tests/golden/corrective/C6-003");
const relative = (file) => path.relative(root, file).replaceAll(path.sep, "/");
const sha256 = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex");
const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
const writeJson = (file, value) => fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
const write = process.argv.includes("--write");
if (!write) throw new Error("queue reactivation is write-only after review; pass --write explicitly");
const review = readJson(reviewPath);
assert.equal(review.task, "C6-003");
assert.equal(review.status, "APPROVED");
assert.equal(review.authorization?.approved, true);
assert.equal(review.decision?.allowQueueMutation, true);
assert.equal(review.decision?.targetTask, "M16-GAP-00277");
const dryRunBytes = fs.readFileSync(dryRunPath);
const writePreviewBytes = fs.readFileSync(writePreviewPath);
assert.equal(sha256(dryRunBytes), review.reviewedEvidence.dryRun.sha256);
assert.equal(sha256(writePreviewBytes), review.reviewedEvidence.writePreview.sha256);
assert.deepEqual(dryRunBytes, writePreviewBytes, "dry-run and write-preview bytes differ");
const dryRun = JSON.parse(dryRunBytes);
assert.equal(dryRun.status, "BLOCKED_OWNER_REVIEW");
assert.equal(dryRun.queueMutation, false);
assert.equal(dryRun.legacyQueue.currentTask, "M16-GAP-00276");
assert.equal(dryRun.legacyQueue.parentManifest, "tests/golden/M16-GAP-00275/manifest.json");
const currentManifest = readJson(currentManifestPath);
assert.equal(currentManifest.task, "M16-GAP-00276");
assert.equal(currentManifest.status, "done", "complete the focused legacy task before queue write");
assert.equal(currentManifest.nextTask, "M16-GAP-00277");
assert.match(fs.readFileSync(currentStatusPath, "utf8"), /^status:\s*done\s*$/mu);
assert.ok(readJson(completionPath).includes("operator:asset.clear_single"), "completion registry is not closed");
const nextPlan = readJson(nextPlanPath);
assert.equal(nextPlan.firstTask, "M16-GAP-00277");
assert.equal(nextPlan.tasks.find((entry) => entry.id === "M16-GAP-00276")?.state, "completed");
assert.equal(nextPlan.tasks.find((entry) => entry.id === "M16-GAP-00277")?.state, "active");
const taskIndex = readJson(indexPath);
assert.equal(taskIndex.activeTask, "M16-GAP-00277");
const catalogRows = fs.readFileSync(catalogPath, "utf8").trimEnd().split("\n").map((line) => JSON.parse(line));
assert.equal(catalogRows.find((entry) => entry.id === "M16-GAP-00276")?.state, "completed");
assert.equal(catalogRows.find((entry) => entry.id === "M16-GAP-00277")?.state, "active");
const queueBefore = fs.readFileSync(queuePath);
assert.equal(sha256(queueBefore), review.reviewedEvidence.protectedHashes["docs/EXECUTION_QUEUE.md"]);
const parentManifestPath = path.join(root, "tests/golden/M16-GAP-00275/manifest.json");
assert.equal(sha256(fs.readFileSync(parentManifestPath)), review.reviewedEvidence.protectedHashes["tests/golden/M16-GAP-00275/manifest.json"]);
const queueSource = queueBefore.toString("utf8");
assert.match(queueSource, /\|\s*当前任务\s*\|\s*`M16-GAP-00276`/u);
assert.match(queueSource, /\|\s*parent manifest\s*\|\s*`tests\/golden\/M16-GAP-00275\/manifest\.json`/u);
const queueAfter = queueSource
.replace("| 当前任务 | `M16-GAP-00276`", "| 当前任务 | `M16-GAP-00277`")
.replace("| parent manifest | `tests/golden/M16-GAP-00275/manifest.json`", "| parent manifest | `tests/golden/M16-GAP-00276/manifest.json`")
.replace("| 任务卡 | [`tasks/M16-GAP-00276.md`](tasks/M16-GAP-00276.md)", "| 任务卡 | [`tasks/M16-GAP-00277.md`](tasks/M16-GAP-00277.md)")
.replace("| 专项验收 | `npm --prefix web run test:generated-gap -- --task M16-GAP-00276`", "| 专项验收 | `npm --prefix web run test:generated-gap -- --task M16-GAP-00277`");
assert.notEqual(queueAfter, queueSource);
assert.match(queueAfter, /\|\s*当前任务\s*\|\s*`M16-GAP-00277`/u);
assert.match(queueAfter, /\|\s*parent manifest\s*\|\s*`tests\/golden\/M16-GAP-00276\/manifest\.json`/u);
const beforePath = path.join(evidenceRoot, "queue-before.md");
const afterPath = path.join(evidenceRoot, "queue-after.md");
fs.writeFileSync(beforePath, queueBefore);
fs.writeFileSync(afterPath, queueAfter);
const temporary = `${queuePath}.c6-003-${process.pid}.tmp`;
try {
fs.writeFileSync(temporary, queueAfter, { mode: fs.statSync(queuePath).mode });
fs.renameSync(temporary, queuePath);
} finally {
if (fs.existsSync(temporary)) fs.rmSync(temporary);
}
const observedAfter = fs.readFileSync(queuePath);
assert.deepEqual(observedAfter, Buffer.from(queueAfter));
const receipt = {
schemaVersion: 1,
task: "C6-003",
operation: "CORRECTIVE_QUEUE_REACTIVATION_WRITE",
status: "APPLIED",
queueMutation: true,
authorization: { review: relative(reviewPath), approved: true },
before: { path: relative(beforePath), sha256: sha256(queueBefore), currentTask: "M16-GAP-00276", parentManifest: "tests/golden/M16-GAP-00275/manifest.json" },
after: { path: relative(afterPath), sha256: sha256(observedAfter), currentTask: "M16-GAP-00277", parentManifest: "tests/golden/M16-GAP-00276/manifest.json" },
changedFields: ["currentTask", "parentManifest", "taskCard", "focusedCommand"],
rollback: { action: "restore before.path atomically", source: relative(beforePath) },
};
writeJson(path.join(evidenceRoot, "queue-reactivation-write-receipt.json"), receipt);
process.stdout.write(`queue-reactivation-ok task=C6-003 queue=M16-GAP-00277 before=${receipt.before.sha256} after=${receipt.after.sha256}\n`);