Files
workinf_Blender_Wasm/tools/web/generate-wbv2-capability-ledger.mjs
mes123456 2abe7cc220
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Advance WBV2 domain parity through P12
2026-08-28 06:38:27 +08:00

94 lines
11 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 write = process.argv.includes("--write");
const absolute = (file) => path.join(root, file);
const read = (file) => fs.readFileSync(absolute(file), "utf8");
const readJson = (file) => JSON.parse(read(file));
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
const outputRoot = "tests/golden/WBV2-P12-001";
const ledgerPath = `${outputRoot}/capability-ledger.json`;
const reportPath = `${outputRoot}/capability-ledger-report.json`;
const sourceIndexPath = `${outputRoot}/source-manifest-index.json`;
const statusPath = "docs/status/WBV2-P12-001.md";
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
const manifestPath = `${outputRoot}/manifest.json`;
const parentPath = "tests/golden/WBV2-P12-000/manifest.json";
const inventoryPath = "tests/golden/WBV2-P0-002/parity-map.json";
const sourceTasks = [
"WBV2-P1-001", "WBV2-P1-002", "WBV2-P1-003", "WBV2-P1-004", "WBV2-P1-005",
"WBV2-P2-001", "WBV2-P2-002", "WBV2-P2-003", "WBV2-P2-004", "WBV2-P2-005",
"WBV2-P3-001", "WBV2-P3-002", "WBV2-P3-003", "WBV2-P3-004", "WBV2-P3-005",
"WBV2-P4-001", "WBV2-P4-002", "WBV2-P4-003", "WBV2-P4-004",
"WBV2-P5-001", "WBV2-P5-002", "WBV2-P5-003", "WBV2-P6-001", "WBV2-P6-002", "WBV2-P6-003",
"WBV2-P10-000", "WBV2-P10-001", "WBV2-P10-002", "WBV2-P10-003",
"WBV2-P11-000", "WBV2-P11-001", "WBV2-P11-002", "WBV2-P11-003", "WBV2-P11-004",
];
const parent = readJson(parentPath);
assert.equal(parent.task, "WBV2-P12-000");
assert.equal(parent.status, "done");
assert.equal(parent.nextTask, "WBV2-P12-001");
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
const inventory = readJson(inventoryPath);
assert.equal(inventory.summary.inventoryEntries, 6900);
assert.equal(inventory.summary.pendingLegacyEntries, 6618);
const entries = sourceTasks.map((task) => {
const manifestPath = `tests/golden/${task}/manifest.json`;
const manifest = readJson(manifestPath);
assert.equal(manifest.task, task);
assert.equal(manifest.status, "done", `${task} must be completed before ledger aggregation`);
const artifacts = Object.values(manifest.artifacts ?? {}).map((artifact) => {
const exists = fs.existsSync(absolute(artifact.path));
return { path: artifact.path, recordedSha256: artifact.sha256, exists, currentHash: exists ? sha256(artifact.path) : null, drift: !exists || (exists && sha256(artifact.path) !== artifact.sha256) };
});
const currentDriftCount = artifacts.filter((artifact) => artifact.drift).length;
const engineBound = ["WBV2-P10-002", "WBV2-P11-004"].includes(task);
return { task, phase: task.match(/^WBV2-P(\d+)/u)?.[1] ?? "?", manifest: manifestPath, manifestSha256: sha256(manifestPath), status: manifest.status, operation: manifest.operation, artifactCount: artifacts.length, currentDriftCount, evidenceClass: engineBound ? "ENGINE_BOUND_EXACT" : currentDriftCount > 0 ? "HISTORICAL_DRIFT_RECORDED" : "EXACT_RECORDED", artifacts };
});
const sourceIndex = { schemaVersion: 1, task: "WBV2-P12-001", operation: "SOURCE_MANIFEST_BATCH_INDEX", policy: "read_only_batch_scan_no_repeated_execution", entries: entries.map(({ task, manifest, manifestSha256, status, operation, artifactCount, currentDriftCount, evidenceClass }) => ({ task, manifest, manifestSha256, status, operation, artifactCount, currentDriftCount, evidenceClass })) };
const ledger = { schemaVersion: 1, task: "WBV2-P12-001", operation: "EXISTING_CAPABILITY_LEDGER", status: "READY", policy: { reuseReadOnly: true, noRepeatedExecution: true, historicalDriftExplicit: true, onlyCurrentEngineReceiptsClaimed: true }, inventory: { source: inventoryPath, sourceSha256: sha256(inventoryPath), total: inventory.summary.inventoryEntries, pending: inventory.summary.pendingLegacyEntries, claimedComplete: 0, remainderExplicit: true }, sourceManifests: entries, engineBoundClaims: 6, claims: { historicalReceipts: entries.filter((entry) => entry.evidenceClass === "EXACT_RECORDED").length, historicalDriftRecorded: entries.filter((entry) => entry.evidenceClass === "HISTORICAL_DRIFT_RECORDED").length, currentEngineBound: entries.filter((entry) => entry.evidenceClass === "ENGINE_BOUND_EXACT").map((entry) => entry.task), noNewExecution: true }, summary: { manifestsDone: entries.length, artifactRecords: entries.reduce((sum, entry) => sum + entry.artifactCount, 0), historicalDriftManifests: entries.filter((entry) => entry.currentDriftCount > 0).length, currentEngineBoundManifests: entries.filter((entry) => entry.evidenceClass === "ENGINE_BOUND_EXACT").length, missingArtifacts: entries.reduce((sum, entry) => sum + entry.artifacts.filter((artifact) => !artifact.exists).length, 0) } };
assert.equal(entries.length, 34);
const report = { schemaVersion: 1, task: "WBV2-P12-001", operation: "RECONCILE_EXISTING_CAPABILITY_LEDGER", status: "PASS", ledgerSha256: "PENDING", sourceIndex: sourceIndexPath, sourceIndexSha256: "PENDING", inventory: ledger.inventory, summary: ledger.summary, reuse: { existingManifestsRead: entries.length, repeatedBlenderRuns: 0, repeatedChromiumRuns: 0, newProductionClaims: 0, engineBoundClaimsReused: ledger.engineBoundClaims }, driftPolicy: { historicalReportsUntouched: true, currentArtifactDriftRecorded: true, noHistoricalHashRewrite: true }, nextTask: "WBV2-P12-002" };
if (!write) { process.stdout.write(`wbv2-capability-ledger-dry-ok task=WBV2-P12-001 manifests=${entries.length} artifacts=${ledger.summary.artifactRecords} driftManifests=${ledger.summary.historicalDriftManifests} repeatedRuns=0 next=WBV2-P12-002\n`); process.exit(0); }
fs.mkdirSync(absolute(outputRoot), { recursive: true });
fs.writeFileSync(absolute(ledgerPath), `${JSON.stringify(ledger, null, 2)}\n`);
fs.writeFileSync(absolute(sourceIndexPath), `${JSON.stringify(sourceIndex, null, 2)}\n`);
report.ledgerSha256 = sha256(ledgerPath);
report.sourceIndexSha256 = sha256(sourceIndexPath);
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
execFileSync(process.execPath, [absolute("tools/web/check-wbv2-capability-ledger.mjs")], { cwd: root, stdio: "inherit" });
fs.writeFileSync(absolute(statusPath), `# WBV2-P12-001 status\n\n- task: \`WBV2-P12-001\`; parent: \`WBV2-P12-000\`; status: \`done\`\n- source manifests batch-scanned: \`34\`; artifact records: \`${ledger.summary.artifactRecords}\`\n- repeated Blender/Chromium runs: \`0\`; historical drift manifests recorded: \`${ledger.summary.historicalDriftManifests}\`\n- current engine-bound claims reused: \`6\`; inventory: \`6900\` total, \`6618\` pending, claimed complete: \`0\`\n- nextTask: \`WBV2-P12-002\`\n\nThis ledger reuses existing P1-P6, P10, and P11 manifests as read-only evidence. It records current artifact drift instead of rewriting historical hashes and does not rerun already completed Blender or Chromium checks. Only P10/P11 engine-bound receipts are treated as current engine evidence; the remaining inventory stays explicit.\n`);
const previousPlan = readJson("tests/golden/WBV2-P12-000/domain-expansion-task-plan.json");
const nextPlan = structuredClone(previousPlan);
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P12-000/domain-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P12-000/domain-expansion-task-plan.json") };
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P12-001" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P12-002" ? { ...task, status: "in_progress", ready: true } : { ...task, ready: false });
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
const nextCardPath = "docs/tasks/WBV2-P12-002.md";
fs.writeFileSync(absolute(nextCardPath), read(nextCardPath).replace("- status: planned", "- status: in_progress"));
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" });
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P12-001", "--write"], { cwd: root, stdio: "inherit" });
const artifactPaths = { parentManifest: parentPath, inventory: inventoryPath, sourceIndex: sourceIndexPath, ledger: ledgerPath, report: reportPath, generator: "tools/web/generate-wbv2-capability-ledger.mjs", checker: "tools/web/check-wbv2-capability-ledger.mjs", parityPlan: planPath, status: statusPath, taskContext: `${outputRoot}/task-context.json` };
const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
const manifest = { schemaVersion: 1, task: "WBV2-P12-001", parentTask: "WBV2-P12-000", operation: "RECONCILE_EXISTING_CAPABILITY_LEDGER", status: "done", enablingTask: true, parityStateChange: false, runtime: "READ_ONLY_MANIFEST_BATCH_SCAN", artifacts, assertions: { sourceManifests: 34, artifactRecords: ledger.summary.artifactRecords, repeatedBlenderRuns: 0, repeatedChromiumRuns: 0, historicalDriftExplicit: true, currentEngineBoundClaimsReused: 6, inventoryTotal: 6900, inventoryPending: 6618, inventoryClaimedComplete: 0, historicalReproduction: false }, nextTask: "WBV2-P12-002" };
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
let queue = read("docs/EXECUTION_QUEUE.md");
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P12-002` |")
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-001/manifest.json` |")
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-002.md`](tasks/WBV2-P12-002.md) |");
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
let nextTaskFile = read("nextTask.md");
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-002` |")
.replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `in_progress` |")
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-001/manifest.json` |")
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-002.md` |")
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P12-003` |")
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-scene-object-production.spec.ts` |");
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
process.stdout.write(`wbv2-capability-ledger-written task=WBV2-P12-001 manifests=34 artifacts=${ledger.summary.artifactRecords} driftManifests=${ledger.summary.historicalDriftManifests} repeatedRuns=0 next=WBV2-P12-002\n`);