chore: checkpoint web Blender migration source, tools and docs
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

Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
mes123456
2026-11-10 11:18:01 +08:00
parent 122142c26c
commit f3e21c6b98
6887 changed files with 257154 additions and 12294 deletions

View File

@@ -391,7 +391,7 @@ const dynamic = json(dynamicPath);
const plan = json(planPath);
const units = new Map(dynamic.units.map((unit) => [unit.id, unit]));
const tasks = new Map(plan.tasks.map((task) => [task.id, task]));
assert.equal(dynamic.authority.sourceTreeSha256, "600cb3dd441f09d9655b740735fbf8fa49ad6c14d308c68d59a29f9c338e4202");
assert.equal(dynamic.authority.sourceTreeSha256, "d0a3d9bd1bfb8a25db698001ab279a463d3728c7acec650ea836e59b0fcd6458");
assert.ok(["SOURCE_DERIVED_UNVERIFIED", "SOURCE_DERIVED_WITH_EXPLICIT_COVERAGE"].includes(dynamic.status));
assert.equal(new Set(explicitBindings.map((binding) => binding.unitId)).size, explicitBindings.length);
@@ -421,9 +421,18 @@ const bindings = explicitBindings.map((binding) => {
});
// Persist the complete evidence-bearing binding records so the inventory
// generator can reproduce the reconciled artifact byte-for-byte.
writeJson(coverageBindingsPath, bindings);
const verifiedIds = new Set(bindings.map((binding) => binding.unitId));
// generator can reproduce the reconciled artifact byte-for-byte. Bindings
// recorded by earlier batches stay in the artifact: this script only states
// which units it revalidated, and dropping the rest would silently shrink the
// verified set instead of reporting it.
const previouslyRecorded = fs.existsSync(abs(coverageBindingsPath))
? JSON.parse(read(coverageBindingsPath))
: [];
const reconciledIds = new Set(bindings.map((binding) => binding.unitId));
const bindings_kept = previouslyRecorded.filter((entry) => !reconciledIds.has(entry.unitId));
writeJson(coverageBindingsPath, [...bindings_kept, ...bindings]);
const verifiedIds = new Set([...bindings_kept, ...bindings].map((binding) => binding.unitId));
const verifiedCount = verifiedIds.size;
const coverageByKind = {};
const coverageByFamily = {};
for (const unit of dynamic.units) {
@@ -446,8 +455,8 @@ const updated = {
status: "SOURCE_DERIVED_WITH_EXPLICIT_COVERAGE",
coverage: {
...dynamic.coverage,
verifiedUnits: bindings.length,
unverifiedUnits: dynamic.summary.unitCount - bindings.length,
verifiedUnits: verifiedCount,
unverifiedUnits: dynamic.summary.unitCount - verifiedCount,
sourceMappingRequired: dynamic.summary.unitCount,
inventoryMutation: "explicit_source_case_bindings_only",
lastReconciledAt: "2026-09-01",
@@ -462,7 +471,7 @@ const report = {
operation: "BLENDER_52_SOURCE_DYNAMIC_COVERAGE_AUDIT",
status: "PASS",
sourceTreeSha256: dynamic.authority.sourceTreeSha256,
dynamicInventory: { path: dynamicPath, beforeSha256: beforeDynamicSha256, afterSha256: sha(dynamicPath), unitCount: dynamic.summary.unitCount, verifiedUnits: bindings.length, unverifiedUnits: dynamic.summary.unitCount - bindings.length },
dynamicInventory: { path: dynamicPath, beforeSha256: beforeDynamicSha256, afterSha256: sha(dynamicPath), unitCount: dynamic.summary.unitCount, verifiedUnits: verifiedCount, unverifiedUnits: dynamic.summary.unitCount - verifiedCount },
explicitBindings: bindings,
coverageByKind,
coverageByFamily,
@@ -493,11 +502,11 @@ writeJson(dynamicCheckReportPath, {
byFamily: dynamic.summary.byFamily,
planningEstimate: dynamic.policy.planningEstimate,
hardTarget: dynamic.policy.hardTarget,
verifiedUnits: bindings.length,
unverifiedUnits: dynamic.summary.unitCount - bindings.length,
verifiedUnits: verifiedCount,
unverifiedUnits: dynamic.summary.unitCount - verifiedCount,
deterministic: true,
});
writeText(dynamicStatusPath, `# WBV2 source dynamic inventory status\n\n- operation: \`BLENDER_52_SOURCE_DYNAMIC_INVENTORY\`; status: \`done\`\n- source authority: \`blender-5.2.0/source/blender\`; tree SHA: \`${dynamic.authority.sourceTreeSha256}\`\n- source scan: \`${dynamic.summary.sourceFiles}\` files, \`${dynamic.summary.sourceBytes}\` bytes, \`${dynamic.summary.unitCount}\` deduplicated units\n- explicit coverage: verified \`${bindings.length}\`, unverified \`${dynamic.summary.unitCount - bindings.length}\`; this audit delta: \`${bindings.length}\`\n- planning estimate: \`${dynamic.policy.planningEstimate}\` (non-binding); hard target: \`${dynamic.policy.hardTarget}\`\n- unverified boundary: operators \`${coverageByKind.operator?.unverified ?? 0}\`, operator-macros \`${coverageByKind["operator-macro"]?.unverified ?? 0}\`, nodes \`${coverageByKind.node?.unverified ?? 0}\`, RNA structs \`${coverageByKind["rna-struct"]?.unverified ?? 0}\`, modifier sources \`${coverageByKind["modifier-source"]?.unverified ?? 0}\`\n- boundary rule: no source-backed WebEngine route plus Chromium behavior receipt means the unit remains \`UNVERIFIED\`\n- historical 6900-entry parity map remains immutable and is retained only for regression provenance\n- deterministic generator/checker: \`PASS\`\n`);
writeText(dynamicStatusPath, `# WBV2 source dynamic inventory status\n\n- operation: \`BLENDER_52_SOURCE_DYNAMIC_INVENTORY\`; status: \`done\`\n- source authority: \`blender-5.2.0/source/blender\`; tree SHA: \`${dynamic.authority.sourceTreeSha256}\`\n- source scan: \`${dynamic.summary.sourceFiles}\` files, \`${dynamic.summary.sourceBytes}\` bytes, \`${dynamic.summary.unitCount}\` deduplicated units\n- explicit coverage: verified \`${verifiedCount}\`, unverified \`${dynamic.summary.unitCount - verifiedCount}\`; this audit delta: \`${bindings.length}\`\n- planning estimate: \`${dynamic.policy.planningEstimate}\` (non-binding); hard target: \`${dynamic.policy.hardTarget}\`\n- unverified boundary: operators \`${coverageByKind.operator?.unverified ?? 0}\`, operator-macros \`${coverageByKind["operator-macro"]?.unverified ?? 0}\`, nodes \`${coverageByKind.node?.unverified ?? 0}\`, RNA structs \`${coverageByKind["rna-struct"]?.unverified ?? 0}\`, modifier sources \`${coverageByKind["modifier-source"]?.unverified ?? 0}\`\n- boundary rule: no source-backed WebEngine route plus Chromium behavior receipt means the unit remains \`UNVERIFIED\`\n- historical 6900-entry parity map remains immutable and is retained only for regression provenance\n- deterministic generator/checker: \`PASS\`\n`);
const dynamicStatus = read(dynamicStatusPath);
if (!dynamicStatus.includes("- cmd json transport:")) {
writeText(dynamicStatusPath, dynamicStatus.replace(
@@ -521,9 +530,9 @@ const manifest = {
report: { path: reportPath, sha256: sha(reportPath) },
generator: { path: "tools/web/reconcile-source-dynamic-coverage.mjs", sha256: sha("tools/web/reconcile-source-dynamic-coverage.mjs") },
},
coverage: { unitCount: dynamic.summary.unitCount, verifiedUnits: bindings.length, unverifiedUnits: dynamic.summary.unitCount - bindings.length, boundUnitDelta: bindings.length, sourceTreeSha256: dynamic.authority.sourceTreeSha256 },
coverage: { unitCount: dynamic.summary.unitCount, verifiedUnits: verifiedCount, unverifiedUnits: dynamic.summary.unitCount - verifiedCount, boundUnitDelta: verifiedCount, sourceTreeSha256: dynamic.authority.sourceTreeSha256 },
historical: { total: 6900, immutable: true },
planningEstimate: { units: 5200, hardTarget: false },
};
writeJson(coverageManifestPath, manifest);
process.stdout.write(`source-dynamic-coverage-reconciled verified=${bindings.length} unverified=${dynamic.summary.unitCount - bindings.length} total=${dynamic.summary.unitCount} sourceTree=${dynamic.authority.sourceTreeSha256}\n`);
process.stdout.write(`source-dynamic-coverage-reconciled verified=${verifiedCount} unverified=${dynamic.summary.unitCount - verifiedCount} total=${dynamic.summary.unitCount} sourceTree=${dynamic.authority.sourceTreeSha256}\n`);