docs(web): publish detailed feature completeness audit
This commit is contained in:
80
tools/web/audit-wbv2-feature-completeness.mjs
Normal file
80
tools/web/audit-wbv2-feature-completeness.mjs
Normal file
@@ -0,0 +1,80 @@
|
||||
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 readJson = (relative) => JSON.parse(fs.readFileSync(path.join(root, relative), "utf8"));
|
||||
const sha = (relative) => crypto.createHash("sha256").update(fs.readFileSync(path.join(root, relative))).digest("hex");
|
||||
const report = readJson("tests/golden/WBV2-P1424-001/product-implementation-report.json");
|
||||
const catalog = readJson("web/app/src/capabilities/blender-feature-route-catalog.json");
|
||||
const smokePlan = readJson("tests/golden/WBV2/feature-smoke-plan.json");
|
||||
const smokeReport = readJson("tests/golden/WBV2/feature-smoke-report.json");
|
||||
const smokeFix = readJson("tests/golden/WBV2/feature-smoke-fix-report.json");
|
||||
const wasmManifest = readJson("web/app/public/wasm-module-manifest.json");
|
||||
|
||||
const countBy = (items, selector) => Object.fromEntries([...new Set(items.map(selector))].sort().map((key) => [key, items.filter((item) => selector(item) === key).length]));
|
||||
const unverified = catalog.entries.filter((entry) => entry.evidenceStatus === "UNVERIFIED");
|
||||
const failedSmoke = smokeReport.cases.filter((entry) => entry.status !== "PASS");
|
||||
const implementationResults = report.implementationTasks.map((task) => ({
|
||||
id: task.id,
|
||||
module: task.module,
|
||||
status: task.status,
|
||||
resultPath: task.resultPath ?? null,
|
||||
resultPresent: task.resultPath ? fs.existsSync(path.join(root, task.resultPath)) : false,
|
||||
}));
|
||||
const missingResults = implementationResults.filter((entry) => !entry.resultPresent);
|
||||
|
||||
const audit = {
|
||||
schemaVersion: 1,
|
||||
auditId: "WBV2-FEATURE-COMPLETENESS-001",
|
||||
operation: "DETAILED_MIGRATION_COMPLETENESS_AUDIT",
|
||||
status: missingResults.length || failedSmoke.length ? "PARTIAL_BLOCKED" : "IMPLEMENTATION_COMPLETE",
|
||||
implementation: {
|
||||
workflowModules: { total: report.workflowModules.length, implemented: report.workflowModules.filter((item) => item.status === "implemented").length },
|
||||
productTasks: { total: report.implementationTasks.length, implemented: report.implementationTasks.filter((item) => item.status === "implemented").length, missingResultFiles: missingResults },
|
||||
},
|
||||
routeCoverage: {
|
||||
unitCount: catalog.unitCount,
|
||||
classifiedCount: catalog.classifiedCount,
|
||||
unclassifiedCount: catalog.unclassifiedCount,
|
||||
counts: catalog.counts,
|
||||
unavailable: catalog.entries.filter((entry) => entry.route === "UNAVAILABLE").map((entry) => entry.id),
|
||||
byKind: countBy(catalog.entries, (entry) => entry.kind),
|
||||
byFamily: countBy(catalog.entries, (entry) => entry.family),
|
||||
},
|
||||
behavioralEvidence: {
|
||||
status: catalog.behavioralEvidence.status,
|
||||
verifiedUnits: catalog.behavioralEvidence.verifiedUnits,
|
||||
unverifiedUnits: catalog.behavioralEvidence.unverifiedUnits,
|
||||
unverifiedByKind: countBy(unverified, (entry) => entry.kind),
|
||||
unverifiedByFamily: countBy(unverified, (entry) => entry.family),
|
||||
rule: "route assignment is not behavioral completion",
|
||||
},
|
||||
smoke: {
|
||||
planId: smokePlan.planId,
|
||||
totalFeatures: smokePlan.cases.length,
|
||||
attempts: smokeReport.cases.reduce((sum, entry) => sum + Number(entry.attempts ?? 0), 0),
|
||||
passed: smokeReport.cases.filter((entry) => entry.status === "PASS").length,
|
||||
failedOrBlocked: failedSmoke,
|
||||
focusedFix: smokeFix.fixes,
|
||||
retries: smokeFix.retries,
|
||||
},
|
||||
wasmLifecycle: wasmManifest.modules.map((module) => ({ id: module.id, lifecycle: module.lifecycle, preload: module.preload, single: module.resources?.single?.fileName ?? null, pthread: module.resources?.pthread?.fileName ?? null })),
|
||||
actualMissingOrBlocked: [
|
||||
{ id: "IO_IMPORT_WASM_ARTIFACT", status: "BLOCKED", description: "importScene/exportScene is present in source/protocol but the checked-in WASM lacks the unified JSON route; rebuilding currently fails on Blender API/header drift.", evidence: "tests/golden/WBV2/feature-smoke-fix-report.json" },
|
||||
{ id: "BEHAVIORAL_EVIDENCE_OVERLAY", status: "DEFERRED", description: "2720 classified source units still lack exact behavioral receipts; they remain routed, not claimed verified.", evidence: "web/app/src/capabilities/blender-feature-route-catalog.json" },
|
||||
],
|
||||
nextWork: {
|
||||
priority: ["repair WebEngine source/API drift and rebuild source-matched WASM", "rerun only OPERATOR-ROUTE-PALETTE focused IO smoke", "then schedule batched evidence for unverified operators/RNA/macros/modifier units"],
|
||||
forbidden: ["do not rerun passed feature smoke cases", "do not mark route assignment as behavioral verification", "do not replace WASM with a simulated JS implementation"],
|
||||
},
|
||||
inputs: {
|
||||
productReportSha256: sha("tests/golden/WBV2-P1424-001/product-implementation-report.json"),
|
||||
routeCatalogSha256: sha("web/app/src/capabilities/blender-feature-route-catalog.json"),
|
||||
smokeReportSha256: sha("tests/golden/WBV2/feature-smoke-report.json"),
|
||||
},
|
||||
};
|
||||
const outputPath = path.join(root, "tests/golden/WBV2/feature-completeness-audit.json");
|
||||
fs.writeFileSync(outputPath, `${JSON.stringify(audit, null, 2)}\n`);
|
||||
process.stdout.write(`wbv2-feature-completeness-audit status=${audit.status} modules=${audit.implementation.workflowModules.implemented}/${audit.implementation.workflowModules.total} tasks=${audit.implementation.productTasks.implemented}/${audit.implementation.productTasks.total} routes=${audit.routeCoverage.classifiedCount}/${audit.routeCoverage.unitCount} verified=${audit.behavioralEvidence.verifiedUnits} unverified=${audit.behavioralEvidence.unverifiedUnits} smokePassed=${audit.smoke.passed}/${audit.smoke.totalFeatures} blocked=${audit.actualMissingOrBlocked.filter((item) => item.status === "BLOCKED").length}\n`);
|
||||
Reference in New Issue
Block a user