Complete WBV2 feature parity evidence epoch
This commit is contained in:
179
tools/web/generate-wbv2-asset-catalog-receipt.mjs
Normal file
179
tools/web/generate-wbv2-asset-catalog-receipt.mjs
Normal file
@@ -0,0 +1,179 @@
|
||||
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-P9-003";
|
||||
const chromiumPath = `${outputRoot}/chromium-asset-catalog-production.json`;
|
||||
const chromiumSecondPath = `${outputRoot}/chromium-asset-catalog-production.second.json`;
|
||||
const reportPath = `${outputRoot}/asset-catalog-receipt-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P9-003.md";
|
||||
const planPath = `${outputRoot}/feature-parity-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentManifestPath = "tests/golden/WBV2-P9-002/manifest.json";
|
||||
const sourceManifestPath = "tests/golden/corrective/C3-003/manifest.json";
|
||||
const sourceReportPath = "tests/golden/corrective/C3-003/receipt-report.json";
|
||||
|
||||
const parent = readJson(parentManifestPath);
|
||||
assert.equal(parent.task, "WBV2-P9-002");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P9-003");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
|
||||
const sourceManifest = readJson(sourceManifestPath);
|
||||
const sourceReport = readJson(sourceReportPath);
|
||||
assert.equal(sourceManifest.task, "C3-003");
|
||||
assert.equal(sourceManifest.status, "done");
|
||||
assert.equal(sourceReport.task, "C3-003");
|
||||
assert.equal(sourceReport.browser, "chromium");
|
||||
assert.equal(sourceReport.queueMutation, false);
|
||||
assert.equal(sourceReport.parity, true);
|
||||
assert.equal(sourceReport.positive.desktop.status, "FINISHED");
|
||||
assert.equal(sourceReport.positive.wasm.status, "FINISHED");
|
||||
assert.equal(sourceReport.persistence.dirty, false);
|
||||
const sourceBound = Object.values(sourceManifest.artifacts ?? {}).find((artifact) => artifact.path === sourceReportPath);
|
||||
assert.ok(sourceBound, "C3-003 source report is not manifest-bound");
|
||||
assert.equal(sourceBound.sha256, sha256(sourceReportPath));
|
||||
|
||||
assert.equal(sha256(chromiumPath), sha256(chromiumSecondPath), "Chromium Asset Catalog report is not deterministic");
|
||||
const chromium = readJson(chromiumPath);
|
||||
assert.equal(chromium.task, "WBV2-P9-003");
|
||||
assert.equal(chromium.operation, "ASSET_CATALOG_PRODUCTION_CHROMIUM");
|
||||
assert.equal(chromium.browser, "chromium");
|
||||
assert.equal(chromium.queueMutation, false);
|
||||
assert.equal(chromium.positive.parity, true);
|
||||
for (const surface of ["desktop", "wasm"]) {
|
||||
const result = chromium.positive[surface];
|
||||
assert.equal(result.status, "FINISHED");
|
||||
assert.equal(result.code, "OK");
|
||||
assert.equal(result.mainRevisionBefore, 4);
|
||||
assert.equal(result.mainRevisionAfter, 5);
|
||||
assert.equal(result.mainMutation, "CHANGED");
|
||||
assert.deepEqual(result.delta, { addedId: "asset:wbv2-p9-003", count: 1 });
|
||||
}
|
||||
assert.deepEqual(chromium.positive.desktop, chromium.positive.wasm);
|
||||
assert.equal(chromium.resource.provider, "EXTERNAL_LIBRARY");
|
||||
assert.match(chromium.resource.sha256, /^[a-f0-9]{64}$/u);
|
||||
assert.equal(chromium.resource.byteLength, 27);
|
||||
assert.equal(chromium.positive.desktopMain.value.entries[0].sourceSha256, chromium.resource.sha256);
|
||||
assert.equal(chromium.negative.duplicate.code, "COMMAND_UNSUPPORTED");
|
||||
assert.equal(chromium.negative.stale.code, "REVISION_CONFLICT");
|
||||
assert.equal(chromium.negative.malformed.code, "COMMAND_MALFORMED");
|
||||
assert.equal(chromium.negative.missing.code, "RESOURCE_REQUIRED");
|
||||
assert.equal(chromium.negative.missing.mainRevisionAfter, 4);
|
||||
assert.equal(chromium.persistence.exact, true);
|
||||
assert.deepEqual(chromium.persistence.reopened, chromium.persistence.saved);
|
||||
|
||||
const receipt = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P9-003",
|
||||
operation: "ASSET_CATALOG_PRODUCTION_CHROMIUM_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
source: {
|
||||
task: "C3-003",
|
||||
manifest: sourceManifestPath,
|
||||
manifestSha256: sha256(sourceManifestPath),
|
||||
report: sourceReportPath,
|
||||
reportSha256: sha256(sourceReportPath),
|
||||
exactChromiumPilot: true,
|
||||
pilotSaveReopenState: sourceReport.persistence.dirty === false,
|
||||
},
|
||||
chromium: {
|
||||
report: chromiumPath,
|
||||
reportSha256: sha256(chromiumPath),
|
||||
secondReport: chromiumSecondPath,
|
||||
secondReportSha256: sha256(chromiumSecondPath),
|
||||
deterministic: true,
|
||||
surfaces: ["DESKTOP", "WASM"],
|
||||
resource: chromium.resource,
|
||||
positive: { desktop: chromium.positive.desktop, wasm: chromium.positive.wasm, parity: chromium.positive.parity },
|
||||
negative: { duplicate: chromium.negative.duplicate, stale: chromium.negative.stale, malformed: chromium.negative.malformed, missing: chromium.negative.missing },
|
||||
persistence: { exact: chromium.persistence.exact, saved: chromium.persistence.saved, reopened: chromium.persistence.reopened },
|
||||
},
|
||||
assertions: {
|
||||
realAssetCatalogAppend: true,
|
||||
resourceHashBound: true,
|
||||
desktopWasmDeltaMatch: true,
|
||||
saveReopenExact: true,
|
||||
failureMatrixClosed: true,
|
||||
featureParityClaim: "CAP-ASSET-CATALOG-MUTATION",
|
||||
historicalReproduction: false,
|
||||
},
|
||||
nextTask: "WBV2-P9-004",
|
||||
};
|
||||
|
||||
if (!write) {
|
||||
process.stdout.write("wbv2-asset-catalog-receipt-ok task=WBV2-P9-003 deterministic=true next=WBV2-P9-004\n");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(receipt, null, 2)}\n`);
|
||||
const status = `# WBV2-P9-003 status\n\n- task: \`WBV2-P9-003\`; parent: \`WBV2-P9-002\`; status: \`done\`\n- Asset Catalog Chromium receipt: \`DESKTOP + WASM\`\n- resource: \`EXTERNAL_LIBRARY/library.blend\`; hash-bound\n- append revision: \`4 -> 5\`; save/reopen: \`EXACT\`\n- nextTask: \`WBV2-P9-004\`\n\nThe production Chromium receipt executes the existing Asset Catalog Main and resource resolver. Duplicate, stale, malformed, and missing-resource commands are rejected without a late mutation. This is a bounded current implementation claim and does not assert historical byte reproduction.\n`;
|
||||
fs.writeFileSync(absolute(statusPath), status);
|
||||
|
||||
const previousPlan = readJson("tests/golden/WBV2-P9-002/feature-parity-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P9-002/feature-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P9-002/feature-parity-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P9-003"
|
||||
? { ...task, status: "done", ready: false }
|
||||
: task.id === "WBV2-P9-004"
|
||||
? { ...task, status: "in_progress", ready: true }
|
||||
: { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
|
||||
const nextCard = `# WBV2-P9-004: feature parity gate\n\n- task: WBV2-P9-004\n- parent: WBV2-P9-003\n- status: in_progress\n- gap: workflow:recompute_feature_parity_gate\n- ownerFamily: RELEASE\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nRecompute declared feature parity claims only from the three production Chromium receipts and preserve the authorized-rebaseline-only release boundary.\n\n## 输入与范围\n\n- Mesh receipt: \`tests/golden/WBV2-P9-001/mesh-receipt-report.json\`\n- Modifier receipt: \`tests/golden/WBV2-P9-002/modifier-receipt-report.json\`\n- Asset receipt: \`tests/golden/WBV2-P9-003/asset-catalog-receipt-report.json\`\n- M12 approval: \`docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json\`\n\n## 验收\n\n- \`node tools/web/generate-wbv2-feature-parity-gate.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P9-004 --write\`\n\nMissing receipt, hash drift, unsupported browser, non-exact save/reopen, false historical reproduction, or undeclared feature claim must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P9-004/\`\n- Status: \`docs/status/WBV2-P9-004.md\`\n- Manifest: \`tests/golden/WBV2-P9-004/manifest.json\`\n- Rollback: restore P9-003 as queue parent without modifying any production receipt or provenance evidence.\n`;
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P9-004.md"), nextCard);
|
||||
|
||||
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-P9-003", "--write"], { cwd: root, stdio: "inherit" });
|
||||
|
||||
const artifactPaths = {
|
||||
parentManifest: parentManifestPath,
|
||||
sourceManifest: sourceManifestPath,
|
||||
sourceReport: sourceReportPath,
|
||||
chromiumReport: chromiumPath,
|
||||
chromiumSecondReport: chromiumSecondPath,
|
||||
e2e: "web/tests/e2e/wbv2-asset-catalog-production.spec.ts",
|
||||
protocol: "web/protocol/corrective-asset-catalog-command.ts",
|
||||
resourceProvider: "web/protocol/corrective-resource-provider.ts",
|
||||
bridge: "web/app/src/corrective-pilot-bridge.ts",
|
||||
generator: "tools/web/generate-wbv2-asset-catalog-receipt.mjs",
|
||||
report: reportPath,
|
||||
status: statusPath,
|
||||
featureParityPlan: planPath,
|
||||
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-P9-003",
|
||||
parentTask: "WBV2-P9-002",
|
||||
operation: "ASSET_CATALOG_PRODUCTION_CHROMIUM_RECEIPT",
|
||||
status: "done",
|
||||
enablingTask: false,
|
||||
parityStateChange: true,
|
||||
runtime: "PLAYWRIGHT_CHROMIUM_DESKTOP_AND_WASM",
|
||||
artifacts,
|
||||
assertions: { capabilityId: "CAP-ASSET-CATALOG-MUTATION", browser: "chromium", surfaces: 2, deterministic: true, resourceHashBound: true, saveReopen: "EXACT", negativeCases: 4, historicalReproduction: false },
|
||||
nextTask: "WBV2-P9-004",
|
||||
};
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P9-004` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P9-003/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P9-004.md`](tasks/WBV2-P9-004.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-v2-task-index.mjs")], { cwd: root, stdio: "pipe" });
|
||||
process.stdout.write(`wbv2-asset-catalog-receipt-written task=WBV2-P9-003 surfaces=2 deterministic=true next=WBV2-P9-004 artifacts=${Object.keys(artifacts).length}\n`);
|
||||
164
tools/web/generate-wbv2-feature-parity-gate.mjs
Normal file
164
tools/web/generate-wbv2-feature-parity-gate.mjs
Normal file
@@ -0,0 +1,164 @@
|
||||
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-P9-004";
|
||||
const reportPath = `${outputRoot}/feature-parity-gate-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P9-004.md";
|
||||
const planPath = `${outputRoot}/feature-parity-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentManifestPath = "tests/golden/WBV2-P9-003/manifest.json";
|
||||
const approvalPath = "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json";
|
||||
|
||||
const parent = readJson(parentManifestPath);
|
||||
assert.equal(parent.task, "WBV2-P9-003");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P9-004");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
|
||||
const approval = readJson(approvalPath);
|
||||
assert.equal(approval.decision, "APPROVED");
|
||||
assert.equal(approval.epoch, 2);
|
||||
assert.equal(approval.approvedBy, "wangdequan");
|
||||
assert.equal(approval.limitations.fullHistoricalReproduction, false);
|
||||
assert.equal(approval.limitations.replacementIsHistoricalRestoration, false);
|
||||
assert.equal(approval.limitations.releaseLabel, "AUTHORIZED_REBASELINE_ONLY");
|
||||
|
||||
const receipts = [
|
||||
{ family: "MESH", capabilityId: "CAP-MESH-POSITIVE-EDIT", manifest: "tests/golden/WBV2-P9-001/manifest.json", report: "tests/golden/WBV2-P9-001/mesh-receipt-report.json" },
|
||||
{ family: "MODIFIER", capabilityId: "CAP-MODIFIER-STATE-MUTATION", manifest: "tests/golden/WBV2-P9-002/manifest.json", report: "tests/golden/WBV2-P9-002/modifier-receipt-report.json" },
|
||||
{ family: "ASSET_CATALOG", capabilityId: "CAP-ASSET-CATALOG-MUTATION", manifest: "tests/golden/WBV2-P9-003/manifest.json", report: "tests/golden/WBV2-P9-003/asset-catalog-receipt-report.json" },
|
||||
];
|
||||
const checked = receipts.map((entry) => {
|
||||
const manifest = readJson(entry.manifest);
|
||||
const report = readJson(entry.report);
|
||||
assert.equal(manifest.status, "done", `${entry.family} manifest is not done`);
|
||||
assert.equal(manifest.nextTask, entry.family === "ASSET_CATALOG" ? "WBV2-P9-004" : entry.family === "MODIFIER" ? "WBV2-P9-003" : "WBV2-P9-002");
|
||||
assert.equal(report.status, "PASS", `${entry.family} receipt is not PASS`);
|
||||
assert.equal(report.browser, "chromium", `${entry.family} receipt is not Chromium evidence`);
|
||||
assert.equal(report.queueMutation, false, `${entry.family} receipt mutated the queue`);
|
||||
assert.equal(report.assertions.historicalReproduction, false, `${entry.family} receipt claims historical reproduction`);
|
||||
assert.equal(report.assertions.saveReopenExact, true, `${entry.family} receipt lacks exact save/reopen`);
|
||||
assert.equal(report.chromium.deterministic, true, `${entry.family} receipt is not deterministic`);
|
||||
const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === entry.report);
|
||||
assert.ok(bound, `${entry.family} report is not manifest-bound`);
|
||||
assert.equal(bound.sha256, sha256(entry.report), `${entry.family} report hash drift`);
|
||||
return {
|
||||
family: entry.family,
|
||||
capabilityId: entry.capabilityId,
|
||||
manifest: entry.manifest,
|
||||
manifestSha256: sha256(entry.manifest),
|
||||
report: entry.report,
|
||||
reportSha256: sha256(entry.report),
|
||||
browser: report.browser,
|
||||
surfaces: report.chromium.surfaces,
|
||||
deterministic: report.chromium.deterministic,
|
||||
saveReopen: report.assertions.saveReopenExact ? "EXACT" : "UNPROVEN",
|
||||
negativeMatrixClosed: report.assertions.failureMatrixClosed === true,
|
||||
};
|
||||
});
|
||||
|
||||
const gate = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P9-004",
|
||||
operation: "RECOMPUTE_FEATURE_PARITY_GATE",
|
||||
status: "PASS",
|
||||
decision: {
|
||||
status: "READY_WITH_BOUNDED_FEATURE_PARITY",
|
||||
code: "FEATURE_PARITY_AUTHORIZED_REBASELINE",
|
||||
featureParityClaims: checked.map((entry) => entry.capabilityId),
|
||||
featureParityClaimCount: checked.length,
|
||||
provenanceEpoch: approval.epoch,
|
||||
releaseScope: approval.limitations.releaseLabel,
|
||||
fullHistoricalReproduction: approval.limitations.fullHistoricalReproduction,
|
||||
historicalOriginalsRestored: false,
|
||||
},
|
||||
receipts: checked,
|
||||
negative: {
|
||||
missingReceipt: "REJECTED",
|
||||
receiptHashDrift: "REJECTED",
|
||||
unsupportedBrowser: "REJECTED",
|
||||
nonExactSaveReopen: "REJECTED",
|
||||
falseHistoricalReproduction: "REJECTED",
|
||||
undeclaredFeatureClaim: "REJECTED",
|
||||
},
|
||||
policy: {
|
||||
authorizedRebaselineOnly: true,
|
||||
sourceHistoryReadOnly: true,
|
||||
claimsAreEvidenceBound: true,
|
||||
terminalQueuePointer: true,
|
||||
},
|
||||
nextTask: null,
|
||||
};
|
||||
|
||||
if (!write) {
|
||||
process.stdout.write(`wbv2-feature-parity-gate-ok task=WBV2-P9-004 claims=${checked.length} epoch=${approval.epoch} release=${approval.limitations.releaseLabel}\n`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(gate, null, 2)}\n`);
|
||||
const status = `# WBV2-P9-004 status\n\n- task: \`WBV2-P9-004\`; parent: \`WBV2-P9-003\`; status: \`done\`\n- evidenced feature claims: \`3\`\n- claims: \`CAP-MESH-POSITIVE-EDIT\`, \`CAP-MODIFIER-STATE-MUTATION\`, \`CAP-ASSET-CATALOG-MUTATION\`\n- provenance: epoch \`2\`, \`AUTHORIZED_REBASELINE_ONLY\`\n- fullHistoricalReproduction: \`false\`\n- nextTask: \`NONE\`\n\nThe gate emits only claims backed by deterministic Chromium production receipts with exact save/reopen evidence. The project owner-approved epoch 2 baseline remains explicitly separate from unavailable historical bytes; this is not a full historical reproduction claim. P9-004 remains the terminal execution pointer because no successor is authorized.\n`;
|
||||
fs.writeFileSync(absolute(statusPath), status);
|
||||
|
||||
const previousPlan = readJson("tests/golden/WBV2-P9-003/feature-parity-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.status = "COMPLETED_WITH_BOUNDED_FEATURE_PARITY";
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P9-003/feature-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P9-003/feature-parity-task-plan.json") };
|
||||
// Keep one active terminal pointer for the execution index; the manifest below
|
||||
// is the completion record and deliberately has no successor.
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P9-004"
|
||||
? { ...task, status: "in_progress", ready: true }
|
||||
: { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
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-P9-004", "--write"], { cwd: root, stdio: "inherit" });
|
||||
|
||||
const artifactPaths = {
|
||||
parentManifest: parentManifestPath,
|
||||
approval: approvalPath,
|
||||
meshManifest: receipts[0].manifest,
|
||||
meshReport: receipts[0].report,
|
||||
modifierManifest: receipts[1].manifest,
|
||||
modifierReport: receipts[1].report,
|
||||
assetManifest: receipts[2].manifest,
|
||||
assetReport: receipts[2].report,
|
||||
generator: "tools/web/generate-wbv2-feature-parity-gate.mjs",
|
||||
report: reportPath,
|
||||
status: statusPath,
|
||||
featureParityPlan: planPath,
|
||||
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-P9-004",
|
||||
parentTask: "WBV2-P9-003",
|
||||
operation: "RECOMPUTE_FEATURE_PARITY_GATE",
|
||||
status: "done",
|
||||
enablingTask: true,
|
||||
parityStateChange: true,
|
||||
runtime: "PLAYWRIGHT_CHROMIUM_DESKTOP_AND_WASM",
|
||||
artifacts,
|
||||
assertions: {
|
||||
featureParityClaims: checked.map((entry) => entry.capabilityId),
|
||||
featureParityClaimCount: checked.length,
|
||||
deterministicReceipts: checked.length,
|
||||
exactSaveReopen: checked.length,
|
||||
provenanceEpoch: approval.epoch,
|
||||
authorizedRebaselineOnly: true,
|
||||
fullHistoricalReproduction: false,
|
||||
},
|
||||
nextTask: null,
|
||||
};
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
process.stdout.write(`wbv2-feature-parity-gate-written task=WBV2-P9-004 claims=${checked.length} epoch=${approval.epoch} release=${approval.limitations.releaseLabel} terminal=true artifacts=${Object.keys(artifacts).length}\n`);
|
||||
67
tools/web/generate-wbv2-feature-parity-root.mjs
Normal file
67
tools/web/generate-wbv2-feature-parity-root.mjs
Normal file
@@ -0,0 +1,67 @@
|
||||
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 absolute = (file) => path.join(root, file);
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const readJson = (file) => JSON.parse(fs.readFileSync(absolute(file), "utf8"));
|
||||
const outputRoot = "tests/golden/WBV2-P9-000";
|
||||
const planPath = `${outputRoot}/feature-parity-task-plan.json`;
|
||||
const reportPath = `${outputRoot}/feature-parity-root-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P9-000.md";
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const p8ManifestPath = "tests/golden/WBV2-P8-004/manifest.json";
|
||||
const p8ReportPath = "tests/golden/WBV2-P8-004/recovery-release-gate-report.json";
|
||||
const p8StatusPath = "docs/status/WBV2-P8-004.md";
|
||||
|
||||
const p8 = readJson(p8ManifestPath); const p8Report = readJson(p8ReportPath);
|
||||
assert.equal(p8.task, "WBV2-P8-004"); assert.equal(p8.status, "blocked"); assert.ok(p8.nextTask === null || p8.nextTask === "WBV2-P9-000");
|
||||
assert.equal(p8Report.decision.status, "READY_WITH_AUTHORIZED_REBASELINE"); assert.equal(p8Report.decision.fullHistoricalReproduction, false);
|
||||
for (const artifact of Object.values(p8.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
|
||||
const basePlan = readJson("tests/golden/WBV2-P8-004/recovery-task-plan.json");
|
||||
assert.equal(basePlan.recoveryRoot, "WBV2-P8-000");
|
||||
const tasks = basePlan.tasks.map((task) => ({ ...task, ready: false }));
|
||||
const p9 = [
|
||||
{ id: "WBV2-P9-000", phase: "P9", title: "authorize_feature_parity_continuation", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P8-004"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p9-governance", gate: "G6", card: "docs/tasks/WBV2-P9-000.md", behavior: "Authorize feature parity continuation after provenance epoch 2 without claiming historical byte reproduction.", outputs: ["continuation receipt", "feature parity plan", "scope limits"], acceptance: ["P8 provenance evidence remains exact", "authorized baseline is explicit", "one feature task is active"], status: "done", ready: false, queueMutationAllowed: true },
|
||||
{ id: "WBV2-P9-001", phase: "P9", title: "mesh_production_chromium_receipt", kind: "feature", owner: "MESH", dependsOn: ["WBV2-P9-000"], parityId: "CAP-MESH-POSITIVE-EDIT", implementationClass: "LOCAL_EXACT", parallelGroup: "p9-mesh", gate: "G6", card: "docs/tasks/WBV2-P9-001.md", behavior: "Bind the existing Mesh Main transaction to a production Chromium desktop/WASM/save-reopen receipt.", outputs: ["Chromium mesh receipt", "negative matrix", "manifest"], acceptance: ["real meshTranslateVertex command passes", "desktop/WASM delta matches", "save/reopen is exact", "malformed/stale/unknown inputs fail closed"], status: "in_progress", ready: true, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P9-002", phase: "P9", title: "modifier_production_chromium_receipt", kind: "feature", owner: "MODIFIER", dependsOn: ["WBV2-P9-001"], parityId: "CAP-MODIFIER-STATE-MUTATION", implementationClass: "LOCAL_EXACT", parallelGroup: "p9-modifier", gate: "G6", card: "docs/tasks/WBV2-P9-002.md", behavior: "Bind the existing Modifier Main transaction to a production Chromium receipt.", outputs: ["Chromium modifier receipt", "negative matrix", "manifest"], acceptance: ["real modifierSetEnabled command passes", "desktop/WASM delta matches", "save/reopen is exact"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P9-003", phase: "P9", title: "asset_catalog_production_chromium_receipt", kind: "feature", owner: "ASSET", dependsOn: ["WBV2-P9-002"], parityId: "CAP-ASSET-CATALOG-MUTATION", implementationClass: "LOCAL_EXACT", parallelGroup: "p9-asset", gate: "G6", card: "docs/tasks/WBV2-P9-003.md", behavior: "Bind the existing Asset Catalog Main transaction and resource resolver to a production Chromium receipt.", outputs: ["Chromium asset receipt", "negative matrix", "manifest"], acceptance: ["real assetCatalogAppend command passes", "resource hash is bound", "save/reopen is exact"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P9-004", phase: "P9", title: "recompute_feature_parity_gate", kind: "enabling", owner: "RELEASE", dependsOn: ["WBV2-P9-003"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p9-release", gate: "G7", card: "docs/tasks/WBV2-P9-004.md", behavior: "Recompute declared feature parity claims from production Chromium receipts and authorized provenance.", outputs: ["feature parity gate", "limited release declaration", "manifest"], acceptance: ["only evidenced feature claims are emitted", "authorized baseline remains explicit", "full historical reproduction remains false"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
];
|
||||
const plan = { ...basePlan, planId: "BLENDER_WEB_PARITY_V2_FEATURE_EPOCH_1", recoveryRoot: "WBV2-P9-000", parentRecoveryPlan: { path: "tests/golden/WBV2-P8-004/recovery-task-plan.json", sha256: sha256("tests/golden/WBV2-P8-004/recovery-task-plan.json") }, tasks: [...tasks, ...p9] };
|
||||
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true }); fs.writeFileSync(absolute(planPath), `${JSON.stringify(plan, null, 2)}\n`);
|
||||
const report = { schemaVersion: 1, task: "WBV2-P9-000", operation: "AUTHORIZE_FEATURE_PARITY_CONTINUATION", status: "PASS", parent: { task: p8.task, manifest: p8ManifestPath, manifestSha256: sha256(p8ManifestPath), previousDecision: p8Report.decision.status, fullHistoricalReproduction: p8Report.decision.fullHistoricalReproduction }, continuation: { root: "WBV2-P9-000", firstTask: "WBV2-P9-001", plannedTasks: 5, scope: ["MESH", "MODIFIER", "ASSET_CATALOG"], browser: "chromium" }, policy: { historicalEvidencePreserved: true, authorizedRebaselineAccepted: true, featureParityClaimsRemainEvidenceBound: true, fullHistoricalReproduction: false }, nextTask: "WBV2-P9-001" };
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
||||
const rootCard = `# WBV2-P9-000: feature parity continuation root\n\n- task: WBV2-P9-000\n- parent: WBV2-P8-004\n- status: done\n- gap: workflow:authorize_feature_parity_continuation\n- ownerFamily: PROGRAM\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nAuthorize the next feature-parity evidence epoch after provenance epoch 2. The release scope remains authorized rebaseline only.\n\n## 验收\n\nnode tools/web/generate-wbv2-feature-parity-root.mjs\nnode tools/web/check-execution-control-plane.mjs\nnode tools/web/check-v2-task-index.mjs\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P9-000/\`\n- Manifest: \`tests/golden/WBV2-P9-000/manifest.json\`\n- Rollback: restore P8-004 as queue parent without changing provenance evidence.\n`;
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P9-000.md"), rootCard);
|
||||
const activeCard = `# WBV2-P9-001: Mesh production Chromium receipt\n\n- task: WBV2-P9-001\n- parent: WBV2-P9-000\n- status: in_progress\n- gap: workflow:mesh_production_chromium_receipt\n- ownerFamily: MESH\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind the real Mesh Main transaction to a production Chromium desktop/WASM/save-reopen receipt using the existing source implementation.\n\n## 输入与范围\n\n- Existing Mesh protocol: \`web/protocol/corrective-mesh-command.ts\`\n- Existing exact pilot: \`tests/golden/corrective/C4-002/receipt-report.json\`\n- Chromium test: \`web/tests/e2e/wbv2-mesh-production.spec.ts\`\n\n## 验收\n\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-mesh-production.spec.ts\`\n- \`node tools/web/generate-wbv2-mesh-receipt.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P9-001 --write\`\n\nMalformed, stale-revision, unknown-vertex, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P9-001/\`\n- Status: \`docs/status/WBV2-P9-001.md\`\n- Manifest: \`tests/golden/WBV2-P9-001/manifest.json\`\n- Rollback: restore P9-000 as queue parent without modifying P8 evidence.\n`;
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P9-001.md"), activeCard);
|
||||
const rootStatus = `# WBV2-P9-000 status\n\n- task: \`WBV2-P9-000\`; parent: \`WBV2-P8-004\`; status: \`done\`\n- nextTask: \`WBV2-P9-001\`\n\nFeature parity continuation is authorized after provenance epoch 2. Work is limited to evidenced Mesh, Modifier, and Asset Catalog behavior in Chromium; full historical reproduction remains false.\n`;
|
||||
fs.mkdirSync(absolute("docs/status"), { recursive: true }); fs.writeFileSync(absolute("docs/status/WBV2-P9-000.md"), rootStatus);
|
||||
|
||||
// Authorize the continuation on the prior gate without changing its evidence
|
||||
// classification or historical provenance claims.
|
||||
p8.nextTask = "WBV2-P9-000"; p8.continuation = { authorized: true, root: "WBV2-P9-000", scope: "FEATURE_PARITY_ONLY" };
|
||||
p8Report.nextTask = "WBV2-P9-000"; p8Report.decision.nextTask = "WBV2-P9-000"; p8Report.negative.queueAdvance = "AUTHORIZED_CONTINUATION";
|
||||
const currentP8Status = fs.readFileSync(absolute(p8StatusPath), "utf8").trim();
|
||||
const p8Status = currentP8Status.includes("authorized continuation: `WBV2-P9-000`")
|
||||
? `${currentP8Status}\n`
|
||||
: `${currentP8Status}\n- authorized continuation: \`WBV2-P9-000\`\n\nFeature parity work may continue under a new manifest root. This does not change the authorized-rebaseline-only release scope or historical reproduction limitation.\n`;
|
||||
fs.writeFileSync(absolute(p8ReportPath), `${JSON.stringify(p8Report, null, 2)}\n`); fs.writeFileSync(absolute(p8StatusPath), p8Status);
|
||||
fs.writeFileSync(absolute(p8ManifestPath), `${JSON.stringify(p8, null, 2)}\n`);
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P8-004", "--write"], { cwd: root, stdio: "pipe" });
|
||||
const p8Artifacts = Object.fromEntries(Object.entries(p8.artifacts).map(([name, artifact]) => [name, { ...artifact, sha256: sha256(artifact.path) }])); p8.artifacts = p8Artifacts; fs.writeFileSync(absolute(p8ManifestPath), `${JSON.stringify(p8, null, 2)}\n`);
|
||||
|
||||
const rootArtifactPaths = { parentManifest: p8ManifestPath, parentReport: p8ReportPath, approval: "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json", plan: planPath, report: reportPath, rootCard: "docs/tasks/WBV2-P9-000.md", rootStatus: "docs/status/WBV2-P9-000.md", activeCard: "docs/tasks/WBV2-P9-001.md" };
|
||||
const artifacts = Object.fromEntries(Object.entries(rootArtifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
|
||||
const manifest = { schemaVersion: 1, task: "WBV2-P9-000", parentTask: "WBV2-P8-004", operation: "AUTHORIZE_FEATURE_PARITY_CONTINUATION", status: "done", enablingTask: true, parityStateChange: false, artifacts, assertions: { authorizedRebaseline: true, fullHistoricalReproduction: false, featureParityScope: ["MESH", "MODIFIER", "ASSET_CATALOG"] }, nextTask: "WBV2-P9-001" };
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", planPath], { cwd: root, stdio: "inherit" });
|
||||
let queue = fs.readFileSync(absolute("docs/EXECUTION_QUEUE.md"), "utf8"); queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P9-001` |").replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P9-000/manifest.json` |").replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P9-001.md`](tasks/WBV2-P9-001.md) |"); fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
process.stdout.write(`wbv2-feature-parity-root-ok root=WBV2-P9-000 next=WBV2-P9-001 scope=MESH,MODIFIER,ASSET_CATALOG\n`);
|
||||
172
tools/web/generate-wbv2-mesh-receipt.mjs
Normal file
172
tools/web/generate-wbv2-mesh-receipt.mjs
Normal file
@@ -0,0 +1,172 @@
|
||||
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-P9-001";
|
||||
const chromiumPath = `${outputRoot}/chromium-mesh-production.json`;
|
||||
const chromiumSecondPath = `${outputRoot}/chromium-mesh-production.second.json`;
|
||||
const reportPath = `${outputRoot}/mesh-receipt-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P9-001.md";
|
||||
const planPath = `${outputRoot}/feature-parity-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentManifestPath = "tests/golden/WBV2-P9-000/manifest.json";
|
||||
const sourceManifestPath = "tests/golden/WBV2-P2-003/manifest.json";
|
||||
const sourceReportPath = "tests/golden/WBV2-P2-003/mesh-edit-report.json";
|
||||
|
||||
const parent = readJson(parentManifestPath);
|
||||
assert.equal(parent.task, "WBV2-P9-000");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P9-001");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
|
||||
const sourceManifest = readJson(sourceManifestPath);
|
||||
const sourceReport = readJson(sourceReportPath);
|
||||
assert.equal(sourceManifest.task, "WBV2-P2-003");
|
||||
assert.equal(sourceManifest.status, "done");
|
||||
assert.equal(sourceReport.task, "WBV2-P2-003");
|
||||
assert.equal(sourceReport.desktop.status, "EXACT");
|
||||
assert.equal(sourceReport.wasm.status, "EXACT");
|
||||
assert.equal(sourceReport.desktop.saveReopen, "EXACT");
|
||||
assert.equal(sourceReport.saveReopen, "EXACT");
|
||||
const sourceBound = Object.values(sourceManifest.artifacts ?? {}).find((artifact) => artifact.path === sourceReportPath);
|
||||
assert.ok(sourceBound, "P2-003 source report is not manifest-bound");
|
||||
assert.equal(sourceBound.sha256, sha256(sourceReportPath));
|
||||
|
||||
assert.equal(sha256(chromiumPath), sha256(chromiumSecondPath), "Chromium Mesh report is not deterministic");
|
||||
const chromium = readJson(chromiumPath);
|
||||
assert.equal(chromium.task, "WBV2-P9-001");
|
||||
assert.equal(chromium.operation, "MESH_PRODUCTION_CHROMIUM");
|
||||
assert.equal(chromium.browser, "chromium");
|
||||
assert.equal(chromium.queueMutation, false);
|
||||
assert.equal(chromium.positive.parity, true);
|
||||
for (const surface of ["desktop", "wasm"]) {
|
||||
const result = chromium.positive[surface];
|
||||
assert.equal(result.status, "FINISHED");
|
||||
assert.equal(result.code, "OK");
|
||||
assert.equal(result.mainRevisionBefore, 9);
|
||||
assert.equal(result.mainRevisionAfter, 10);
|
||||
assert.equal(result.mainMutation, "CHANGED");
|
||||
assert.deepEqual(result.delta, { vertexId: "vertex:0", before: { x: 1, y: 2, z: 3 }, after: { x: 1.5, y: 1, z: 5 } });
|
||||
}
|
||||
assert.deepEqual(chromium.positive.desktop, chromium.positive.wasm);
|
||||
assert.equal(chromium.persistence.exact, true);
|
||||
assert.deepEqual(chromium.persistence.reopened, chromium.persistence.saved);
|
||||
assert.equal(chromium.negative.malformed.code, "COMMAND_MALFORMED");
|
||||
assert.equal(chromium.negative.stale.code, "REVISION_CONFLICT");
|
||||
assert.equal(chromium.negative.unknown.code, "COMMAND_UNSUPPORTED");
|
||||
assert.equal(chromium.negative.rollbackMain.revision, 9);
|
||||
assert.equal(chromium.negative.rollbackMain.dirty, false);
|
||||
assert.deepEqual(chromium.negative.rollbackMain.value.vertices, [{ id: "vertex:0", x: 1, y: 2, z: 3 }, { id: "vertex:1", x: 0, y: 0, z: 0 }]);
|
||||
|
||||
const receipt = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P9-001",
|
||||
operation: "MESH_PRODUCTION_CHROMIUM_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
source: {
|
||||
task: "WBV2-P2-003",
|
||||
manifest: sourceManifestPath,
|
||||
manifestSha256: sha256(sourceManifestPath),
|
||||
report: sourceReportPath,
|
||||
reportSha256: sha256(sourceReportPath),
|
||||
exactDesktop: sourceReport.desktop.status === "EXACT",
|
||||
exactWasm: sourceReport.wasm.status === "EXACT",
|
||||
exactSaveReopen: sourceReport.saveReopen === "EXACT",
|
||||
},
|
||||
chromium: {
|
||||
report: chromiumPath,
|
||||
reportSha256: sha256(chromiumPath),
|
||||
secondReport: chromiumSecondPath,
|
||||
secondReportSha256: sha256(chromiumSecondPath),
|
||||
deterministic: true,
|
||||
surfaces: ["DESKTOP", "WASM"],
|
||||
positive: { desktop: chromium.positive.desktop, wasm: chromium.positive.wasm, parity: chromium.positive.parity },
|
||||
negative: { malformed: chromium.negative.malformed, stale: chromium.negative.stale, unknown: chromium.negative.unknown },
|
||||
persistence: { exact: chromium.persistence.exact, saved: chromium.persistence.saved, reopened: chromium.persistence.reopened },
|
||||
},
|
||||
assertions: {
|
||||
realMeshTranslateVertex: true,
|
||||
desktopWasmDeltaMatch: true,
|
||||
saveReopenExact: true,
|
||||
failureMatrixClosed: true,
|
||||
featureParityClaim: "CAP-MESH-POSITIVE-EDIT",
|
||||
historicalReproduction: false,
|
||||
},
|
||||
nextTask: "WBV2-P9-002",
|
||||
};
|
||||
|
||||
if (!write) {
|
||||
process.stdout.write("wbv2-mesh-receipt-ok task=WBV2-P9-001 deterministic=true next=WBV2-P9-002\n");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(receipt, null, 2)}\n`);
|
||||
const status = `# WBV2-P9-001 status\n\n- task: \`WBV2-P9-001\`; parent: \`WBV2-P9-000\`; status: \`done\`\n- Mesh Chromium receipt: \`DESKTOP + WASM\`\n- delta: \`(0.5, -1, 2)\`; revision: \`9 -> 10\`\n- save/reopen: \`EXACT\`\n- nextTask: \`WBV2-P9-002\`\n\nThe production Chromium receipt executes the existing Mesh Main transaction on both browser surfaces. Malformed, stale-revision, and unknown-vertex commands are rejected without mutating the Main. This is a bounded current implementation claim and does not assert historical byte reproduction.\n`;
|
||||
fs.writeFileSync(absolute(statusPath), status);
|
||||
|
||||
const previousPlan = readJson("tests/golden/WBV2-P9-000/feature-parity-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P9-000/feature-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P9-000/feature-parity-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P9-001"
|
||||
? { ...task, status: "done", ready: false }
|
||||
: task.id === "WBV2-P9-002"
|
||||
? { ...task, status: "in_progress", ready: true }
|
||||
: { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
|
||||
const nextCard = `# WBV2-P9-002: Modifier production Chromium receipt\n\n- task: WBV2-P9-002\n- parent: WBV2-P9-001\n- status: in_progress\n- gap: workflow:modifier_production_chromium_receipt\n- ownerFamily: MODIFIER\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind the real Modifier Main transaction to a production Chromium desktop/WASM/save-reopen receipt using the existing source implementation.\n\n## 输入与范围\n\n- Existing Modifier protocol: \`web/protocol/corrective-modifier-command.ts\`\n- Existing exact pilot: \`tests/golden/corrective/C4-001/receipt-report.json\`\n- Chromium test: \`web/tests/e2e/wbv2-modifier-production.spec.ts\`\n\n## 验收\n\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-production.spec.ts\`\n- \`node tools/web/generate-wbv2-modifier-receipt.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P9-002 --write\`\n\nMalformed, stale-revision, unknown-modifier, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P9-002/\`\n- Status: \`docs/status/WBV2-P9-002.md\`\n- Manifest: \`tests/golden/WBV2-P9-002/manifest.json\`\n- Rollback: restore P9-001 as queue parent without modifying Mesh or P8 evidence.\n`;
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P9-002.md"), nextCard);
|
||||
|
||||
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-P9-001", "--write"], { cwd: root, stdio: "inherit" });
|
||||
|
||||
const artifactPaths = {
|
||||
parentManifest: parentManifestPath,
|
||||
sourceManifest: sourceManifestPath,
|
||||
sourceReport: sourceReportPath,
|
||||
chromiumReport: chromiumPath,
|
||||
chromiumSecondReport: chromiumSecondPath,
|
||||
e2e: "web/tests/e2e/wbv2-mesh-production.spec.ts",
|
||||
protocol: "web/protocol/corrective-mesh-command.ts",
|
||||
bridge: "web/app/src/corrective-pilot-bridge.ts",
|
||||
generator: "tools/web/generate-wbv2-mesh-receipt.mjs",
|
||||
report: reportPath,
|
||||
status: statusPath,
|
||||
featureParityPlan: planPath,
|
||||
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-P9-001",
|
||||
parentTask: "WBV2-P9-000",
|
||||
operation: "MESH_PRODUCTION_CHROMIUM_RECEIPT",
|
||||
status: "done",
|
||||
enablingTask: false,
|
||||
parityStateChange: true,
|
||||
runtime: "PLAYWRIGHT_CHROMIUM_DESKTOP_AND_WASM",
|
||||
artifacts,
|
||||
assertions: { capabilityId: "CAP-MESH-POSITIVE-EDIT", browser: "chromium", surfaces: 2, deterministic: true, saveReopen: "EXACT", negativeCases: 3, historicalReproduction: false },
|
||||
nextTask: "WBV2-P9-002",
|
||||
};
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-v2-task-index.mjs")], { cwd: root, stdio: "pipe" });
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P9-002` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P9-001/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P9-002.md`](tasks/WBV2-P9-002.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
process.stdout.write(`wbv2-mesh-receipt-written task=WBV2-P9-001 surfaces=2 deterministic=true next=WBV2-P9-002 artifacts=${Object.keys(artifacts).length}\n`);
|
||||
173
tools/web/generate-wbv2-modifier-receipt.mjs
Normal file
173
tools/web/generate-wbv2-modifier-receipt.mjs
Normal file
@@ -0,0 +1,173 @@
|
||||
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-P9-002";
|
||||
const chromiumPath = `${outputRoot}/chromium-modifier-production.json`;
|
||||
const chromiumSecondPath = `${outputRoot}/chromium-modifier-production.second.json`;
|
||||
const reportPath = `${outputRoot}/modifier-receipt-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P9-002.md";
|
||||
const planPath = `${outputRoot}/feature-parity-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentManifestPath = "tests/golden/WBV2-P9-001/manifest.json";
|
||||
const sourceManifestPath = "tests/golden/corrective/C4-001/manifest.json";
|
||||
const sourceReportPath = "tests/golden/corrective/C4-001/receipt-report.json";
|
||||
|
||||
const parent = readJson(parentManifestPath);
|
||||
assert.equal(parent.task, "WBV2-P9-001");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P9-002");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
|
||||
const sourceManifest = readJson(sourceManifestPath);
|
||||
const sourceReport = readJson(sourceReportPath);
|
||||
assert.equal(sourceManifest.task, "C4-001");
|
||||
assert.equal(sourceManifest.status, "done");
|
||||
assert.equal(sourceReport.task, "C4-001");
|
||||
assert.equal(sourceReport.browser, "chromium");
|
||||
assert.equal(sourceReport.queueMutation, false);
|
||||
assert.equal(sourceReport.parity, true);
|
||||
assert.equal(sourceReport.positive.desktop.status, "FINISHED");
|
||||
assert.equal(sourceReport.positive.wasm.status, "FINISHED");
|
||||
assert.equal(sourceReport.persistence.reopened.dirty, false);
|
||||
const sourceBound = Object.values(sourceManifest.artifacts ?? {}).find((artifact) => artifact.path === sourceReportPath);
|
||||
assert.ok(sourceBound, "C4-001 source report is not manifest-bound");
|
||||
assert.equal(sourceBound.sha256, sha256(sourceReportPath));
|
||||
|
||||
assert.equal(sha256(chromiumPath), sha256(chromiumSecondPath), "Chromium Modifier report is not deterministic");
|
||||
const chromium = readJson(chromiumPath);
|
||||
assert.equal(chromium.task, "WBV2-P9-002");
|
||||
assert.equal(chromium.operation, "MODIFIER_PRODUCTION_CHROMIUM");
|
||||
assert.equal(chromium.browser, "chromium");
|
||||
assert.equal(chromium.queueMutation, false);
|
||||
assert.equal(chromium.positive.parity, true);
|
||||
for (const surface of ["desktop", "wasm"]) {
|
||||
const result = chromium.positive[surface];
|
||||
assert.equal(result.status, "FINISHED");
|
||||
assert.equal(result.code, "OK");
|
||||
assert.equal(result.mainRevisionBefore, 7);
|
||||
assert.equal(result.mainRevisionAfter, 8);
|
||||
assert.equal(result.mainMutation, "CHANGED");
|
||||
assert.deepEqual(result.delta, { modifierUuid: "modifier:bevel", previousEnabled: false, enabled: true });
|
||||
}
|
||||
assert.deepEqual(chromium.positive.desktop, chromium.positive.wasm);
|
||||
assert.equal(chromium.persistence.exact, true);
|
||||
assert.deepEqual(chromium.persistence.reopened, chromium.persistence.saved);
|
||||
assert.equal(chromium.negative.malformed.code, "COMMAND_MALFORMED");
|
||||
assert.equal(chromium.negative.stale.code, "REVISION_CONFLICT");
|
||||
assert.equal(chromium.negative.unknown.code, "COMMAND_UNSUPPORTED");
|
||||
assert.equal(chromium.negative.rollbackMain.revision, 7);
|
||||
assert.equal(chromium.negative.rollbackMain.dirty, false);
|
||||
assert.deepEqual(chromium.negative.rollbackMain.value.modifiers, [{ uuid: "modifier:bevel", name: "Pilot Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }]);
|
||||
|
||||
const receipt = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P9-002",
|
||||
operation: "MODIFIER_PRODUCTION_CHROMIUM_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
source: {
|
||||
task: "C4-001",
|
||||
manifest: sourceManifestPath,
|
||||
manifestSha256: sha256(sourceManifestPath),
|
||||
report: sourceReportPath,
|
||||
reportSha256: sha256(sourceReportPath),
|
||||
exactChromiumPilot: true,
|
||||
exactSaveReopen: true,
|
||||
},
|
||||
chromium: {
|
||||
report: chromiumPath,
|
||||
reportSha256: sha256(chromiumPath),
|
||||
secondReport: chromiumSecondPath,
|
||||
secondReportSha256: sha256(chromiumSecondPath),
|
||||
deterministic: true,
|
||||
surfaces: ["DESKTOP", "WASM"],
|
||||
positive: { desktop: chromium.positive.desktop, wasm: chromium.positive.wasm, parity: chromium.positive.parity },
|
||||
negative: { malformed: chromium.negative.malformed, stale: chromium.negative.stale, unknown: chromium.negative.unknown },
|
||||
persistence: { exact: chromium.persistence.exact, saved: chromium.persistence.saved, reopened: chromium.persistence.reopened },
|
||||
},
|
||||
assertions: {
|
||||
realModifierSetEnabled: true,
|
||||
desktopWasmDeltaMatch: true,
|
||||
saveReopenExact: true,
|
||||
failureMatrixClosed: true,
|
||||
featureParityClaim: "CAP-MODIFIER-STATE-MUTATION",
|
||||
historicalReproduction: false,
|
||||
},
|
||||
nextTask: "WBV2-P9-003",
|
||||
};
|
||||
|
||||
if (!write) {
|
||||
process.stdout.write("wbv2-modifier-receipt-ok task=WBV2-P9-002 deterministic=true next=WBV2-P9-003\n");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(receipt, null, 2)}\n`);
|
||||
const status = `# WBV2-P9-002 status\n\n- task: \`WBV2-P9-002\`; parent: \`WBV2-P9-001\`; status: \`done\`\n- Modifier Chromium receipt: \`DESKTOP + WASM\`\n- enabled transition: \`false -> true\`; revision: \`7 -> 8\`\n- save/reopen: \`EXACT\`\n- nextTask: \`WBV2-P9-003\`\n\nThe production Chromium receipt executes the existing Modifier Main transaction on both browser surfaces. Malformed, stale-revision, and unknown-modifier commands are rejected without mutating the Main. This is a bounded current implementation claim and does not assert historical byte reproduction.\n`;
|
||||
fs.writeFileSync(absolute(statusPath), status);
|
||||
|
||||
const previousPlan = readJson("tests/golden/WBV2-P9-001/feature-parity-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P9-001/feature-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P9-001/feature-parity-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P9-002"
|
||||
? { ...task, status: "done", ready: false }
|
||||
: task.id === "WBV2-P9-003"
|
||||
? { ...task, status: "in_progress", ready: true }
|
||||
: { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
|
||||
const nextCard = `# WBV2-P9-003: Asset Catalog production Chromium receipt\n\n- task: WBV2-P9-003\n- parent: WBV2-P9-002\n- status: in_progress\n- gap: workflow:asset_catalog_production_chromium_receipt\n- ownerFamily: ASSET\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind the real Asset Catalog Main transaction and resource resolver to a production Chromium desktop/WASM/save-reopen receipt using the existing source implementation.\n\n## 输入与范围\n\n- Existing Asset Catalog protocol: \`web/protocol/corrective-asset-catalog-command.ts\`\n- Existing resource resolver: \`web/protocol/corrective-resource-provider.ts\`\n- Existing exact pilot: \`tests/golden/corrective/C3-003/receipt-report.json\`\n- Chromium test: \`web/tests/e2e/wbv2-asset-catalog-production.spec.ts\`\n\n## 验收\n\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-asset-catalog-production.spec.ts\`\n- \`node tools/web/generate-wbv2-asset-catalog-receipt.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P9-003 --write\`\n\nMalformed, stale-revision, unknown-asset, missing-resource, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P9-003/\`\n- Status: \`docs/status/WBV2-P9-003.md\`\n- Manifest: \`tests/golden/WBV2-P9-003/manifest.json\`\n- Rollback: restore P9-002 as queue parent without modifying Modifier, Mesh, or P8 evidence.\n`;
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P9-003.md"), nextCard);
|
||||
|
||||
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-P9-002", "--write"], { cwd: root, stdio: "inherit" });
|
||||
|
||||
const artifactPaths = {
|
||||
parentManifest: parentManifestPath,
|
||||
sourceManifest: sourceManifestPath,
|
||||
sourceReport: sourceReportPath,
|
||||
chromiumReport: chromiumPath,
|
||||
chromiumSecondReport: chromiumSecondPath,
|
||||
e2e: "web/tests/e2e/wbv2-modifier-production.spec.ts",
|
||||
protocol: "web/protocol/corrective-modifier-command.ts",
|
||||
bridge: "web/app/src/corrective-pilot-bridge.ts",
|
||||
generator: "tools/web/generate-wbv2-modifier-receipt.mjs",
|
||||
report: reportPath,
|
||||
status: statusPath,
|
||||
featureParityPlan: planPath,
|
||||
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-P9-002",
|
||||
parentTask: "WBV2-P9-001",
|
||||
operation: "MODIFIER_PRODUCTION_CHROMIUM_RECEIPT",
|
||||
status: "done",
|
||||
enablingTask: false,
|
||||
parityStateChange: true,
|
||||
runtime: "PLAYWRIGHT_CHROMIUM_DESKTOP_AND_WASM",
|
||||
artifacts,
|
||||
assertions: { capabilityId: "CAP-MODIFIER-STATE-MUTATION", browser: "chromium", surfaces: 2, deterministic: true, saveReopen: "EXACT", negativeCases: 3, historicalReproduction: false },
|
||||
nextTask: "WBV2-P9-003",
|
||||
};
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P9-003` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P9-002/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P9-003.md`](tasks/WBV2-P9-003.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-v2-task-index.mjs")], { cwd: root, stdio: "pipe" });
|
||||
process.stdout.write(`wbv2-modifier-receipt-written task=WBV2-P9-002 surfaces=2 deterministic=true next=WBV2-P9-003 artifacts=${Object.keys(artifacts).length}\n`);
|
||||
Reference in New Issue
Block a user