From b78e23b16cc32996becb5ad27b8a4ffd9e3b78ec Mon Sep 17 00:00:00 2001 From: mes123456 Date: Fri, 28 Aug 2026 00:46:58 +0800 Subject: [PATCH] Advance WBV2 through native engine module matrix --- docs/EXECUTION_QUEUE.md | 6 +- docs/status/WBV2-P10-000.md | 6 + docs/status/WBV2-P10-001.md | 9 + docs/status/WBV2-P10-002.md | 9 + docs/status/WBV2-P10-003.md | 9 + docs/status/WBV2-P9-004.md | 3 + docs/tasks/WBV2-P10-000.md | 24 + docs/tasks/WBV2-P10-001.md | 35 + docs/tasks/WBV2-P10-002.md | 43 + docs/tasks/WBV2-P10-003.md | 34 + tests/golden/WBV2-P10-000/manifest.json | 56 + .../native-parity-root-report.json | 35 + .../WBV2-P10-000/native-parity-task-plan.json | 1567 ++++++++++++++ .../WBV2-P10-001/current-source-hashes.json | 23 + .../dependency-inventory.current.json | 1862 +++++++++++++++++ .../inventory-rebaseline-report.json | 47 + tests/golden/WBV2-P10-001/manifest.json | 74 + .../WBV2-P10-001/native-parity-task-plan.json | 1567 ++++++++++++++ tests/golden/WBV2-P10-001/task-context.json | 185 ++ tests/golden/WBV2-P10-002/manifest.json | 90 + .../native-engine-binding-report.json | 61 + .../native-engine-production.json | 478 +++++ .../native-engine-production.second.json | 478 +++++ .../native-engine-receipt-report.json | 102 + .../WBV2-P10-002/native-parity-task-plan.json | 1567 ++++++++++++++ tests/golden/WBV2-P10-002/task-context.json | 197 ++ tests/golden/WBV2-P10-003/manifest.json | 73 + .../module-matrix-production.json | 219 ++ .../module-matrix-production.second.json | 219 ++ .../module-matrix-receipt-report.json | 65 + tests/golden/WBV2-P10-003/module-matrix.json | 176 ++ .../WBV2-P10-003/native-parity-task-plan.json | 1567 ++++++++++++++ tests/golden/WBV2-P10-003/task-context.json | 176 ++ .../feature-parity-gate-report.json | 5 +- tests/golden/WBV2-P9-004/manifest.json | 13 +- tests/golden/WBV2-P9-004/task-context.json | 22 +- tests/golden/WBV2/task-catalog.jsonl | 6 +- tests/golden/WBV2/task-index.json | 2 +- tools/web/check-v2-handoff.mjs | 2 +- tools/web/check-wbv2-inventory-rebaseline.mjs | 50 + tools/web/check-wbv2-native-engine.mjs | 73 + .../generate-wbv2-inventory-rebaseline.mjs | 92 + .../generate-wbv2-module-matrix-receipt.mjs | 95 + tools/web/generate-wbv2-module-matrix.mjs | 60 + .../generate-wbv2-native-engine-receipt.mjs | 132 ++ .../web/generate-wbv2-native-parity-root.mjs | 98 + tools/web/task-context-lib.mjs | 2 +- web/tests/e2e/wbv2-module-matrix.spec.ts | 65 + .../e2e/wbv2-native-engine-production.spec.ts | 149 ++ web/tests/unit/task-context.test.mjs | 4 +- 50 files changed, 11906 insertions(+), 26 deletions(-) create mode 100644 docs/status/WBV2-P10-000.md create mode 100644 docs/status/WBV2-P10-001.md create mode 100644 docs/status/WBV2-P10-002.md create mode 100644 docs/status/WBV2-P10-003.md create mode 100644 docs/tasks/WBV2-P10-000.md create mode 100644 docs/tasks/WBV2-P10-001.md create mode 100644 docs/tasks/WBV2-P10-002.md create mode 100644 docs/tasks/WBV2-P10-003.md create mode 100644 tests/golden/WBV2-P10-000/manifest.json create mode 100644 tests/golden/WBV2-P10-000/native-parity-root-report.json create mode 100644 tests/golden/WBV2-P10-000/native-parity-task-plan.json create mode 100644 tests/golden/WBV2-P10-001/current-source-hashes.json create mode 100644 tests/golden/WBV2-P10-001/dependency-inventory.current.json create mode 100644 tests/golden/WBV2-P10-001/inventory-rebaseline-report.json create mode 100644 tests/golden/WBV2-P10-001/manifest.json create mode 100644 tests/golden/WBV2-P10-001/native-parity-task-plan.json create mode 100644 tests/golden/WBV2-P10-001/task-context.json create mode 100644 tests/golden/WBV2-P10-002/manifest.json create mode 100644 tests/golden/WBV2-P10-002/native-engine-binding-report.json create mode 100644 tests/golden/WBV2-P10-002/native-engine-production.json create mode 100644 tests/golden/WBV2-P10-002/native-engine-production.second.json create mode 100644 tests/golden/WBV2-P10-002/native-engine-receipt-report.json create mode 100644 tests/golden/WBV2-P10-002/native-parity-task-plan.json create mode 100644 tests/golden/WBV2-P10-002/task-context.json create mode 100644 tests/golden/WBV2-P10-003/manifest.json create mode 100644 tests/golden/WBV2-P10-003/module-matrix-production.json create mode 100644 tests/golden/WBV2-P10-003/module-matrix-production.second.json create mode 100644 tests/golden/WBV2-P10-003/module-matrix-receipt-report.json create mode 100644 tests/golden/WBV2-P10-003/module-matrix.json create mode 100644 tests/golden/WBV2-P10-003/native-parity-task-plan.json create mode 100644 tests/golden/WBV2-P10-003/task-context.json create mode 100644 tools/web/check-wbv2-inventory-rebaseline.mjs create mode 100644 tools/web/check-wbv2-native-engine.mjs create mode 100644 tools/web/generate-wbv2-inventory-rebaseline.mjs create mode 100644 tools/web/generate-wbv2-module-matrix-receipt.mjs create mode 100644 tools/web/generate-wbv2-module-matrix.mjs create mode 100644 tools/web/generate-wbv2-native-engine-receipt.mjs create mode 100644 tools/web/generate-wbv2-native-parity-root.mjs create mode 100644 web/tests/e2e/wbv2-module-matrix.spec.ts create mode 100644 web/tests/e2e/wbv2-native-engine-production.spec.ts diff --git a/docs/EXECUTION_QUEUE.md b/docs/EXECUTION_QUEUE.md index 8b65e0cd9..27f211397 100644 --- a/docs/EXECUTION_QUEUE.md +++ b/docs/EXECUTION_QUEUE.md @@ -13,9 +13,9 @@ | 字段 | 值 | | --- | --- | | 里程碑 | WBV2 capability workflow | -| 当前任务 | `WBV2-P9-004` | -| parent manifest | `tests/golden/WBV2-P9-003/manifest.json` | -| 任务卡 | [`tasks/WBV2-P9-004.md`](tasks/WBV2-P9-004.md) | +| 当前任务 | `WBV2-P10-003` | +| parent manifest | `tests/golden/WBV2-P10-002/manifest.json` | +| 任务卡 | [`tasks/WBV2-P10-003.md`](tasks/WBV2-P10-003.md) | | 专项验收 | `node tools/web/check-execution-control-plane.mjs` | | legacy coverage checkpoint | `M16-GAP-00282` | | legacy coverage parent | `tests/golden/M16-GAP-00281/manifest.json` | diff --git a/docs/status/WBV2-P10-000.md b/docs/status/WBV2-P10-000.md new file mode 100644 index 000000000..aca3596c7 --- /dev/null +++ b/docs/status/WBV2-P10-000.md @@ -0,0 +1,6 @@ +# WBV2-P10-000 status + +- task: `WBV2-P10-000`; parent: `WBV2-P9-004`; status: `done` +- nextTask: `WBV2-P10-001` + +Native engine parity continuation is authorized after P9 bounded Chromium evidence. P10 first reconciles the known WBV2 inventory drift, then requires receipts from the compiled Blender native binary and web_engine.wasm. Full historical reproduction remains false. diff --git a/docs/status/WBV2-P10-001.md b/docs/status/WBV2-P10-001.md new file mode 100644 index 000000000..24dcd23f8 --- /dev/null +++ b/docs/status/WBV2-P10-001.md @@ -0,0 +1,9 @@ +# WBV2-P10-001 status + +- task: `WBV2-P10-001`; parent: `WBV2-P10-000`; status: `done` +- plan drift: `1` authorized mutable plan hash +- dependency packages: `144`; lockfile/roots/closure: `STABLE` +- historical P0 hashes: preserved +- nextTask: `WBV2-P10-002` + +The current WBV2 plan hash is recorded as an additive epoch-1 baseline. The historical P0-002 source-hashes.json and all historical manifests remain unchanged. Dependency roots, lockfile, package closure, and package count remain stable. diff --git a/docs/status/WBV2-P10-002.md b/docs/status/WBV2-P10-002.md new file mode 100644 index 000000000..e960c015a --- /dev/null +++ b/docs/status/WBV2-P10-002.md @@ -0,0 +1,9 @@ +# WBV2-P10-002 status + +- task: `WBV2-P10-002`; parent: `WBV2-P10-001`; status: `done` +- compiled native: `Blender 5.2.0 LTS`; compiled WASM: `web_engine.wasm` +- real Main mutations: `Mesh + Modifier + Asset Catalog` +- deterministic Chromium runs: `2`; save/reopen: `3/3 EXACT` +- nextTask: `WBV2-P10-003` + +The Chromium Worker loaded the checked-in WebEngine WASM and executed the native ABI through WebEngineClient. Mesh translation, modifier state, and library append all changed the real WASM Main, persisted through save/reopen, and rejected stale or malformed inputs without a late mutation. This evidence is engine-bound and still does not claim full historical reproduction. diff --git a/docs/status/WBV2-P10-003.md b/docs/status/WBV2-P10-003.md new file mode 100644 index 000000000..cc116b8d7 --- /dev/null +++ b/docs/status/WBV2-P10-003.md @@ -0,0 +1,9 @@ +# WBV2-P10-003 status + +- task: `WBV2-P10-003`; parent: `WBV2-P10-002`; status: `done` +- module cases: `9`; positive Main mutations: `3`; retained negatives: `6` +- shards: `2`; one catalog hash; exit codes: `0/0` +- inventory: `6900` total, `6900` explicitly remaining; no false completion claim +- nextTask: `NONE` + +The data-driven Mesh, Modifier, and Asset Catalog matrix re-runs the real WebEngine WASM Main path with one catalog hash. Positive cases change Main and pass save/reopen; stale, malformed, unknown, and collision cases remain explicit retained negatives. The matrix does not claim all inventory entries are complete or reproduce unavailable historical bytes. P10-003 is the terminal pointer until a separately authorized continuation is created. diff --git a/docs/status/WBV2-P9-004.md b/docs/status/WBV2-P9-004.md index 6effcbad2..950a50289 100644 --- a/docs/status/WBV2-P9-004.md +++ b/docs/status/WBV2-P9-004.md @@ -8,3 +8,6 @@ - nextTask: `NONE` The 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. +- authorized continuation: `WBV2-P10-000` + +Native Blender/WASM engine parity may continue under a new manifest root. This does not change the bounded P9 claims or the authorized-rebaseline-only release scope. diff --git a/docs/tasks/WBV2-P10-000.md b/docs/tasks/WBV2-P10-000.md new file mode 100644 index 000000000..d3e171ba5 --- /dev/null +++ b/docs/tasks/WBV2-P10-000.md @@ -0,0 +1,24 @@ +# WBV2-P10-000: native engine parity continuation root + +- task: WBV2-P10-000 +- parent: WBV2-P9-004 +- status: done +- gap: workflow:authorize_native_engine_parity_continuation +- ownerFamily: PROGRAM +- targetImplementationClass: LOCAL_BOUNDED + +## 目标 + +Authorize the next parity epoch after P9 bounded Chromium receipts. The next work must bind evidence to the compiled Blender native binary and web_engine.wasm; it must not claim full historical reproduction. + +## 验收 + +- `node tools/web/generate-wbv2-native-parity-root.mjs` +- `node tools/web/check-execution-control-plane.mjs` +- `node tools/web/check-v2-task-index.mjs` + +## 交付与回滚 + +- Reports: `tests/golden/WBV2-P10-000/` +- Manifest: `tests/golden/WBV2-P10-000/manifest.json` +- Rollback: restore P9-004 as queue parent without rewriting P7/P8/P9 evidence. diff --git a/docs/tasks/WBV2-P10-001.md b/docs/tasks/WBV2-P10-001.md new file mode 100644 index 000000000..ba6331da7 --- /dev/null +++ b/docs/tasks/WBV2-P10-001.md @@ -0,0 +1,35 @@ +# WBV2-P10-001: reconcile WBV2 inventory source drift + +- task: WBV2-P10-001 +- parent: WBV2-P10-000 +- status: in_progress +- gap: workflow:reconcile_wbv2_inventory_source_drift +- ownerFamily: PARITY +- targetImplementationClass: LOCAL_BOUNDED + +## 目标 + +Record the already observed mutable plan drift and prove dependency closure stability. The historical P0-002 source hashes remain immutable; a current baseline is an additive P10 artifact. + +## 输入与范围 + +- Historical source hashes: `tests/golden/WBV2-P0-002/source-hashes.json` +- Current plan: `docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json` +- Dependency baseline: `tests/golden/M13-05C/dependency-inventory.json` +- Checker: `tools/web/check-wbv2-inventory.mjs` +- Rebaseline generator: `tools/web/generate-wbv2-inventory-rebaseline.mjs` + +## 验收 + +- `node tools/web/generate-wbv2-inventory-rebaseline.mjs --write` +- `node tools/web/check-wbv2-inventory-rebaseline.mjs` +- `node tools/web/check-task-context.mjs --task WBV2-P10-001 --write` + +Failure cases (malformed input, unsupported dependency, unexpected drift, changed closure, historical hash rewrite, missing baseline, or failed checker) must keep in_progress and must not advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/WBV2-P10-001/` +- Status: `docs/status/WBV2-P10-001.md` +- Manifest: `tests/golden/WBV2-P10-001/manifest.json` +- Rollback: restore P10-000 as queue parent; keep P0-002 hashes untouched. diff --git a/docs/tasks/WBV2-P10-002.md b/docs/tasks/WBV2-P10-002.md new file mode 100644 index 000000000..5d0464b16 --- /dev/null +++ b/docs/tasks/WBV2-P10-002.md @@ -0,0 +1,43 @@ +# WBV2-P10-002: native and WASM engine receipts + +- task: WBV2-P10-002 +- parent: WBV2-P10-001 +- status: in_progress +- gap: workflow:bind_native_and_wasm_engine_receipts +- ownerFamily: ENGINE +- targetImplementationClass: LOCAL_EXACT + +## 目标 + +Bind the proven Mesh, Modifier, and Asset Catalog mutations to the compiled Blender native binary and the checked-in web_engine.wasm runtime, with Chromium as the browser gate. + +## 输入与范围 + +- Native binary: `build_blender_native/bin/blender` +- WASM binary: `web/app/src/vendor/blender/web_engine.wasm` +- WASM loader: `web/app/src/vendor/blender/web_engine.js` +- Native Web Engine API: `blender-5.2.0/source/blender/web_engine/web_engine_api.cpp` +- Existing P9 capability receipts: `tests/golden/WBV2-P9-004/feature-parity-gate-report.json` + +## 生产入口 + +- WebEngine client: `web/app/src/engine-client/WebEngineClient.ts` +- WebEngine worker: `web/app/src/workers/web-engine.worker.ts` +- Production receipt test: `web/tests/e2e/wbv2-native-engine-production.spec.ts` + +## 验收 + +- `build_blender_native/bin/blender --version` +- `node tools/web/check-wbv2-native-engine.mjs --write` +- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-native-engine-production.spec.ts` +- `node tools/web/generate-wbv2-native-engine-receipt.mjs --write` +- `node tools/web/check-task-context.mjs --task WBV2-P10-002 --write` + +Missing binary, source hash drift, fake bridge execution, unsupported browser, non-exact save/reopen, or failure mutation must keep in_progress and must not advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/WBV2-P10-002/` +- Status: `docs/status/WBV2-P10-002.md` +- Manifest: `tests/golden/WBV2-P10-002/manifest.json` +- Rollback: restore P10-001 as queue parent without modifying P9 receipts. diff --git a/docs/tasks/WBV2-P10-003.md b/docs/tasks/WBV2-P10-003.md new file mode 100644 index 000000000..a34126e57 --- /dev/null +++ b/docs/tasks/WBV2-P10-003.md @@ -0,0 +1,34 @@ +# WBV2-P10-003: core module operator matrix + +- task: WBV2-P10-003 +- parent: WBV2-P10-002 +- status: in_progress +- gap: workflow:expand_core_module_operator_matrix +- ownerFamily: PARITY +- targetImplementationClass: LOCAL_BOUNDED + +## 目标 + +Run one hash-bound data-driven matrix for Mesh, Modifier, and Asset Catalog module cases instead of creating one production task per legacy operator. + +## 输入与范围 + +- Capability gate: `tests/golden/WBV2-P9-004/feature-parity-gate-report.json` +- Native engine receipt: `tests/golden/WBV2-P10-002/native-engine-receipt-report.json` +- Operator inventory: `tests/golden/WBV2-P0-002/parity-map.json` + +## 验收 + +- `node tools/web/generate-wbv2-module-matrix.mjs --write` +- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-module-matrix.spec.ts` +- `node tools/web/generate-wbv2-module-matrix-receipt.mjs --write` +- `node tools/web/check-task-context.mjs --task WBV2-P10-003 --write` + +Malformed or unsupported cases, new failures, unexpected blocked cases, catalog hash drift, or a positive case without Main mutation must keep in_progress and must not advance nextTask. + +## 交付与回滚 + +- Reports: `tests/golden/WBV2-P10-003/` +- Status: `docs/status/WBV2-P10-003.md` +- Manifest: `tests/golden/WBV2-P10-003/manifest.json` +- Rollback: restore P10-002 as queue parent without modifying native engine receipts. diff --git a/tests/golden/WBV2-P10-000/manifest.json b/tests/golden/WBV2-P10-000/manifest.json new file mode 100644 index 000000000..32e8799fc --- /dev/null +++ b/tests/golden/WBV2-P10-000/manifest.json @@ -0,0 +1,56 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-000", + "parentTask": "WBV2-P9-004", + "operation": "AUTHORIZE_NATIVE_ENGINE_PARITY_CONTINUATION", + "status": "done", + "enablingTask": true, + "parityStateChange": false, + "artifacts": { + "parentManifest": { + "path": "tests/golden/WBV2-P9-004/manifest.json", + "sha256": "6901f2b779e1bd4e62d240ceb115833ca28f1a209b65aaae71762225758da2f6" + }, + "parentReport": { + "path": "tests/golden/WBV2-P9-004/feature-parity-gate-report.json", + "sha256": "0a7683e08c96bd3d75bda7f420c23945081b238c91031576a149a646451d6d0f" + }, + "approval": { + "path": "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json", + "sha256": "cffc869734af94ffe6b8b8004d7ab8cc2c9edcb85ec2a877548e0b0f923f5ea3" + }, + "plan": { + "path": "tests/golden/WBV2-P10-000/native-parity-task-plan.json", + "sha256": "b72c6fd251f0c2c7e96c410d7195060ea838313937fabf9ee720f9670f512e1f" + }, + "report": { + "path": "tests/golden/WBV2-P10-000/native-parity-root-report.json", + "sha256": "06f4754b70433a66c43835e6d6b72041a673667af51d9c4efe3d8e701bab2c6e" + }, + "rootCard": { + "path": "docs/tasks/WBV2-P10-000.md", + "sha256": "071b3069be0bf0695f801bc8058ba44ac44cc3e200f686396512928f2eee15da" + }, + "rootStatus": { + "path": "docs/status/WBV2-P10-000.md", + "sha256": "97a1caa7843e1ce2be68f8eafdada2c8afe2341ffdaa2407d3701c2b1fd739c8" + }, + "activeCard": { + "path": "docs/tasks/WBV2-P10-001.md", + "sha256": "535a35b420188d19fa7acab58b8eb5b6995177145eec59733288f1fadf8098dd" + } + }, + "assertions": { + "boundedP9EvidencePreserved": true, + "nativeEngineRequired": true, + "authorizedRebaselineOnly": true, + "fullHistoricalReproduction": false, + "featureScope": [ + "INVENTORY_DRIFT", + "NATIVE_ENGINE", + "WASM_ENGINE", + "MODULE_MATRIX" + ] + }, + "nextTask": "WBV2-P10-001" +} diff --git a/tests/golden/WBV2-P10-000/native-parity-root-report.json b/tests/golden/WBV2-P10-000/native-parity-root-report.json new file mode 100644 index 000000000..d54febc65 --- /dev/null +++ b/tests/golden/WBV2-P10-000/native-parity-root-report.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-000", + "operation": "AUTHORIZE_NATIVE_ENGINE_PARITY_CONTINUATION", + "status": "PASS", + "parent": { + "task": "WBV2-P9-004", + "manifest": "tests/golden/WBV2-P9-004/manifest.json", + "manifestSha256": "6901f2b779e1bd4e62d240ceb115833ca28f1a209b65aaae71762225758da2f6", + "previousDecision": "READY_WITH_BOUNDED_FEATURE_PARITY", + "fullHistoricalReproduction": false + }, + "continuation": { + "root": "WBV2-P10-000", + "firstTask": "WBV2-P10-001", + "plannedTasks": 4, + "scope": [ + "INVENTORY_DRIFT", + "NATIVE_ENGINE", + "WASM_ENGINE", + "MODULE_MATRIX" + ], + "browser": "chromium", + "nativeBinary": "build_blender_native/bin/blender", + "wasmBinary": "web/app/src/vendor/blender/web_engine.wasm" + }, + "policy": { + "historicalEvidencePreserved": true, + "authorizedRebaselineAccepted": true, + "nativeEngineReceiptsRequired": true, + "fullHistoricalReproduction": false, + "releaseScope": "AUTHORIZED_REBASELINE_ONLY" + }, + "nextTask": "WBV2-P10-001" +} diff --git a/tests/golden/WBV2-P10-000/native-parity-task-plan.json b/tests/golden/WBV2-P10-000/native-parity-task-plan.json new file mode 100644 index 000000000..0123a4967 --- /dev/null +++ b/tests/golden/WBV2-P10-000/native-parity-task-plan.json @@ -0,0 +1,1567 @@ +{ + "schemaVersion": 1, + "planId": "BLENDER_WEB_PARITY_V2_NATIVE_ENGINE_EPOCH_1", + "status": "ACTIVE_NATIVE_ENGINE_QUEUE", + "authority": "queue_reactivated_after_p9_bounded_parity", + "productContract": "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "sourcePlan": "docs/BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md", + "executionPointer": "docs/EXECUTION_QUEUE.md", + "correctiveCheckpoint": { + "task": "C6-003", + "handoff": "tests/golden/corrective/C6-003/handoff.json", + "status": "active", + "blocker": null, + "queueMutation": true, + "legacyTask": "M16-GAP-00277", + "legacyParentNextTask": "M16-GAP-00277" + }, + "runtimePolicy": { + "blenderSource": "blender-5.2.0", + "browserEvidence": [ + "chromium" + ], + "forbiddenBrowsers": [ + "firefox", + "webkit" + ], + "mainAuthority": "blender_main", + "storage": [ + "opfs", + "indexeddb" + ], + "queueMutation": "enabled_after_owner_review_and_g5" + }, + "completionClasses": [ + "LOCAL_EXACT", + "LOCAL_BOUNDED", + "SERVER_EXACT", + "EXCLUDED" + ], + "gates": [ + { + "id": "G0", + "name": "scope_and_inventory", + "requires": [ + "contract", + "inventory", + "capability_matrix" + ] + }, + { + "id": "G1", + "name": "runtime_foundation", + "requires": [ + "sceneir", + "main_transaction", + "worker_lifecycle", + "storage_journal" + ] + }, + { + "id": "G2", + "name": "feature_parity", + "requires": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence" + ] + }, + { + "id": "G3", + "name": "recovery_and_security", + "requires": [ + "cancel", + "restart", + "oom_quota", + "malformed", + "dispose" + ] + }, + { + "id": "G4", + "name": "release_candidate", + "requires": [ + "offline", + "ci", + "sbom", + "rollback", + "hashes" + ] + }, + { + "id": "G5", + "name": "queue_mutation", + "requires": [ + "owner_review", + "protected_hashes", + "handoff", + "single_ready_task" + ] + } + ], + "waves": [ + { + "id": "P0", + "name": "facts_and_contracts", + "gate": "G0", + "tasks": [ + "WBV2-P0-001", + "WBV2-P0-002", + "WBV2-P0-003" + ] + }, + { + "id": "P1", + "name": "runtime_foundation", + "gate": "G1", + "tasks": [ + "WBV2-P1-001", + "WBV2-P1-002", + "WBV2-P1-003", + "WBV2-P1-004", + "WBV2-P1-005" + ] + }, + { + "id": "P2", + "name": "core_modeler_loop", + "gate": "G2", + "tasks": [ + "WBV2-P2-001", + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P2-005" + ] + }, + { + "id": "P3", + "name": "authoring_and_io", + "gate": "G2", + "tasks": [ + "WBV2-P3-001", + "WBV2-P3-002", + "WBV2-P3-003", + "WBV2-P3-004", + "WBV2-P3-005" + ] + }, + { + "id": "P4", + "name": "advanced_local_slices", + "gate": "G2", + "tasks": [ + "WBV2-P4-001", + "WBV2-P4-002", + "WBV2-P4-003", + "WBV2-P4-004" + ] + }, + { + "id": "P5", + "name": "render_and_server", + "gate": "G3", + "tasks": [ + "WBV2-P5-001", + "WBV2-P5-002", + "WBV2-P5-003" + ] + }, + { + "id": "P6", + "name": "security_performance_release", + "gate": "G4", + "tasks": [ + "WBV2-P6-001", + "WBV2-P6-002", + "WBV2-P6-003" + ] + }, + { + "id": "P7", + "name": "full_parity_gap_program", + "gate": "G5", + "tasks": [ + "WBV2-P7-001", + "WBV2-P7-002", + "WBV2-P7-003" + ] + } + ], + "taskContract": { + "onePrimaryBehavior": true, + "requiredEvidence": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence", + "manifest", + "status" + ], + "requiredCommands": [ + "focused", + "determinism", + "hash", + "governance" + ], + "failureState": "in_progress_or_blocked", + "successorRule": "only_from_parent_manifest_nextTask" + }, + "tasks": [ + { + "id": "WBV2-P0-001", + "phase": "P0", + "title": "reconcile_scope_and_checkpoints", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-governance", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-001.md", + "behavior": "Freeze V1/full-parity boundary and reconcile legacy/corrective pointers without queue mutation.", + "outputs": [ + "scope decision", + "checkpoint report", + "protected hash set" + ], + "acceptance": [ + "corrective owner-review status is explicit", + "legacy parent pointer is unchanged", + "plan has one activation gate" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-002", + "phase": "P0", + "title": "generate_blender52_inventory_and_parity_map", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-inventory", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-002.md", + "behavior": "Generate stable Blender 5.2 data-block/operator/editor/node/format inventory and map every entry to a completion class.", + "outputs": [ + "inventory", + "parity map", + "source hash" + ], + "acceptance": [ + "unknown entries are classified", + "inventory is deterministic", + "no entry claims feature parity without evidence" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-003", + "phase": "P0", + "title": "freeze_capability_error_budget_contract", + "kind": "enabling", + "owner": "PROTOCOL", + "dependsOn": [ + "WBV2-P0-001", + "WBV2-P0-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-contract", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-003.md", + "behavior": "Freeze capability levels, stable error codes, revision, budget, cancellation and loss-report schemas.", + "outputs": [ + "versioned protocol", + "capability matrix", + "negative matrix" + ], + "acceptance": [ + "unsupported input fails closed", + "schema hashes are stable", + "migration policy preserves unknown data" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-001", + "phase": "P1", + "title": "stabilize_runtime_variants_and_source_receipts", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P0-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-runtime", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-001.md", + "behavior": "Bind single-thread/pthread WebEngine variants to pinned Blender source/build/runtime receipts.", + "outputs": [ + "runtime manifest", + "variant selector", + "fallback report" + ], + "acceptance": [ + "variant fallback is deterministic", + "source/build hash is verified", + "one engine session has one generation" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-002", + "phase": "P1", + "title": "unify_sceneir_stable_ids_and_binary_deltas", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-001" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-sceneir", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-002.md", + "behavior": "Make SceneIR/WBG1 stable IDs, topology/attribute domains and binary/range deltas canonical across desktop and WASM.", + "outputs": [ + "SceneIR schema", + "binary fixture", + "delta comparator" + ], + "acceptance": [ + "IDs survive save/reopen", + "malformed chunk is rejected", + "desktop and WASM canonical hashes match" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-003", + "phase": "P1", + "title": "unify_main_transaction_history_and_save", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-002" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-history", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-003.md", + "behavior": "Use one Main transaction/revision/history contract for commit, undo/redo, atomic save and reopen.", + "outputs": [ + "transaction contract", + "history receipt", + "save/reopen runner" + ], + "acceptance": [ + "failed/no-op commands add no history", + "stale revision cannot commit", + "reopen state is byte/hash stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-004", + "phase": "P1", + "title": "harden_worker_cancel_restart_and_dispose", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P1-001", + "WBV2-P1-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-lifecycle", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-004.md", + "behavior": "Make cancellation, late-result rejection, Worker restart and resource disposal common to all domains.", + "outputs": [ + "lifecycle runner", + "fault report", + "dispose counters" + ], + "acceptance": [ + "cancel never publishes result", + "generation mismatch is rejected", + "CPU/WASM/GPU owners return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-005", + "phase": "P1", + "title": "harden_opfs_indexeddb_journal_recovery", + "kind": "enabling", + "owner": "STORAGE", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P1-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-storage", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-005.md", + "behavior": "Unify OPFS staging/content addressing and IndexedDB metadata/journal recovery.", + "outputs": [ + "storage schema", + "crash fixtures", + "recovery checker" + ], + "acceptance": [ + "interrupted commit leaves old project usable", + "hash mismatch quarantines payload", + "small project recovers after restart" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-001", + "phase": "P2", + "title": "open_blend_scene_context_and_outliner", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P1-005" + ], + "parityId": "EDITOR.OPEN_SCENE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-editor", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-001.md", + "behavior": "Open a minimal .blend and expose scene/object/collection context from authoritative Main.", + "outputs": [ + "desktop fixture", + "outliner report", + "Chromium path" + ], + "acceptance": [ + "stable IDs and selection revision match", + "missing data is structured", + "reopen preserves context" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-002", + "phase": "P2", + "title": "object_collection_parent_transform_workflow", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P2-001" + ], + "parityId": "OBJECT.TRANSFORM_HIERARCHY", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-scene", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-002.md", + "behavior": "Edit object transform, collection membership and parent hierarchy through Main transactions.", + "outputs": [ + "desktop/WASM golden", + "negative cases", + "save/reopen receipt" + ], + "acceptance": [ + "world matrix parity", + "cycle/locked/library edits reject", + "undo/redo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-003", + "phase": "P2", + "title": "mesh_edit_core_operations", + "kind": "feature", + "owner": "MESH", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P2-002" + ], + "parityId": "MESH.EDIT_CORE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-mesh", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-003.md", + "behavior": "Expose bounded vertex/edge/face selection plus merge/dissolve/extrude/inset/bevel/loop-cut.", + "outputs": [ + "Blender fixture set", + "topology comparator", + "Chromium edit path" + ], + "acceptance": [ + "topology/attributes match", + "invalid selection and budget fail closed", + "single transaction and reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-004", + "phase": "P2", + "title": "dual_viewport_sceneir_render_path", + "kind": "feature", + "owner": "VIEWPORT", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P2-003" + ], + "parityId": "VIEWPORT.MAIN_OFFSCREEN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-viewport", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-004.md", + "behavior": "Render the same validated SceneIR through main-thread WebGL2 and OffscreenCanvas Worker paths.", + "outputs": [ + "pixel report", + "viewport diagnostics", + "device recovery" + ], + "acceptance": [ + "both paths have nonblank pixels", + "selection/camera revision is shared", + "device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-005", + "phase": "P2", + "title": "close_p0_user_loop", + "kind": "feature", + "owner": "INTEGRATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P1-005", + "WBV2-P2-004" + ], + "parityId": "WORKFLOW.P0_USER_LOOP", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-integration", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-005.md", + "behavior": "Prove open -> edit -> undo -> redo -> save -> restart -> reopen -> GLB in one production flow.", + "outputs": [ + "P0 workflow report", + "release binding", + "rollback receipt" + ], + "acceptance": [ + "Main revision and exported asset are bound", + "fault/cancel leaves old state", + "Chromium production path passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-001", + "phase": "P3", + "title": "material_uv_principled_asset_workflow", + "kind": "feature", + "owner": "MATERIAL", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005" + ], + "parityId": "MATERIAL.PBR_UV", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-001.md", + "behavior": "Edit material slots, UVs and declared Principled/Image/Normal graph nodes with content-addressed textures.", + "outputs": [ + "material golden", + "texture receipt", + "loss report" + ], + "acceptance": [ + "desktop/WASM node fields match", + "unsupported node retained/blocked", + "packed asset survives reopen" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-002", + "phase": "P3", + "title": "keyframe_timeline_action_workflow", + "kind": "feature", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-005", + "WBV2-P3-001" + ], + "parityId": "ANIMATION.TRS_ACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-002.md", + "behavior": "Create/edit TRS keyframes, timeline and declared Action interpolation through Main.", + "outputs": [ + "frame golden", + "animation comparator", + "reopen report" + ], + "acceptance": [ + "sampled values and handles match", + "stale frame result rejected", + "undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-003", + "phase": "P3", + "title": "armature_pose_constraint_skin_workflow", + "kind": "feature", + "owner": "RIG", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P3-002" + ], + "parityId": "RIG.POSE_SKIN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-rig", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-003.md", + "behavior": "Read and edit declared armature pose/constraint/weight/shape-key slices with bounded evaluation.", + "outputs": [ + "pose golden", + "skin report", + "unsupported matrix" + ], + "acceptance": [ + "pose matrices and weights match", + "unsupported constraint is explicit", + "save/reopen and small recovery pass" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-004", + "phase": "P3", + "title": "glb_roundtrip_and_loss_report", + "kind": "feature", + "owner": "IO", + "dependsOn": [ + "WBV2-P2-005", + "WBV2-P3-001", + "WBV2-P3-003" + ], + "parityId": "IO.GLB_ROUNDTRIP", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-io", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-004.md", + "behavior": "Import/export declared GLB mesh/PBR/texture/morph/skin/animation and report non-mapped semantics.", + "outputs": [ + "GLB fixtures", + "desktop reimport report", + "loss report" + ], + "acceptance": [ + "roundtrip canonical graph matches", + "sparse/external URI/budget negatives reject", + "no silent loss" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-005", + "phase": "P3", + "title": "library_asset_append_link_override", + "kind": "feature", + "owner": "ASSET", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P2-001", + "WBV2-P3-004" + ], + "parityId": "ASSET.LIBRARY_OPERATIONS", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-assets", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-005.md", + "behavior": "Support declared append/link/override ownership, reload and missing-library semantics.", + "outputs": [ + "library fixtures", + "ownership report", + "negative matrix" + ], + "acceptance": [ + "source/hash/owner identity preserved", + "linked mutation blocked", + "stale generation and missing source fail closed" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-001", + "phase": "P4", + "title": "modifier_graph_and_apply_slices", + "kind": "feature", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005", + "WBV2-P3-005" + ], + "parityId": "MODIFIER.DECLARED_SLICES", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-001.md", + "behavior": "Enable one declared modifier parameter/apply workflow at a time with dependency-aware blocking.", + "outputs": [ + "modifier goldens", + "dependency report", + "negative cases" + ], + "acceptance": [ + "desktop/evaluated Main match", + "unknown modifier retained and blocked", + "apply/undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-002", + "phase": "P4", + "title": "geometry_nodes_and_shader_allowlist", + "kind": "feature", + "owner": "NODES", + "dependsOn": [ + "WBV2-P3-001", + "WBV2-P4-001" + ], + "parityId": "NODES.ALLOWLIST", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-002.md", + "behavior": "Read/write/evaluate only declared Geometry Nodes and shader graph allowlists with resource budgets.", + "outputs": [ + "node fixtures", + "compile/cache receipts", + "unsupported graph reports" + ], + "acceptance": [ + "node/socket/link/default parity", + "budget and unknown-node block before commit", + "compile failure rolls back" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-003", + "phase": "P4", + "title": "sculpt_nonmesh_and_paint_bounded_slices", + "kind": "feature", + "owner": "SCULPT", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P4-002" + ], + "parityId": "SCULPT.NONMESH.PAINT_BOUNDED", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-003.md", + "behavior": "Expose declared sculpt attributes/strokes, Curve/Surface/Font/PointCloud and paint slices with explicit PBVH limits.", + "outputs": [ + "non-mesh fixtures", + "stroke report", + "capability blocks" + ], + "acceptance": [ + "Main commit is atomic", + "unsupported brush/solver returns stable code", + "GPU/OOM/restart recovery passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-004", + "phase": "P4", + "title": "simulation_cache_identity_and_lifecycle", + "kind": "feature", + "owner": "SIMULATION", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P4-002", + "WBV2-P4-003" + ], + "parityId": "SIMULATION.CACHE_LIFECYCLE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G3", + "card": "docs/tasks/WBV2-P4-004.md", + "behavior": "Bind declared simulation cache to source/settings/revision hashes with cancellation, LRU and restart recovery.", + "outputs": [ + "cache fixtures", + "identity report", + "quarantine evidence" + ], + "acceptance": [ + "stale/corrupt cache never publishes", + "small cache recovers after restart", + "budget release is observable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-001", + "phase": "P5", + "title": "render_capability_routing", + "kind": "feature", + "owner": "RENDER", + "dependsOn": [ + "WBV2-P2-004", + "WBV2-P4-002", + "WBV2-P4-004" + ], + "parityId": "RENDER.ROUTING", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-001.md", + "behavior": "Route bounded Eevee/WebGL capabilities locally and unsupported render classes to SERVER_EXACT or EXCLUDED.", + "outputs": [ + "render receipts", + "pixel golden", + "routing report" + ], + "acceptance": [ + "source/settings/build identity bound", + "unsupported route cannot pretend local success", + "cancel/device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-002", + "phase": "P5", + "title": "compositor_sequencer_media_recovery", + "kind": "feature", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P3-002", + "WBV2-P5-001" + ], + "parityId": "MEDIA.BOUNDED_WORKFLOW", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-002.md", + "behavior": "Provide declared compositor/sequencer/codec/proxy/audio slices with revision and recovery gates.", + "outputs": [ + "media receipts", + "recovery report", + "audio/session diagnostics" + ], + "acceptance": [ + "seek/decode revision ordering", + "cancel/timeout does not publish", + "quota/OOM/restart leaves project valid" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-003", + "phase": "P5", + "title": "server_job_result_binding", + "kind": "feature", + "owner": "SERVER", + "dependsOn": [ + "WBV2-P0-003", + "WBV2-P5-001", + "WBV2-P5-002" + ], + "parityId": "SERVER.JOB_BINDING", + "implementationClass": "SERVER_EXACT", + "parallelGroup": "p5-server", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-003.md", + "behavior": "Bind server render/encode/physics jobs to immutable input/settings/build/output hashes and explicit lifecycle states.", + "outputs": [ + "server protocol", + "idempotency receipt", + "negative matrix" + ], + "acceptance": [ + "duplicate request is idempotent", + "stale result cannot bind", + "timeout/cancel/OOM produces no READY output" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-001", + "phase": "P6", + "title": "scripting_default_deny_and_audit", + "kind": "feature", + "owner": "SECURITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P5-003" + ], + "parityId": "SECURITY.SCRIPTING", + "implementationClass": "EXCLUDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-001.md", + "behavior": "Read text/metadata and expose audited, budgeted, default-deny script policy without arbitrary execution.", + "outputs": [ + "policy manifest", + "malicious fixtures", + "audit report" + ], + "acceptance": [ + "autorun/network/add-on defaults deny", + "sandbox cancellation/dispose works", + "no secret or filesystem escape" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-002", + "phase": "P6", + "title": "performance_fault_and_recovery_matrix", + "kind": "enabling", + "owner": "RELIABILITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P1-005", + "WBV2-P2-004", + "WBV2-P6-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-002.md", + "behavior": "Run deterministic geometry/texture/media/cache budgets and inject OOM/quota/device/network faults.", + "outputs": [ + "budget matrix", + "fault reports", + "resource release ledger" + ], + "acceptance": [ + "100k/1M/10M thresholds recorded", + "fault leaves old revision usable", + "all owned resources return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-003", + "phase": "P6", + "title": "offline_ci_sbom_and_rollback_release", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P6-001", + "WBV2-P6-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-release", + "gate": "G4", + "card": "docs/tasks/WBV2-P6-003.md", + "behavior": "Produce reproducible offline/source/binary release packages with CI lanes, SBOM and rollback evidence.", + "outputs": [ + "RC manifest", + "offline archive", + "CI reports" + ], + "acceptance": [ + "quick/Chromium/release lanes pass", + "artifact hashes reproduce", + "upgrade/rollback and known limitations are tested" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-001", + "phase": "P7", + "title": "cluster_full_blender_gap_inventory", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-002", + "WBV2-P6-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-001.md", + "behavior": "Cluster remaining Blender 5.2 data-block/operator/editor/node/format gaps by family and evidence class.", + "outputs": [ + "cluster catalog", + "coverage report", + "risk ranking" + ], + "acceptance": [ + "each gap has stable ID and owner", + "negative-only/unsupported is not positive parity", + "clusters are deterministic" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-002", + "phase": "P7", + "title": "generate_atomic_family_gap_queue", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-002.md", + "behavior": "Generate one task per parityId x observable behavior x implementation class with parent/hash context.", + "outputs": [ + "task index", + "task catalog", + "task cards" + ], + "acceptance": [ + "one active ready task", + "no guessed successor", + "each card fits context budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-003", + "phase": "P7", + "title": "full_parity_candidate_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P7-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P7-003.md", + "behavior": "Recompute parity closure, evidence health, recovery health and release decision from machine manifests.", + "outputs": [ + "parity release report", + "known limitations", + "final decision" + ], + "acceptance": [ + "all claims bind to evidence", + "blocked/excluded/server classes remain explicit", + "queue and protected hashes pass" + ], + "status": "blocked", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-000", + "phase": "P8", + "title": "authorize_recovery_capability_root", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-000.md", + "behavior": "Authorize a recovery epoch without rewriting the blocked P7 manifest.", + "outputs": [ + "recovery plan", + "root manifest", + "queue authorization" + ], + "acceptance": [ + "P7 evidence remains hash exact", + "recovery scope is explicit", + "one recovery task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P8-001", + "phase": "P8", + "title": "rebaseline_mutable_inventories", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-001.md", + "behavior": "Rebaseline mutable WBV2 plan and dependency inventory inputs while preserving historical manifests.", + "outputs": [ + "semantic drift report", + "current inventory baseline", + "manifest" + ], + "acceptance": [ + "only expected mutable hashes drift", + "dependency closure is unchanged", + "historical manifests remain unmodified" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-002", + "phase": "P8", + "title": "close_atomic_chromium_receipts", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P8-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-receipts", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-002.md", + "behavior": "Produce and bind all 45 atomic Chromium family receipts.", + "outputs": [ + "Chromium report", + "45 receipt index", + "receipt manifests" + ], + "acceptance": [ + "45 receipts are manifest-bound", + "desktop/WASM/save-reopen behaviors are explicit", + "Chromium is the only browser" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-003", + "phase": "P8", + "title": "authorize_m12_provenance_epoch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-provenance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-003.md", + "behavior": "Bind restored M12 sources and explicitly rebaseline unavailable originals in a new provenance epoch.", + "outputs": [ + "provenance epoch", + "replacement bindings", + "manifest" + ], + "acceptance": [ + "22 restored originals stay exact", + "62 unavailable entries are not called restored", + "all replacements are hash-bound" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-004", + "phase": "P8", + "title": "recompute_recovery_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P8-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-004.md", + "behavior": "Recompute the release decision from the recovery epoch and atomic receipts.", + "outputs": [ + "release gate", + "known limitations", + "final manifest" + ], + "acceptance": [ + "all receipts bind to manifests", + "provenance epoch is explicit", + "all governance gates pass" + ], + "status": "in_progress", + "ready": false, + "queueMutationAllowed": false + }, + { + "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": "done", + "ready": false, + "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": "done", + "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": "done", + "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": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-000", + "phase": "P10", + "title": "authorize_native_engine_parity_continuation", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P9-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-governance", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-000.md", + "behavior": "Authorize native Blender/WASM engine parity continuation after bounded Chromium capability evidence.", + "outputs": [ + "continuation receipt", + "native parity plan", + "scope limits" + ], + "acceptance": [ + "P9 evidence remains hash-bound", + "native build/runtime is explicit", + "one native parity task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P10-001", + "phase": "P10", + "title": "reconcile_wbv2_inventory_source_drift", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-inventory", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-001.md", + "behavior": "Record the authorized mutable WBV2 plan drift and prove dependency closure stability without rewriting historical P0 evidence.", + "outputs": [ + "current source hash baseline", + "drift report", + "checker compatibility" + ], + "acceptance": [ + "historical P0 hashes remain unchanged", + "only authorized plan drift is recorded", + "dependency roots/lockfile/closure remain stable", + "inventory checker passes using current baseline" + ], + "status": "in_progress", + "ready": true, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-002", + "phase": "P10", + "title": "bind_native_and_wasm_engine_receipts", + "kind": "feature", + "owner": "ENGINE", + "dependsOn": [ + "WBV2-P10-001" + ], + "parityId": "ENGINE.NATIVE_WASM_BRIDGE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p10-engine", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-002.md", + "behavior": "Bind Mesh, Modifier, and Asset Catalog receipts to the compiled Blender native binary and web_engine.wasm runtime.", + "outputs": [ + "native receipt", + "WASM receipt", + "Chromium engine report" + ], + "acceptance": [ + "native Blender binary is source-bound", + "WASM binary and JS are hash-bound", + "same mutation reaches real engine/Main", + "save/reopen and failures remain exact" + ], + "status": "planned", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-003", + "phase": "P10", + "title": "expand_core_module_operator_matrix", + "kind": "feature", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-002" + ], + "parityId": "CORE.MODULE_MATRIX", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-matrix", + "gate": "G7", + "card": "docs/tasks/WBV2-P10-003.md", + "behavior": "Expand the three proven capability modules with data-driven operator coverage and aggregate regression receipts.", + "outputs": [ + "module matrix", + "shard reports", + "aggregate manifest" + ], + "acceptance": [ + "positive cases are L2+", + "negative cases do not mutate Main", + "shards use one catalog hash", + "unmapped and retained-negative cases stay explicit" + ], + "status": "planned", + "ready": false, + "queueMutationAllowed": false + } + ], + "parentPlan": { + "path": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "sha256": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782" + }, + "recoveryRoot": "WBV2-P10-000", + "parentRecoveryPlan": { + "path": "tests/golden/WBV2-P9-004/feature-parity-task-plan.json", + "sha256": "d754f21d4923eec7cdb497caa7ed77300db81f2ccff965c2690f7734aafb135d" + } +} diff --git a/tests/golden/WBV2-P10-001/current-source-hashes.json b/tests/golden/WBV2-P10-001/current-source-hashes.json new file mode 100644 index 000000000..e0e228206 --- /dev/null +++ b/tests/golden/WBV2-P10-001/current-source-hashes.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-001", + "operation": "CURRENT_WBV2_SOURCE_HASH_BASELINE", + "historicalSourceHashes": "tests/golden/WBV2-P0-002/source-hashes.json", + "historicalSourceHashesSha256": "c6c6260d10bc8529e4b26563ce81168e1b0fffb3b175b2d4998ec1c0aa1c1497", + "sources": { + "tests/golden/M15-02A/blender-parity-map.json": "f3e757f26e58a4252b6cc2a7f9275428bbe5bf659cc0f0ff6350a147bdf2809c", + "tests/golden/M15-03A/next-task-plan.json": "bad0d7822c0d4d764bd174c86d9da897229e71de6363940125a594b8017e07f5", + "tests/golden/M15-03A/completed-gap-tasks.json": "1dfc9c4ae8fb9a135e624ca4f9fe1ea10500ef16a2567a3cccdcfe48fbc38466", + "docs/BLENDER_WASM_CAPABILITY_MATRIX_TEMPLATE.json": "053e1551a24da08e045bb54115858a892ddd825fa59f1691a26a1ccfc1db3ca0", + "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782", + "tests/golden/WBV2-P0-001/manifest.json": "09ffbe342f2c510500767ddaa02b18703c25f6c1ee0b2ebd0c563e260c0d0c2b" + }, + "drift": [ + { + "file": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "expected": "c14e01161876ab924c1fe68466c78481fb583d1b822399ffa9f1df1b1d6fb266", + "actual": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782", + "classification": "AUTHORIZED_MUTABLE_PLAN" + } + ] +} diff --git a/tests/golden/WBV2-P10-001/dependency-inventory.current.json b/tests/golden/WBV2-P10-001/dependency-inventory.current.json new file mode 100644 index 000000000..6fbae821c --- /dev/null +++ b/tests/golden/WBV2-P10-001/dependency-inventory.current.json @@ -0,0 +1,1862 @@ +{ + "schemaVersion": 1, + "task": "M13-05C", + "operation": "NPM_DEPENDENCY_INVENTORY", + "package": { + "path": "web/package.json", + "sha256": "40b7f14d4f568ae94bedde83e02115c127e0c714e5eb32a6a97b1e1084c4fa68", + "name": "blender-web-editor", + "version": "0.1.0-rc.1", + "lockfileVersion": 3 + }, + "lockfile": { + "path": "web/package-lock.json", + "sha256": "61f6d13e0148321d3c625a5baa212b5444296d111193c4d62a692685faebff1f", + "packageCount": 144 + }, + "roots": { + "production": [ + "react", + "react-dom" + ], + "build": [ + "@eslint/js", + "@types/react", + "@types/react-dom", + "@types/three", + "@vitejs/plugin-react", + "eslint", + "typescript", + "typescript-eslint", + "vite" + ], + "test": [ + "@axe-core/playwright", + "@playwright/test" + ] + }, + "categoryCounts": { + "production": 3, + "build": 135, + "test": 6 + }, + "sharedCount": 0, + "packages": [ + { + "path": "node_modules/@axe-core/playwright", + "name": "@axe-core/playwright", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.12.1.tgz", + "integrity": "sha512-rMd7xriptqKpP+w5265i4Hdkv2X5kbu6uiBi/B2I7uf3hieRBM3qDCfaKPtxfiYb2mKXfF+yLODJwIx+Jv1GDw==", + "categories": [ + "test" + ], + "dependencies": [ + "axe-core" + ] + }, + { + "path": "node_modules/@dimforge/rapier3d-compat", + "name": "@dimforge/rapier3d-compat", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", + "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@eslint-community/eslint-utils", + "name": "@eslint-community/eslint-utils", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "categories": [ + "build" + ], + "dependencies": [ + "eslint-visitor-keys" + ] + }, + { + "path": "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys", + "name": "eslint-visitor-keys", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@eslint-community/regexpp", + "name": "@eslint-community/regexpp", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@eslint/config-array", + "name": "@eslint/config-array", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "categories": [ + "build" + ], + "dependencies": [ + "@eslint/object-schema", + "debug", + "minimatch" + ] + }, + { + "path": "node_modules/@eslint/config-helpers", + "name": "@eslint/config-helpers", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "categories": [ + "build" + ], + "dependencies": [ + "@eslint/core" + ] + }, + { + "path": "node_modules/@eslint/core", + "name": "@eslint/core", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "categories": [ + "build" + ], + "dependencies": [ + "@types/json-schema" + ] + }, + { + "path": "node_modules/@eslint/js", + "name": "@eslint/js", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@eslint/object-schema", + "name": "@eslint/object-schema", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@eslint/plugin-kit", + "name": "@eslint/plugin-kit", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "categories": [ + "build" + ], + "dependencies": [ + "@eslint/core", + "levn" + ] + }, + { + "path": "node_modules/@humanfs/core", + "name": "@humanfs/core", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "categories": [ + "build" + ], + "dependencies": [ + "@humanfs/types" + ] + }, + { + "path": "node_modules/@humanfs/node", + "name": "@humanfs/node", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "categories": [ + "build" + ], + "dependencies": [ + "@humanfs/core", + "@humanfs/types", + "@humanwhocodes/retry" + ] + }, + { + "path": "node_modules/@humanfs/types", + "name": "@humanfs/types", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@humanwhocodes/module-importer", + "name": "@humanwhocodes/module-importer", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@humanwhocodes/retry", + "name": "@humanwhocodes/retry", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@oxc-project/types", + "name": "@oxc-project/types", + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@playwright/test", + "name": "@playwright/test", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", + "categories": [ + "test" + ], + "dependencies": [ + "playwright" + ] + }, + { + "path": "node_modules/@rolldown/binding-android-arm64", + "name": "@rolldown/binding-android-arm64", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-darwin-arm64", + "name": "@rolldown/binding-darwin-arm64", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-darwin-x64", + "name": "@rolldown/binding-darwin-x64", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-freebsd-x64", + "name": "@rolldown/binding-freebsd-x64", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-arm-gnueabihf", + "name": "@rolldown/binding-linux-arm-gnueabihf", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-arm64-gnu", + "name": "@rolldown/binding-linux-arm64-gnu", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-arm64-musl", + "name": "@rolldown/binding-linux-arm64-musl", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-ppc64-gnu", + "name": "@rolldown/binding-linux-ppc64-gnu", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-s390x-gnu", + "name": "@rolldown/binding-linux-s390x-gnu", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-x64-gnu", + "name": "@rolldown/binding-linux-x64-gnu", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-linux-x64-musl", + "name": "@rolldown/binding-linux-x64-musl", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-openharmony-arm64", + "name": "@rolldown/binding-openharmony-arm64", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-win32-arm64-msvc", + "name": "@rolldown/binding-win32-arm64-msvc", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/binding-win32-x64-msvc", + "name": "@rolldown/binding-win32-x64-msvc", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@rolldown/pluginutils", + "name": "@rolldown/pluginutils", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@tweenjs/tween.js", + "name": "@tweenjs/tween.js", + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@types/esrecurse", + "name": "@types/esrecurse", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@types/estree", + "name": "@types/estree", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@types/json-schema", + "name": "@types/json-schema", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@types/react", + "name": "@types/react", + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "categories": [ + "build" + ], + "dependencies": [ + "csstype" + ] + }, + { + "path": "node_modules/@types/react-dom", + "name": "@types/react-dom", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@types/stats.js", + "name": "@types/stats.js", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@types/three", + "name": "@types/three", + "version": "0.185.1", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.185.1.tgz", + "integrity": "sha512-db1xTb+EgYF2didW+eudSvVPtn75zo+fGsY8ShQrJY/B5ZBmC2Fiaykv3aImHAlCNEGuMPkPGXBJGLwzu5mC7A==", + "categories": [ + "build" + ], + "dependencies": [ + "@dimforge/rapier3d-compat", + "@tweenjs/tween.js", + "@types/stats.js", + "@types/webxr", + "fflate", + "meshoptimizer" + ] + }, + { + "path": "node_modules/@types/webxr", + "name": "@types/webxr", + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@typescript-eslint/eslint-plugin", + "name": "@typescript-eslint/eslint-plugin", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.66.0.tgz", + "integrity": "sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==", + "categories": [ + "build" + ], + "dependencies": [ + "@eslint-community/regexpp", + "@typescript-eslint/scope-manager", + "@typescript-eslint/type-utils", + "@typescript-eslint/utils", + "@typescript-eslint/visitor-keys", + "ignore", + "natural-compare", + "ts-api-utils" + ] + }, + { + "path": "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore", + "name": "ignore", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@typescript-eslint/parser", + "name": "@typescript-eslint/parser", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.66.0.tgz", + "integrity": "sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/scope-manager", + "@typescript-eslint/types", + "@typescript-eslint/typescript-estree", + "@typescript-eslint/visitor-keys", + "debug" + ] + }, + { + "path": "node_modules/@typescript-eslint/project-service", + "name": "@typescript-eslint/project-service", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.66.0.tgz", + "integrity": "sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/tsconfig-utils", + "@typescript-eslint/types", + "debug" + ] + }, + { + "path": "node_modules/@typescript-eslint/scope-manager", + "name": "@typescript-eslint/scope-manager", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.66.0.tgz", + "integrity": "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/types", + "@typescript-eslint/visitor-keys" + ] + }, + { + "path": "node_modules/@typescript-eslint/tsconfig-utils", + "name": "@typescript-eslint/tsconfig-utils", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.66.0.tgz", + "integrity": "sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@typescript-eslint/type-utils", + "name": "@typescript-eslint/type-utils", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.66.0.tgz", + "integrity": "sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/types", + "@typescript-eslint/typescript-estree", + "@typescript-eslint/utils", + "debug", + "ts-api-utils" + ] + }, + { + "path": "node_modules/@typescript-eslint/types", + "name": "@typescript-eslint/types", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.66.0.tgz", + "integrity": "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/@typescript-eslint/typescript-estree", + "name": "@typescript-eslint/typescript-estree", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.66.0.tgz", + "integrity": "sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/project-service", + "@typescript-eslint/tsconfig-utils", + "@typescript-eslint/types", + "@typescript-eslint/visitor-keys", + "debug", + "minimatch", + "semver", + "tinyglobby", + "ts-api-utils" + ] + }, + { + "path": "node_modules/@typescript-eslint/utils", + "name": "@typescript-eslint/utils", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.66.0.tgz", + "integrity": "sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==", + "categories": [ + "build" + ], + "dependencies": [ + "@eslint-community/eslint-utils", + "@typescript-eslint/scope-manager", + "@typescript-eslint/types", + "@typescript-eslint/typescript-estree" + ] + }, + { + "path": "node_modules/@typescript-eslint/visitor-keys", + "name": "@typescript-eslint/visitor-keys", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.66.0.tgz", + "integrity": "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/types", + "eslint-visitor-keys" + ] + }, + { + "path": "node_modules/@vitejs/plugin-react", + "name": "@vitejs/plugin-react", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.5.tgz", + "integrity": "sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==", + "categories": [ + "build" + ], + "dependencies": [ + "@rolldown/pluginutils" + ] + }, + { + "path": "node_modules/acorn", + "name": "acorn", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/acorn-jsx", + "name": "acorn-jsx", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/ajv", + "name": "ajv", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "categories": [ + "build" + ], + "dependencies": [ + "fast-deep-equal", + "fast-json-stable-stringify", + "json-schema-traverse", + "uri-js" + ] + }, + { + "path": "node_modules/axe-core", + "name": "axe-core", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.12.1.tgz", + "integrity": "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==", + "categories": [ + "test" + ], + "dependencies": [] + }, + { + "path": "node_modules/balanced-match", + "name": "balanced-match", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/brace-expansion", + "name": "brace-expansion", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "categories": [ + "build" + ], + "dependencies": [ + "balanced-match" + ] + }, + { + "path": "node_modules/cross-spawn", + "name": "cross-spawn", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "categories": [ + "build" + ], + "dependencies": [ + "path-key", + "shebang-command", + "which" + ] + }, + { + "path": "node_modules/csstype", + "name": "csstype", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/debug", + "name": "debug", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "categories": [ + "build" + ], + "dependencies": [ + "ms" + ] + }, + { + "path": "node_modules/deep-is", + "name": "deep-is", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/detect-libc", + "name": "detect-libc", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/escape-string-regexp", + "name": "escape-string-regexp", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/eslint", + "name": "eslint", + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz", + "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==", + "categories": [ + "build" + ], + "dependencies": [ + "@eslint-community/eslint-utils", + "@eslint-community/regexpp", + "@eslint/config-array", + "@eslint/config-helpers", + "@eslint/core", + "@eslint/plugin-kit", + "@humanfs/node", + "@humanwhocodes/module-importer", + "@humanwhocodes/retry", + "@types/estree", + "ajv", + "cross-spawn", + "debug", + "escape-string-regexp", + "eslint-scope", + "eslint-visitor-keys", + "espree", + "esquery", + "esutils", + "fast-deep-equal", + "file-entry-cache", + "find-up", + "glob-parent", + "ignore", + "imurmurhash", + "is-glob", + "json-stable-stringify-without-jsonify", + "minimatch", + "natural-compare", + "optionator" + ] + }, + { + "path": "node_modules/eslint-scope", + "name": "eslint-scope", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "categories": [ + "build" + ], + "dependencies": [ + "@types/esrecurse", + "@types/estree", + "esrecurse", + "estraverse" + ] + }, + { + "path": "node_modules/eslint-visitor-keys", + "name": "eslint-visitor-keys", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/espree", + "name": "espree", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "categories": [ + "build" + ], + "dependencies": [ + "acorn", + "acorn-jsx", + "eslint-visitor-keys" + ] + }, + { + "path": "node_modules/esquery", + "name": "esquery", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "categories": [ + "build" + ], + "dependencies": [ + "estraverse" + ] + }, + { + "path": "node_modules/esrecurse", + "name": "esrecurse", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "categories": [ + "build" + ], + "dependencies": [ + "estraverse" + ] + }, + { + "path": "node_modules/estraverse", + "name": "estraverse", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/esutils", + "name": "esutils", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/fast-deep-equal", + "name": "fast-deep-equal", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/fast-json-stable-stringify", + "name": "fast-json-stable-stringify", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/fast-levenshtein", + "name": "fast-levenshtein", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/fdir", + "name": "fdir", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/fflate", + "name": "fflate", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/file-entry-cache", + "name": "file-entry-cache", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "categories": [ + "build" + ], + "dependencies": [ + "flat-cache" + ] + }, + { + "path": "node_modules/find-up", + "name": "find-up", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "categories": [ + "build" + ], + "dependencies": [ + "locate-path", + "path-exists" + ] + }, + { + "path": "node_modules/flat-cache", + "name": "flat-cache", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "categories": [ + "build" + ], + "dependencies": [ + "flatted", + "keyv" + ] + }, + { + "path": "node_modules/flatted", + "name": "flatted", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/fsevents", + "name": "fsevents", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/glob-parent", + "name": "glob-parent", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "categories": [ + "build" + ], + "dependencies": [ + "is-glob" + ] + }, + { + "path": "node_modules/ignore", + "name": "ignore", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/imurmurhash", + "name": "imurmurhash", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/is-extglob", + "name": "is-extglob", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/is-glob", + "name": "is-glob", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "categories": [ + "build" + ], + "dependencies": [ + "is-extglob" + ] + }, + { + "path": "node_modules/isexe", + "name": "isexe", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/json-buffer", + "name": "json-buffer", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/json-schema-traverse", + "name": "json-schema-traverse", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/json-stable-stringify-without-jsonify", + "name": "json-stable-stringify-without-jsonify", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/keyv", + "name": "keyv", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "categories": [ + "build" + ], + "dependencies": [ + "json-buffer" + ] + }, + { + "path": "node_modules/levn", + "name": "levn", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "categories": [ + "build" + ], + "dependencies": [ + "prelude-ls", + "type-check" + ] + }, + { + "path": "node_modules/lightningcss", + "name": "lightningcss", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "categories": [ + "build" + ], + "dependencies": [ + "detect-libc", + "lightningcss-android-arm64", + "lightningcss-darwin-arm64", + "lightningcss-darwin-x64", + "lightningcss-freebsd-x64", + "lightningcss-linux-arm-gnueabihf", + "lightningcss-linux-arm64-gnu", + "lightningcss-linux-arm64-musl", + "lightningcss-linux-x64-gnu", + "lightningcss-linux-x64-musl", + "lightningcss-win32-arm64-msvc", + "lightningcss-win32-x64-msvc" + ] + }, + { + "path": "node_modules/lightningcss-android-arm64", + "name": "lightningcss-android-arm64", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-darwin-arm64", + "name": "lightningcss-darwin-arm64", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-darwin-x64", + "name": "lightningcss-darwin-x64", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-freebsd-x64", + "name": "lightningcss-freebsd-x64", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-linux-arm-gnueabihf", + "name": "lightningcss-linux-arm-gnueabihf", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-linux-arm64-gnu", + "name": "lightningcss-linux-arm64-gnu", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-linux-arm64-musl", + "name": "lightningcss-linux-arm64-musl", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-linux-x64-gnu", + "name": "lightningcss-linux-x64-gnu", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-linux-x64-musl", + "name": "lightningcss-linux-x64-musl", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-win32-arm64-msvc", + "name": "lightningcss-win32-arm64-msvc", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/lightningcss-win32-x64-msvc", + "name": "lightningcss-win32-x64-msvc", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/locate-path", + "name": "locate-path", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "categories": [ + "build" + ], + "dependencies": [ + "p-locate" + ] + }, + { + "path": "node_modules/meshoptimizer", + "name": "meshoptimizer", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz", + "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/minimatch", + "name": "minimatch", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "categories": [ + "build" + ], + "dependencies": [ + "brace-expansion" + ] + }, + { + "path": "node_modules/ms", + "name": "ms", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/nanoid", + "name": "nanoid", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/natural-compare", + "name": "natural-compare", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/optionator", + "name": "optionator", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "categories": [ + "build" + ], + "dependencies": [ + "deep-is", + "fast-levenshtein", + "levn", + "prelude-ls", + "type-check", + "word-wrap" + ] + }, + { + "path": "node_modules/p-limit", + "name": "p-limit", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "categories": [ + "build" + ], + "dependencies": [ + "yocto-queue" + ] + }, + { + "path": "node_modules/p-locate", + "name": "p-locate", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "categories": [ + "build" + ], + "dependencies": [ + "p-limit" + ] + }, + { + "path": "node_modules/path-exists", + "name": "path-exists", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/path-key", + "name": "path-key", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/picocolors", + "name": "picocolors", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/picomatch", + "name": "picomatch", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/playwright", + "name": "playwright", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", + "categories": [ + "test" + ], + "dependencies": [ + "fsevents", + "playwright-core" + ] + }, + { + "path": "node_modules/playwright-core", + "name": "playwright-core", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "categories": [ + "test" + ], + "dependencies": [] + }, + { + "path": "node_modules/playwright/node_modules/fsevents", + "name": "fsevents", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "categories": [ + "test" + ], + "dependencies": [] + }, + { + "path": "node_modules/postcss", + "name": "postcss", + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "categories": [ + "build" + ], + "dependencies": [ + "nanoid", + "picocolors", + "source-map-js" + ] + }, + { + "path": "node_modules/prelude-ls", + "name": "prelude-ls", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/punycode", + "name": "punycode", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/react", + "name": "react", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "categories": [ + "production" + ], + "dependencies": [] + }, + { + "path": "node_modules/react-dom", + "name": "react-dom", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "categories": [ + "production" + ], + "dependencies": [ + "scheduler" + ] + }, + { + "path": "node_modules/rolldown", + "name": "rolldown", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", + "categories": [ + "build" + ], + "dependencies": [ + "@oxc-project/types", + "@rolldown/binding-android-arm64", + "@rolldown/binding-darwin-arm64", + "@rolldown/binding-darwin-x64", + "@rolldown/binding-freebsd-x64", + "@rolldown/binding-linux-arm-gnueabihf", + "@rolldown/binding-linux-arm64-gnu", + "@rolldown/binding-linux-arm64-musl", + "@rolldown/binding-linux-ppc64-gnu", + "@rolldown/binding-linux-s390x-gnu", + "@rolldown/binding-linux-x64-gnu", + "@rolldown/binding-linux-x64-musl", + "@rolldown/binding-openharmony-arm64", + "@rolldown/binding-win32-arm64-msvc", + "@rolldown/binding-win32-x64-msvc", + "@rolldown/pluginutils" + ] + }, + { + "path": "node_modules/scheduler", + "name": "scheduler", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "categories": [ + "production" + ], + "dependencies": [] + }, + { + "path": "node_modules/semver", + "name": "semver", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/shebang-command", + "name": "shebang-command", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "categories": [ + "build" + ], + "dependencies": [ + "shebang-regex" + ] + }, + { + "path": "node_modules/shebang-regex", + "name": "shebang-regex", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/source-map-js", + "name": "source-map-js", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/tinyglobby", + "name": "tinyglobby", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "categories": [ + "build" + ], + "dependencies": [ + "fdir", + "picomatch" + ] + }, + { + "path": "node_modules/ts-api-utils", + "name": "ts-api-utils", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/type-check", + "name": "type-check", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "categories": [ + "build" + ], + "dependencies": [ + "prelude-ls" + ] + }, + { + "path": "node_modules/typescript", + "name": "typescript", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/typescript-eslint", + "name": "typescript-eslint", + "version": "8.66.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.66.0.tgz", + "integrity": "sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==", + "categories": [ + "build" + ], + "dependencies": [ + "@typescript-eslint/eslint-plugin", + "@typescript-eslint/parser", + "@typescript-eslint/typescript-estree", + "@typescript-eslint/utils" + ] + }, + { + "path": "node_modules/uri-js", + "name": "uri-js", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "categories": [ + "build" + ], + "dependencies": [ + "punycode" + ] + }, + { + "path": "node_modules/vite", + "name": "vite", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz", + "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==", + "categories": [ + "build" + ], + "dependencies": [ + "fsevents", + "lightningcss", + "picomatch", + "postcss", + "rolldown", + "tinyglobby" + ] + }, + { + "path": "node_modules/which", + "name": "which", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "categories": [ + "build" + ], + "dependencies": [ + "isexe" + ] + }, + { + "path": "node_modules/word-wrap", + "name": "word-wrap", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "categories": [ + "build" + ], + "dependencies": [] + }, + { + "path": "node_modules/yocto-queue", + "name": "yocto-queue", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "categories": [ + "build" + ], + "dependencies": [] + } + ], + "nextTask": "M13-05D" +} diff --git a/tests/golden/WBV2-P10-001/inventory-rebaseline-report.json b/tests/golden/WBV2-P10-001/inventory-rebaseline-report.json new file mode 100644 index 000000000..cc61169e5 --- /dev/null +++ b/tests/golden/WBV2-P10-001/inventory-rebaseline-report.json @@ -0,0 +1,47 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-001", + "operation": "RECONCILE_WBV2_INVENTORY_SOURCE_DRIFT", + "status": "PASS", + "historical": { + "sourceHashes": "tests/golden/WBV2-P0-002/source-hashes.json", + "sourceHashesSha256": "c6c6260d10bc8529e4b26563ce81168e1b0fffb3b175b2d4998ec1c0aa1c1497", + "manifestsRewritten": false, + "baselinePreserved": true + }, + "currentSourceBaseline": { + "path": "tests/golden/WBV2-P10-001/current-source-hashes.json", + "sha256": "d93dd22e430cfc6c03cb8819ff71c3bfd9b92a818cc078dec0dcbe53e9cbb39c", + "planPath": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "planSha256": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782" + }, + "drift": { + "count": 1, + "entries": [ + { + "file": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "expected": "c14e01161876ab924c1fe68466c78481fb583d1b822399ffa9f1df1b1d6fb266", + "actual": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782", + "classification": "AUTHORIZED_MUTABLE_PLAN" + } + ], + "onlyAuthorizedMutablePlan": true + }, + "dependency": { + "historicalInventory": "tests/golden/M13-05C/dependency-inventory.json", + "currentInventory": "tests/golden/WBV2-P10-001/dependency-inventory.current.json", + "packageCount": 144, + "packageHashChanged": true, + "lockfileHashStable": true, + "rootsStable": true, + "closureStable": true, + "packagesAdded": 0 + }, + "policy": { + "historicalP0Unchanged": true, + "historicalP8Unchanged": true, + "additiveCurrentBaseline": true, + "falseHistoricalRestoration": false + }, + "nextTask": "WBV2-P10-002" +} diff --git a/tests/golden/WBV2-P10-001/manifest.json b/tests/golden/WBV2-P10-001/manifest.json new file mode 100644 index 000000000..da2b43286 --- /dev/null +++ b/tests/golden/WBV2-P10-001/manifest.json @@ -0,0 +1,74 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-001", + "parentTask": "WBV2-P10-000", + "operation": "RECONCILE_WBV2_INVENTORY_SOURCE_DRIFT", + "status": "done", + "enablingTask": true, + "parityStateChange": false, + "artifacts": { + "parentManifest": { + "path": "tests/golden/WBV2-P10-000/manifest.json", + "sha256": "269acf27b93097887e8b475b53fbbfae4c7d9c653dd4b6c5921258db86576de0" + }, + "historicalSourceHashes": { + "path": "tests/golden/WBV2-P0-002/source-hashes.json", + "sha256": "c6c6260d10bc8529e4b26563ce81168e1b0fffb3b175b2d4998ec1c0aa1c1497" + }, + "historicalDependencyManifest": { + "path": "tests/golden/M13-05C/manifest.json", + "sha256": "24abe1863de8fcb112434fb3226986f3a7072820cde8869dadb8fbad32d1e6c1" + }, + "historicalRecoveryReport": { + "path": "tests/golden/WBV2-P8-001/recovery-baseline-report.json", + "sha256": "33491669cc094c5f698cac734ed49a81dca7bc0fa2e65a0024542215bf8bda73" + }, + "currentSourceHashes": { + "path": "tests/golden/WBV2-P10-001/current-source-hashes.json", + "sha256": "d93dd22e430cfc6c03cb8819ff71c3bfd9b92a818cc078dec0dcbe53e9cbb39c" + }, + "currentDependencyInventory": { + "path": "tests/golden/WBV2-P10-001/dependency-inventory.current.json", + "sha256": "5a9ecfbd811199827b46fcd1ac5c2e170667d5f0765d1995ad9e4b42e02addb4" + }, + "sourcePlan": { + "path": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "sha256": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782" + }, + "generator": { + "path": "tools/web/generate-wbv2-inventory-rebaseline.mjs", + "sha256": "184d67e6af71bd1b8d05b8900bbdbb2eddd4971a7bfadfe56e3775f388b086fa" + }, + "checker": { + "path": "tools/web/check-wbv2-inventory-rebaseline.mjs", + "sha256": "6e02cfdc44a2cb4815837e33f18e18d77cd3ad8697394f5e3615a2b359ee3e9f" + }, + "report": { + "path": "tests/golden/WBV2-P10-001/inventory-rebaseline-report.json", + "sha256": "caeabb45d0f7b7b1f4a94481b9c0f9747e38f22e0adeb34874bce452117f2c0a" + }, + "status": { + "path": "docs/status/WBV2-P10-001.md", + "sha256": "d93f37dd1bc0bd320b2477a807c228c333027b9bf35ef8c770eddd073470245a" + }, + "parityPlan": { + "path": "tests/golden/WBV2-P10-001/native-parity-task-plan.json", + "sha256": "1dc85326304c28ded4bdd12ff905de7522bcd61d783bf4adf20ac628432a7512" + }, + "taskContext": { + "path": "tests/golden/WBV2-P10-001/task-context.json", + "sha256": "0be0f326fb603e98084b7c0e26316fac00a39f6090970070b7582927072708c6" + } + }, + "assertions": { + "historicalP0Preserved": true, + "historicalP8Preserved": true, + "authorizedPlanDrift": 1, + "currentBaseline": true, + "dependencyPackages": 144, + "dependencyClosureStable": true, + "lockfileStable": true, + "nextEngineTask": "WBV2-P10-002" + }, + "nextTask": "WBV2-P10-002" +} diff --git a/tests/golden/WBV2-P10-001/native-parity-task-plan.json b/tests/golden/WBV2-P10-001/native-parity-task-plan.json new file mode 100644 index 000000000..ab219ecc6 --- /dev/null +++ b/tests/golden/WBV2-P10-001/native-parity-task-plan.json @@ -0,0 +1,1567 @@ +{ + "schemaVersion": 1, + "planId": "BLENDER_WEB_PARITY_V2_NATIVE_ENGINE_EPOCH_1", + "status": "ACTIVE_NATIVE_ENGINE_QUEUE", + "authority": "queue_reactivated_after_p9_bounded_parity", + "productContract": "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "sourcePlan": "docs/BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md", + "executionPointer": "docs/EXECUTION_QUEUE.md", + "correctiveCheckpoint": { + "task": "C6-003", + "handoff": "tests/golden/corrective/C6-003/handoff.json", + "status": "active", + "blocker": null, + "queueMutation": true, + "legacyTask": "M16-GAP-00277", + "legacyParentNextTask": "M16-GAP-00277" + }, + "runtimePolicy": { + "blenderSource": "blender-5.2.0", + "browserEvidence": [ + "chromium" + ], + "forbiddenBrowsers": [ + "firefox", + "webkit" + ], + "mainAuthority": "blender_main", + "storage": [ + "opfs", + "indexeddb" + ], + "queueMutation": "enabled_after_owner_review_and_g5" + }, + "completionClasses": [ + "LOCAL_EXACT", + "LOCAL_BOUNDED", + "SERVER_EXACT", + "EXCLUDED" + ], + "gates": [ + { + "id": "G0", + "name": "scope_and_inventory", + "requires": [ + "contract", + "inventory", + "capability_matrix" + ] + }, + { + "id": "G1", + "name": "runtime_foundation", + "requires": [ + "sceneir", + "main_transaction", + "worker_lifecycle", + "storage_journal" + ] + }, + { + "id": "G2", + "name": "feature_parity", + "requires": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence" + ] + }, + { + "id": "G3", + "name": "recovery_and_security", + "requires": [ + "cancel", + "restart", + "oom_quota", + "malformed", + "dispose" + ] + }, + { + "id": "G4", + "name": "release_candidate", + "requires": [ + "offline", + "ci", + "sbom", + "rollback", + "hashes" + ] + }, + { + "id": "G5", + "name": "queue_mutation", + "requires": [ + "owner_review", + "protected_hashes", + "handoff", + "single_ready_task" + ] + } + ], + "waves": [ + { + "id": "P0", + "name": "facts_and_contracts", + "gate": "G0", + "tasks": [ + "WBV2-P0-001", + "WBV2-P0-002", + "WBV2-P0-003" + ] + }, + { + "id": "P1", + "name": "runtime_foundation", + "gate": "G1", + "tasks": [ + "WBV2-P1-001", + "WBV2-P1-002", + "WBV2-P1-003", + "WBV2-P1-004", + "WBV2-P1-005" + ] + }, + { + "id": "P2", + "name": "core_modeler_loop", + "gate": "G2", + "tasks": [ + "WBV2-P2-001", + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P2-005" + ] + }, + { + "id": "P3", + "name": "authoring_and_io", + "gate": "G2", + "tasks": [ + "WBV2-P3-001", + "WBV2-P3-002", + "WBV2-P3-003", + "WBV2-P3-004", + "WBV2-P3-005" + ] + }, + { + "id": "P4", + "name": "advanced_local_slices", + "gate": "G2", + "tasks": [ + "WBV2-P4-001", + "WBV2-P4-002", + "WBV2-P4-003", + "WBV2-P4-004" + ] + }, + { + "id": "P5", + "name": "render_and_server", + "gate": "G3", + "tasks": [ + "WBV2-P5-001", + "WBV2-P5-002", + "WBV2-P5-003" + ] + }, + { + "id": "P6", + "name": "security_performance_release", + "gate": "G4", + "tasks": [ + "WBV2-P6-001", + "WBV2-P6-002", + "WBV2-P6-003" + ] + }, + { + "id": "P7", + "name": "full_parity_gap_program", + "gate": "G5", + "tasks": [ + "WBV2-P7-001", + "WBV2-P7-002", + "WBV2-P7-003" + ] + } + ], + "taskContract": { + "onePrimaryBehavior": true, + "requiredEvidence": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence", + "manifest", + "status" + ], + "requiredCommands": [ + "focused", + "determinism", + "hash", + "governance" + ], + "failureState": "in_progress_or_blocked", + "successorRule": "only_from_parent_manifest_nextTask" + }, + "tasks": [ + { + "id": "WBV2-P0-001", + "phase": "P0", + "title": "reconcile_scope_and_checkpoints", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-governance", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-001.md", + "behavior": "Freeze V1/full-parity boundary and reconcile legacy/corrective pointers without queue mutation.", + "outputs": [ + "scope decision", + "checkpoint report", + "protected hash set" + ], + "acceptance": [ + "corrective owner-review status is explicit", + "legacy parent pointer is unchanged", + "plan has one activation gate" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-002", + "phase": "P0", + "title": "generate_blender52_inventory_and_parity_map", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-inventory", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-002.md", + "behavior": "Generate stable Blender 5.2 data-block/operator/editor/node/format inventory and map every entry to a completion class.", + "outputs": [ + "inventory", + "parity map", + "source hash" + ], + "acceptance": [ + "unknown entries are classified", + "inventory is deterministic", + "no entry claims feature parity without evidence" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-003", + "phase": "P0", + "title": "freeze_capability_error_budget_contract", + "kind": "enabling", + "owner": "PROTOCOL", + "dependsOn": [ + "WBV2-P0-001", + "WBV2-P0-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-contract", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-003.md", + "behavior": "Freeze capability levels, stable error codes, revision, budget, cancellation and loss-report schemas.", + "outputs": [ + "versioned protocol", + "capability matrix", + "negative matrix" + ], + "acceptance": [ + "unsupported input fails closed", + "schema hashes are stable", + "migration policy preserves unknown data" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-001", + "phase": "P1", + "title": "stabilize_runtime_variants_and_source_receipts", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P0-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-runtime", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-001.md", + "behavior": "Bind single-thread/pthread WebEngine variants to pinned Blender source/build/runtime receipts.", + "outputs": [ + "runtime manifest", + "variant selector", + "fallback report" + ], + "acceptance": [ + "variant fallback is deterministic", + "source/build hash is verified", + "one engine session has one generation" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-002", + "phase": "P1", + "title": "unify_sceneir_stable_ids_and_binary_deltas", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-001" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-sceneir", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-002.md", + "behavior": "Make SceneIR/WBG1 stable IDs, topology/attribute domains and binary/range deltas canonical across desktop and WASM.", + "outputs": [ + "SceneIR schema", + "binary fixture", + "delta comparator" + ], + "acceptance": [ + "IDs survive save/reopen", + "malformed chunk is rejected", + "desktop and WASM canonical hashes match" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-003", + "phase": "P1", + "title": "unify_main_transaction_history_and_save", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-002" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-history", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-003.md", + "behavior": "Use one Main transaction/revision/history contract for commit, undo/redo, atomic save and reopen.", + "outputs": [ + "transaction contract", + "history receipt", + "save/reopen runner" + ], + "acceptance": [ + "failed/no-op commands add no history", + "stale revision cannot commit", + "reopen state is byte/hash stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-004", + "phase": "P1", + "title": "harden_worker_cancel_restart_and_dispose", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P1-001", + "WBV2-P1-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-lifecycle", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-004.md", + "behavior": "Make cancellation, late-result rejection, Worker restart and resource disposal common to all domains.", + "outputs": [ + "lifecycle runner", + "fault report", + "dispose counters" + ], + "acceptance": [ + "cancel never publishes result", + "generation mismatch is rejected", + "CPU/WASM/GPU owners return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-005", + "phase": "P1", + "title": "harden_opfs_indexeddb_journal_recovery", + "kind": "enabling", + "owner": "STORAGE", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P1-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-storage", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-005.md", + "behavior": "Unify OPFS staging/content addressing and IndexedDB metadata/journal recovery.", + "outputs": [ + "storage schema", + "crash fixtures", + "recovery checker" + ], + "acceptance": [ + "interrupted commit leaves old project usable", + "hash mismatch quarantines payload", + "small project recovers after restart" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-001", + "phase": "P2", + "title": "open_blend_scene_context_and_outliner", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P1-005" + ], + "parityId": "EDITOR.OPEN_SCENE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-editor", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-001.md", + "behavior": "Open a minimal .blend and expose scene/object/collection context from authoritative Main.", + "outputs": [ + "desktop fixture", + "outliner report", + "Chromium path" + ], + "acceptance": [ + "stable IDs and selection revision match", + "missing data is structured", + "reopen preserves context" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-002", + "phase": "P2", + "title": "object_collection_parent_transform_workflow", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P2-001" + ], + "parityId": "OBJECT.TRANSFORM_HIERARCHY", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-scene", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-002.md", + "behavior": "Edit object transform, collection membership and parent hierarchy through Main transactions.", + "outputs": [ + "desktop/WASM golden", + "negative cases", + "save/reopen receipt" + ], + "acceptance": [ + "world matrix parity", + "cycle/locked/library edits reject", + "undo/redo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-003", + "phase": "P2", + "title": "mesh_edit_core_operations", + "kind": "feature", + "owner": "MESH", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P2-002" + ], + "parityId": "MESH.EDIT_CORE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-mesh", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-003.md", + "behavior": "Expose bounded vertex/edge/face selection plus merge/dissolve/extrude/inset/bevel/loop-cut.", + "outputs": [ + "Blender fixture set", + "topology comparator", + "Chromium edit path" + ], + "acceptance": [ + "topology/attributes match", + "invalid selection and budget fail closed", + "single transaction and reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-004", + "phase": "P2", + "title": "dual_viewport_sceneir_render_path", + "kind": "feature", + "owner": "VIEWPORT", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P2-003" + ], + "parityId": "VIEWPORT.MAIN_OFFSCREEN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-viewport", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-004.md", + "behavior": "Render the same validated SceneIR through main-thread WebGL2 and OffscreenCanvas Worker paths.", + "outputs": [ + "pixel report", + "viewport diagnostics", + "device recovery" + ], + "acceptance": [ + "both paths have nonblank pixels", + "selection/camera revision is shared", + "device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-005", + "phase": "P2", + "title": "close_p0_user_loop", + "kind": "feature", + "owner": "INTEGRATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P1-005", + "WBV2-P2-004" + ], + "parityId": "WORKFLOW.P0_USER_LOOP", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-integration", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-005.md", + "behavior": "Prove open -> edit -> undo -> redo -> save -> restart -> reopen -> GLB in one production flow.", + "outputs": [ + "P0 workflow report", + "release binding", + "rollback receipt" + ], + "acceptance": [ + "Main revision and exported asset are bound", + "fault/cancel leaves old state", + "Chromium production path passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-001", + "phase": "P3", + "title": "material_uv_principled_asset_workflow", + "kind": "feature", + "owner": "MATERIAL", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005" + ], + "parityId": "MATERIAL.PBR_UV", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-001.md", + "behavior": "Edit material slots, UVs and declared Principled/Image/Normal graph nodes with content-addressed textures.", + "outputs": [ + "material golden", + "texture receipt", + "loss report" + ], + "acceptance": [ + "desktop/WASM node fields match", + "unsupported node retained/blocked", + "packed asset survives reopen" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-002", + "phase": "P3", + "title": "keyframe_timeline_action_workflow", + "kind": "feature", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-005", + "WBV2-P3-001" + ], + "parityId": "ANIMATION.TRS_ACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-002.md", + "behavior": "Create/edit TRS keyframes, timeline and declared Action interpolation through Main.", + "outputs": [ + "frame golden", + "animation comparator", + "reopen report" + ], + "acceptance": [ + "sampled values and handles match", + "stale frame result rejected", + "undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-003", + "phase": "P3", + "title": "armature_pose_constraint_skin_workflow", + "kind": "feature", + "owner": "RIG", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P3-002" + ], + "parityId": "RIG.POSE_SKIN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-rig", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-003.md", + "behavior": "Read and edit declared armature pose/constraint/weight/shape-key slices with bounded evaluation.", + "outputs": [ + "pose golden", + "skin report", + "unsupported matrix" + ], + "acceptance": [ + "pose matrices and weights match", + "unsupported constraint is explicit", + "save/reopen and small recovery pass" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-004", + "phase": "P3", + "title": "glb_roundtrip_and_loss_report", + "kind": "feature", + "owner": "IO", + "dependsOn": [ + "WBV2-P2-005", + "WBV2-P3-001", + "WBV2-P3-003" + ], + "parityId": "IO.GLB_ROUNDTRIP", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-io", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-004.md", + "behavior": "Import/export declared GLB mesh/PBR/texture/morph/skin/animation and report non-mapped semantics.", + "outputs": [ + "GLB fixtures", + "desktop reimport report", + "loss report" + ], + "acceptance": [ + "roundtrip canonical graph matches", + "sparse/external URI/budget negatives reject", + "no silent loss" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-005", + "phase": "P3", + "title": "library_asset_append_link_override", + "kind": "feature", + "owner": "ASSET", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P2-001", + "WBV2-P3-004" + ], + "parityId": "ASSET.LIBRARY_OPERATIONS", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-assets", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-005.md", + "behavior": "Support declared append/link/override ownership, reload and missing-library semantics.", + "outputs": [ + "library fixtures", + "ownership report", + "negative matrix" + ], + "acceptance": [ + "source/hash/owner identity preserved", + "linked mutation blocked", + "stale generation and missing source fail closed" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-001", + "phase": "P4", + "title": "modifier_graph_and_apply_slices", + "kind": "feature", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005", + "WBV2-P3-005" + ], + "parityId": "MODIFIER.DECLARED_SLICES", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-001.md", + "behavior": "Enable one declared modifier parameter/apply workflow at a time with dependency-aware blocking.", + "outputs": [ + "modifier goldens", + "dependency report", + "negative cases" + ], + "acceptance": [ + "desktop/evaluated Main match", + "unknown modifier retained and blocked", + "apply/undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-002", + "phase": "P4", + "title": "geometry_nodes_and_shader_allowlist", + "kind": "feature", + "owner": "NODES", + "dependsOn": [ + "WBV2-P3-001", + "WBV2-P4-001" + ], + "parityId": "NODES.ALLOWLIST", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-002.md", + "behavior": "Read/write/evaluate only declared Geometry Nodes and shader graph allowlists with resource budgets.", + "outputs": [ + "node fixtures", + "compile/cache receipts", + "unsupported graph reports" + ], + "acceptance": [ + "node/socket/link/default parity", + "budget and unknown-node block before commit", + "compile failure rolls back" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-003", + "phase": "P4", + "title": "sculpt_nonmesh_and_paint_bounded_slices", + "kind": "feature", + "owner": "SCULPT", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P4-002" + ], + "parityId": "SCULPT.NONMESH.PAINT_BOUNDED", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-003.md", + "behavior": "Expose declared sculpt attributes/strokes, Curve/Surface/Font/PointCloud and paint slices with explicit PBVH limits.", + "outputs": [ + "non-mesh fixtures", + "stroke report", + "capability blocks" + ], + "acceptance": [ + "Main commit is atomic", + "unsupported brush/solver returns stable code", + "GPU/OOM/restart recovery passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-004", + "phase": "P4", + "title": "simulation_cache_identity_and_lifecycle", + "kind": "feature", + "owner": "SIMULATION", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P4-002", + "WBV2-P4-003" + ], + "parityId": "SIMULATION.CACHE_LIFECYCLE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G3", + "card": "docs/tasks/WBV2-P4-004.md", + "behavior": "Bind declared simulation cache to source/settings/revision hashes with cancellation, LRU and restart recovery.", + "outputs": [ + "cache fixtures", + "identity report", + "quarantine evidence" + ], + "acceptance": [ + "stale/corrupt cache never publishes", + "small cache recovers after restart", + "budget release is observable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-001", + "phase": "P5", + "title": "render_capability_routing", + "kind": "feature", + "owner": "RENDER", + "dependsOn": [ + "WBV2-P2-004", + "WBV2-P4-002", + "WBV2-P4-004" + ], + "parityId": "RENDER.ROUTING", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-001.md", + "behavior": "Route bounded Eevee/WebGL capabilities locally and unsupported render classes to SERVER_EXACT or EXCLUDED.", + "outputs": [ + "render receipts", + "pixel golden", + "routing report" + ], + "acceptance": [ + "source/settings/build identity bound", + "unsupported route cannot pretend local success", + "cancel/device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-002", + "phase": "P5", + "title": "compositor_sequencer_media_recovery", + "kind": "feature", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P3-002", + "WBV2-P5-001" + ], + "parityId": "MEDIA.BOUNDED_WORKFLOW", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-002.md", + "behavior": "Provide declared compositor/sequencer/codec/proxy/audio slices with revision and recovery gates.", + "outputs": [ + "media receipts", + "recovery report", + "audio/session diagnostics" + ], + "acceptance": [ + "seek/decode revision ordering", + "cancel/timeout does not publish", + "quota/OOM/restart leaves project valid" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-003", + "phase": "P5", + "title": "server_job_result_binding", + "kind": "feature", + "owner": "SERVER", + "dependsOn": [ + "WBV2-P0-003", + "WBV2-P5-001", + "WBV2-P5-002" + ], + "parityId": "SERVER.JOB_BINDING", + "implementationClass": "SERVER_EXACT", + "parallelGroup": "p5-server", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-003.md", + "behavior": "Bind server render/encode/physics jobs to immutable input/settings/build/output hashes and explicit lifecycle states.", + "outputs": [ + "server protocol", + "idempotency receipt", + "negative matrix" + ], + "acceptance": [ + "duplicate request is idempotent", + "stale result cannot bind", + "timeout/cancel/OOM produces no READY output" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-001", + "phase": "P6", + "title": "scripting_default_deny_and_audit", + "kind": "feature", + "owner": "SECURITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P5-003" + ], + "parityId": "SECURITY.SCRIPTING", + "implementationClass": "EXCLUDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-001.md", + "behavior": "Read text/metadata and expose audited, budgeted, default-deny script policy without arbitrary execution.", + "outputs": [ + "policy manifest", + "malicious fixtures", + "audit report" + ], + "acceptance": [ + "autorun/network/add-on defaults deny", + "sandbox cancellation/dispose works", + "no secret or filesystem escape" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-002", + "phase": "P6", + "title": "performance_fault_and_recovery_matrix", + "kind": "enabling", + "owner": "RELIABILITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P1-005", + "WBV2-P2-004", + "WBV2-P6-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-002.md", + "behavior": "Run deterministic geometry/texture/media/cache budgets and inject OOM/quota/device/network faults.", + "outputs": [ + "budget matrix", + "fault reports", + "resource release ledger" + ], + "acceptance": [ + "100k/1M/10M thresholds recorded", + "fault leaves old revision usable", + "all owned resources return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-003", + "phase": "P6", + "title": "offline_ci_sbom_and_rollback_release", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P6-001", + "WBV2-P6-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-release", + "gate": "G4", + "card": "docs/tasks/WBV2-P6-003.md", + "behavior": "Produce reproducible offline/source/binary release packages with CI lanes, SBOM and rollback evidence.", + "outputs": [ + "RC manifest", + "offline archive", + "CI reports" + ], + "acceptance": [ + "quick/Chromium/release lanes pass", + "artifact hashes reproduce", + "upgrade/rollback and known limitations are tested" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-001", + "phase": "P7", + "title": "cluster_full_blender_gap_inventory", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-002", + "WBV2-P6-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-001.md", + "behavior": "Cluster remaining Blender 5.2 data-block/operator/editor/node/format gaps by family and evidence class.", + "outputs": [ + "cluster catalog", + "coverage report", + "risk ranking" + ], + "acceptance": [ + "each gap has stable ID and owner", + "negative-only/unsupported is not positive parity", + "clusters are deterministic" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-002", + "phase": "P7", + "title": "generate_atomic_family_gap_queue", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-002.md", + "behavior": "Generate one task per parityId x observable behavior x implementation class with parent/hash context.", + "outputs": [ + "task index", + "task catalog", + "task cards" + ], + "acceptance": [ + "one active ready task", + "no guessed successor", + "each card fits context budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-003", + "phase": "P7", + "title": "full_parity_candidate_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P7-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P7-003.md", + "behavior": "Recompute parity closure, evidence health, recovery health and release decision from machine manifests.", + "outputs": [ + "parity release report", + "known limitations", + "final decision" + ], + "acceptance": [ + "all claims bind to evidence", + "blocked/excluded/server classes remain explicit", + "queue and protected hashes pass" + ], + "status": "blocked", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-000", + "phase": "P8", + "title": "authorize_recovery_capability_root", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-000.md", + "behavior": "Authorize a recovery epoch without rewriting the blocked P7 manifest.", + "outputs": [ + "recovery plan", + "root manifest", + "queue authorization" + ], + "acceptance": [ + "P7 evidence remains hash exact", + "recovery scope is explicit", + "one recovery task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P8-001", + "phase": "P8", + "title": "rebaseline_mutable_inventories", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-001.md", + "behavior": "Rebaseline mutable WBV2 plan and dependency inventory inputs while preserving historical manifests.", + "outputs": [ + "semantic drift report", + "current inventory baseline", + "manifest" + ], + "acceptance": [ + "only expected mutable hashes drift", + "dependency closure is unchanged", + "historical manifests remain unmodified" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-002", + "phase": "P8", + "title": "close_atomic_chromium_receipts", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P8-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-receipts", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-002.md", + "behavior": "Produce and bind all 45 atomic Chromium family receipts.", + "outputs": [ + "Chromium report", + "45 receipt index", + "receipt manifests" + ], + "acceptance": [ + "45 receipts are manifest-bound", + "desktop/WASM/save-reopen behaviors are explicit", + "Chromium is the only browser" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-003", + "phase": "P8", + "title": "authorize_m12_provenance_epoch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-provenance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-003.md", + "behavior": "Bind restored M12 sources and explicitly rebaseline unavailable originals in a new provenance epoch.", + "outputs": [ + "provenance epoch", + "replacement bindings", + "manifest" + ], + "acceptance": [ + "22 restored originals stay exact", + "62 unavailable entries are not called restored", + "all replacements are hash-bound" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-004", + "phase": "P8", + "title": "recompute_recovery_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P8-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-004.md", + "behavior": "Recompute the release decision from the recovery epoch and atomic receipts.", + "outputs": [ + "release gate", + "known limitations", + "final manifest" + ], + "acceptance": [ + "all receipts bind to manifests", + "provenance epoch is explicit", + "all governance gates pass" + ], + "status": "in_progress", + "ready": false, + "queueMutationAllowed": false + }, + { + "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": "done", + "ready": false, + "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": "done", + "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": "done", + "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": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-000", + "phase": "P10", + "title": "authorize_native_engine_parity_continuation", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P9-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-governance", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-000.md", + "behavior": "Authorize native Blender/WASM engine parity continuation after bounded Chromium capability evidence.", + "outputs": [ + "continuation receipt", + "native parity plan", + "scope limits" + ], + "acceptance": [ + "P9 evidence remains hash-bound", + "native build/runtime is explicit", + "one native parity task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P10-001", + "phase": "P10", + "title": "reconcile_wbv2_inventory_source_drift", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-inventory", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-001.md", + "behavior": "Record the authorized mutable WBV2 plan drift and prove dependency closure stability without rewriting historical P0 evidence.", + "outputs": [ + "current source hash baseline", + "drift report", + "checker compatibility" + ], + "acceptance": [ + "historical P0 hashes remain unchanged", + "only authorized plan drift is recorded", + "dependency roots/lockfile/closure remain stable", + "inventory checker passes using current baseline" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-002", + "phase": "P10", + "title": "bind_native_and_wasm_engine_receipts", + "kind": "feature", + "owner": "ENGINE", + "dependsOn": [ + "WBV2-P10-001" + ], + "parityId": "ENGINE.NATIVE_WASM_BRIDGE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p10-engine", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-002.md", + "behavior": "Bind Mesh, Modifier, and Asset Catalog receipts to the compiled Blender native binary and web_engine.wasm runtime.", + "outputs": [ + "native receipt", + "WASM receipt", + "Chromium engine report" + ], + "acceptance": [ + "native Blender binary is source-bound", + "WASM binary and JS are hash-bound", + "same mutation reaches real engine/Main", + "save/reopen and failures remain exact" + ], + "status": "in_progress", + "ready": true, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-003", + "phase": "P10", + "title": "expand_core_module_operator_matrix", + "kind": "feature", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-002" + ], + "parityId": "CORE.MODULE_MATRIX", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-matrix", + "gate": "G7", + "card": "docs/tasks/WBV2-P10-003.md", + "behavior": "Expand the three proven capability modules with data-driven operator coverage and aggregate regression receipts.", + "outputs": [ + "module matrix", + "shard reports", + "aggregate manifest" + ], + "acceptance": [ + "positive cases are L2+", + "negative cases do not mutate Main", + "shards use one catalog hash", + "unmapped and retained-negative cases stay explicit" + ], + "status": "planned", + "ready": false, + "queueMutationAllowed": false + } + ], + "parentPlan": { + "path": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "sha256": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782" + }, + "recoveryRoot": "WBV2-P10-000", + "parentRecoveryPlan": { + "path": "tests/golden/WBV2-P10-000/native-parity-task-plan.json", + "sha256": "b72c6fd251f0c2c7e96c410d7195060ea838313937fabf9ee720f9670f512e1f" + } +} diff --git a/tests/golden/WBV2-P10-001/task-context.json b/tests/golden/WBV2-P10-001/task-context.json new file mode 100644 index 000000000..71d4e6be8 --- /dev/null +++ b/tests/golden/WBV2-P10-001/task-context.json @@ -0,0 +1,185 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-001", + "parentTask": "WBV2-P10-000", + "status": "in_progress", + "goal": "Record the already observed mutable plan drift and prove dependency closure stability. The historical P0-002 source hashes remain immutable; a current baseline is an additive P10 artifact.", + "scope": { + "gap": "workflow:reconcile_wbv2_inventory_source_drift", + "ownerFamily": "PARITY", + "implementationClass": "LOCAL_BOUNDED" + }, + "commands": [ + "node tools/web/generate-wbv2-inventory-rebaseline.mjs --write", + "node tools/web/check-wbv2-inventory-rebaseline.mjs", + "node tools/web/check-task-context.mjs --task WBV2-P10-001 --write" + ], + "inputPaths": [ + "tests/golden/WBV2-P0-002/source-hashes.json" + ], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 3381, + "contextRemainingTokens": 844 + }, + "source": { + "bytes": 6523, + "tokens": 1632 + }, + "selected": [ + { + "path": "tests/golden/WBV2-P0-002/source-hashes.json", + "bytes": 782, + "tokens": 196 + } + ], + "excluded": [ + { + "path": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "bytes": 23727, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/M13-05C/dependency-inventory.json", + "bytes": 64565, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/check-wbv2-inventory.mjs", + "bytes": 9778, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tools/web/generate-wbv2-inventory-rebaseline.mjs", + "bytes": 9115, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/WBV2-P10-001/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/WBV2-P10-001.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/WBV2-P10-001/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 1, + "bytes": 782, + "tokens": 196 + } + }, + "exitCriteria": [ + "historical P0 hashes remain unchanged", + "only authorized plan drift is recorded", + "dependency roots/lockfile/closure remain stable", + "inventory checker passes using current baseline" + ], + "nextTask": "WBV2-P10-002", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/WBV2-P10-001.md", + "taskIndex": "tests/golden/WBV2/task-index.json", + "parentManifest": "tests/golden/WBV2-P10-000/manifest.json", + "parentStatus": "docs/status/WBV2-P10-000.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/WBV2-P10-001.md", + "tests/golden/WBV2-P10-000/manifest.json", + "docs/status/WBV2-P10-000.md" + ], + "machineOnly": [ + "tests/golden/WBV2/task-index.json", + "tests/golden/M15-03A/task-catalog.jsonl" + ], + "optionalByNeed": [ + "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "任务卡列出的精确协议/生产路径", + "任务卡明确命名的长期计划小节" + ], + "forbiddenByDefault": [ + "完整 CURRENT_EXECUTION_PLAN.md", + "完整 PROJECT_STATUS_AND_NEXT_WORK.md", + "全部 docs/status/*.md", + "完整 parity/WBS 计划", + "README 历史和 test-results/" + ] + }, + "parent": { + "manifest": { + "schemaVersion": 1, + "task": "WBV2-P10-000", + "parentTask": "WBV2-P9-004", + "status": "done", + "nextTask": "WBV2-P10-001", + "artifactCount": 8 + }, + "statusSummary": [ + "# WBV2-P10-000 status", + "- task: `WBV2-P10-000`; parent: `WBV2-P9-004`; status: `done`", + "- nextTask: `WBV2-P10-001`", + "Native engine parity continuation is authorized after P9 bounded Chromium evidence. P10 first reconciles the known WBV2 inventory drift, then requires receipts from the compiled Blender native binary and web_engine.wasm. Full historical reproduction remains false." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1431, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 36, + "taskTokens": 358 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2803, + "lines": 51, + "tokens": 701 + }, + { + "path": "docs/tasks/WBV2-P10-001.md", + "bytes": 1431, + "lines": 36, + "tokens": 358 + }, + { + "path": "tests/golden/WBV2-P10-000/manifest.json", + "bytes": 1911, + "lines": 57, + "tokens": 478 + }, + { + "path": "docs/status/WBV2-P10-000.md", + "bytes": 378, + "lines": 7, + "tokens": 95 + } + ], + "sourceTokens": 1632, + "evidenceFiles": 1, + "evidenceBytes": 782, + "evidenceTokens": 196, + "totalTokens": 1828, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 2852, + "serializedContextTokens": 724, + "withinBudget": true + } +} diff --git a/tests/golden/WBV2-P10-002/manifest.json b/tests/golden/WBV2-P10-002/manifest.json new file mode 100644 index 000000000..bfe47fb7d --- /dev/null +++ b/tests/golden/WBV2-P10-002/manifest.json @@ -0,0 +1,90 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-002", + "parentTask": "WBV2-P10-001", + "operation": "NATIVE_WASM_ENGINE_PRODUCTION_RECEIPT", + "status": "done", + "enablingTask": false, + "parityStateChange": true, + "runtime": "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", + "artifacts": { + "parentManifest": { + "path": "tests/golden/WBV2-P10-001/manifest.json", + "sha256": "200ad417f44414b25c2b431fd6e7ff2c98c59e23871a7220facd92f295f1cd8d" + }, + "binding": { + "path": "tests/golden/WBV2-P10-002/native-engine-binding-report.json", + "sha256": "a98010ccfdb4a2f145356a35cf3bc7e03a5fcedf0201d38cd3f3a6fecb4c6aae" + }, + "production": { + "path": "tests/golden/WBV2-P10-002/native-engine-production.json", + "sha256": "b3a54efb3624d949c56865ff0fca8e8177ba8fe71d9e923f5003db15973fff59" + }, + "productionSecond": { + "path": "tests/golden/WBV2-P10-002/native-engine-production.second.json", + "sha256": "b3a54efb3624d949c56865ff0fca8e8177ba8fe71d9e923f5003db15973fff59" + }, + "e2e": { + "path": "web/tests/e2e/wbv2-native-engine-production.spec.ts", + "sha256": "53735206840a950d0b0aedf37e1f20fa1811c9d1ccfb7a9f95a88e90559b52e1" + }, + "webEngineClient": { + "path": "web/app/src/engine-client/WebEngineClient.ts", + "sha256": "f6d9a8e0a16403bc6fb765195b8f1a619a28de7a75c59a412f1654d46e8ebc0b" + }, + "webEngineWorker": { + "path": "web/app/src/workers/web-engine.worker.ts", + "sha256": "e3bb430e401144bf17cdcbd0de13cde0a4f904f1f9ff9d5b10a73d90f0d4c648" + }, + "nativeApi": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "sha256": "8fa70dc7605e66393482e661e5987a8443dded56ab0092aeb977b40ae49888f8" + }, + "mainState": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "sha256": "3c31a049714860cc89c5b28ebad887a1978df11f8c528c3dfd7836635ed62fb3" + }, + "nativeBinary": { + "path": "build_blender_native/bin/blender", + "sha256": "97d025812d51642e6c118a7a6228b0481e5ff95e4acb7742f62875f9f27f924b" + }, + "wasmBinary": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "25bc1e286fd3b72c2c7c082b85a29b2d0bb109588a6dc0de5be94fcdc37cc88c" + }, + "wasmJavaScript": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "e2b21fcc3c9d098cfb343fc682776c2ed95678064e95eabd71409a8b3284cce0" + }, + "generator": { + "path": "tools/web/generate-wbv2-native-engine-receipt.mjs", + "sha256": "73ae2edf00dabadbe10abfdeb2f51bbaab495520fbcdfa168795351e8523eba5" + }, + "report": { + "path": "tests/golden/WBV2-P10-002/native-engine-receipt-report.json", + "sha256": "09c13b1814d61a6132ae1168d999e09b768915fe7fec652b6b965f9a6d3796f9" + }, + "status": { + "path": "docs/status/WBV2-P10-002.md", + "sha256": "74b52f1a9a5969545db5d9659404d5f25adeb9c4ec581d18242455883dabfa0c" + }, + "parityPlan": { + "path": "tests/golden/WBV2-P10-002/native-parity-task-plan.json", + "sha256": "a6e205dec083f76ec08eef07f0085b8be228b2a7d28a16618ec3625d3e2fd19b" + }, + "taskContext": { + "path": "tests/golden/WBV2-P10-002/task-context.json", + "sha256": "fd7c2fcd7e43a44b5a666d4bc3ad5a817f698ef6c2db2150975eb04d80a3b402" + } + }, + "assertions": { + "compiledNativeBound": true, + "compiledWasmBound": true, + "realEngineMainMutation": true, + "deterministic": true, + "saveReopen": "EXACT", + "surfaces": 3, + "historicalReproduction": false + }, + "nextTask": "WBV2-P10-003" +} diff --git a/tests/golden/WBV2-P10-002/native-engine-binding-report.json b/tests/golden/WBV2-P10-002/native-engine-binding-report.json new file mode 100644 index 000000000..f554fd33a --- /dev/null +++ b/tests/golden/WBV2-P10-002/native-engine-binding-report.json @@ -0,0 +1,61 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-002", + "operation": "NATIVE_WASM_ENGINE_BINDING", + "status": "PASS", + "runtime": { + "native": { + "path": "build_blender_native/bin/blender", + "sha256": "97d025812d51642e6c118a7a6228b0481e5ff95e4acb7742f62875f9f27f924b", + "version": "Blender 5.2.0 LTS" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "25bc1e286fd3b72c2c7c082b85a29b2d0bb109588a6dc0de5be94fcdc37cc88c", + "bytes": 15643984 + }, + "javascript": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "e2b21fcc3c9d098cfb343fc682776c2ed95678064e95eabd71409a8b3284cce0", + "bytes": 132196 + }, + "browser": "chromium" + }, + "abi": { + "exports": [ + "web_engine_create", + "web_engine_open_blend", + "web_engine_apply_command", + "web_engine_save_blend", + "web_engine_destroy" + ], + "nativeApi": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "mainState": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "worker": "web/app/src/workers/web-engine.worker.ts" + }, + "sourceBindings": [ + { + "task": "WBV2-P2-003", + "manifest": "tests/golden/WBV2-P2-003/manifest.json", + "report": "tests/golden/WBV2-P2-003/mesh-edit-report.json" + }, + { + "task": "WBV2-P4-001", + "manifest": "tests/golden/WBV2-P4-001/manifest.json", + "report": "tests/golden/WBV2-P4-001/modifier-report.json" + }, + { + "task": "WBV2-P3-005", + "manifest": "tests/golden/WBV2-P3-005/manifest.json", + "report": "tests/golden/WBV2-P3-005/library-report.json" + } + ], + "requirements": { + "compiledNativePresent": true, + "wasmBinaryPresent": true, + "wasmLoaderPresent": true, + "sourceBound": true, + "fakeBridgeOnly": false + }, + "nextTask": "WBV2-P10-002" +} diff --git a/tests/golden/WBV2-P10-002/native-engine-production.json b/tests/golden/WBV2-P10-002/native-engine-production.json new file mode 100644 index 000000000..12ade903a --- /dev/null +++ b/tests/golden/WBV2-P10-002/native-engine-production.json @@ -0,0 +1,478 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-002", + "operation": "NATIVE_WASM_ENGINE_PRODUCTION_CHROMIUM", + "browser": "chromium", + "queueMutation": false, + "mesh": { + "baseRevision": 1, + "editedRevision": 2, + "meshId": "mesh:WBV2P2003TranslateMesh", + "beforePosition": [ + -1, + -1, + 0 + ], + "afterPosition": [ + -0.75, + -1.5, + 1 + ], + "savedSha256": "7bdab0364865c2435d62b004e9c952c05c7110453be02b22836c62e36f354ec2", + "sourceSha256": "1a9a894c4106d73a4533485d9fdddfe2883f75e4692b8e53dc174308e12fe60b", + "reopenedRevision": 1, + "reopenedPosition": [ + -0.75, + -1.5, + 1 + ], + "stale": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + }, + "malformed": { + "code": "INVALID_ARGUMENT", + "message": "translateMeshVertices contains an out-of-range vertex index" + } + }, + "modifier": { + "baseRevision": 1, + "editedRevision": 2, + "meshId": "mesh:WBV2P4001ModifierMesh", + "modifierUuid": "modifier:object:WBV2P4001ModifierObject:1277244409", + "beforeEnabled": true, + "afterEnabled": false, + "savedSha256": "37c8203ea1172fab3cf6bab421682fe56d45a2372750d50bc0eed53f19071e93", + "sourceSha256": "02e56fd6745d983ee9f5ee3f48e581f116f0c41c2d2e7dec062517b4af86718f", + "reopenedRevision": 1, + "reopenedEnabled": false, + "stale": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + }, + "malformed": { + "code": "INVALID_ARGUMENT", + "message": "modifier UUID was not found in mesh stack" + } + }, + "asset": { + "baseRevision": 1, + "appendedRevision": 2, + "sourceSha256": "dcda742db77c6af5e05b79e006a0bd89cf1e8ea8d438592cd1ed2e981c7aca76", + "targetSha256": "86af081b949ac96d6431303464852b4e983cf8c3d05671cacb36e1de4267a425", + "receipt": { + "schemaVersion": 1, + "operation": "APPEND", + "sourceLibraryId": "library:2e0d46a97a5c7e34b76ba16a594ce76a12553ddd795992c3f48d6c1d32826153", + "sourceDataBlockId": "Object/WBV2P3005AppendObject", + "dependencyClosureSha256": "f065b78b4bb80189c2258f78725c3254d6853ecf7f4a34d4b91c62ec28a6670d", + "baseRevision": 1, + "nextRevision": 2, + "transactionCount": 1, + "mapping": [ + { + "source": "Object/WBV2P3005AppendObject", + "local": "Object/WBV2P3005AppendObject", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Mesh/WBV2P3005AppendMesh", + "local": "Mesh/WBV2P3005AppendMesh", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Material/WBV2P3005AppendMaterial", + "local": "Material/WBV2P3005AppendMaterial", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Image/WBV2P3005AppendImage", + "local": "Image/WBV2P3005AppendImage", + "owner": "LOCAL_MAIN", + "readOnly": false + } + ] + }, + "delta": { + "activeObjectId": "object:WBV2P3005AppendObject", + "baseRevision": 1, + "materials": { + "added": [ + { + "alpha": 1, + "baseColor": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1 + ], + "coatRoughness": 0.029999999329447746, + "coatWeight": 0, + "emissionColor": [ + 0, + 0, + 0, + 1 + ], + "emissionStrength": 1, + "id": "material:WBV2P3005AppendMaterial", + "ior": 1.4500000476837158, + "links": [ + { + "fromNodeId": "node:1441037842:Principled BSDF", + "fromSocket": "BSDF", + "toNodeId": "node:1526166084:Material Output", + "toSocket": "Surface" + }, + { + "fromNodeId": "node:1788630761:WBV2P3005AppendImageNode", + "fromSocket": "Color", + "toNodeId": "node:1441037842:Principled BSDF", + "toSocket": "Base Color" + } + ], + "metallic": 0, + "name": "WBV2P3005AppendMaterial", + "nodes": [ + { + "id": "node:1441037842:Principled BSDF", + "name": "Principled BSDF", + "type": "UNSUPPORTED" + }, + { + "id": "node:1526166084:Material Output", + "name": "Material Output", + "type": "UNSUPPORTED" + }, + { + "id": "node:1788630761:WBV2P3005AppendImageNode", + "imageId": "image:WBV2P3005AppendImage", + "name": "WBV2P3005AppendImageNode", + "type": "UNSUPPORTED" + } + ], + "roughness": 0.4000000059604645, + "shaderGraphHash": "b618c541fdc15a1a86d4a3dc6e75690affdc9a0aefb81583d27737a0985a0765", + "specularIORLevel": 0.5, + "transmissionWeight": 0, + "warnings": [ + "unsupported_node:Undefined[ShaderNodeBsdfPrincipled]", + "unsupported_node:Undefined[ShaderNodeOutputMaterial]", + "unsupported_node:Undefined[ShaderNodeTexImage]", + "principled_node_not_found" + ] + } + ], + "removed": [], + "updated": [] + }, + "meshes": { + "added": [ + { + "activeUVMap": null, + "attributes": [ + { + "dataType": "FLOAT3", + "domain": "POINT", + "name": "position" + }, + { + "dataType": "BOOL", + "domain": "FACE", + "name": "sharp_face" + } + ], + "bounds": { + "max": [ + 0.75, + 0.75, + 0 + ], + "min": [ + -0.75, + -0.75, + 0 + ] + }, + "cornerCount": 6, + "edgeCount": 5, + "edgeVertexIndices": [ + 0, + 2, + 0, + 1, + 1, + 2, + 0, + 3, + 2, + 3 + ], + "faceCount": 2, + "geometryStatus": "available", + "id": "mesh:WBV2P3005AppendMesh", + "indices": [ + 0, + 1, + 2, + 0, + 2, + 3 + ], + "materialSlotIds": [ + "material:WBV2P3005AppendMaterial" + ], + "name": "WBV2P3005AppendMesh", + "normals": [ + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1 + ], + "positions": [ + -0.75, + -0.75, + 0, + 0.75, + -0.75, + 0, + 0.75, + 0.75, + 0, + -0.75, + 0.75, + 0 + ], + "topology": "triangles", + "triangleCornerIndices": [ + 0, + 1, + 2, + 3, + 4, + 5 + ], + "triangleCount": 2, + "triangleFaceIndices": [ + 0, + 1 + ], + "triangleMaterialIndices": [ + 0, + 0 + ], + "vertexCount": 4 + } + ], + "removed": [], + "updated": [] + }, + "nextRevision": 2, + "nodes": { + "added": [ + { + "dataId": "mesh:WBV2P3005AppendMesh", + "id": "object:WBV2P3005AppendObject", + "localMatrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1.5, + 0, + 0, + 1 + ], + "name": "WBV2P3005AppendObject", + "parentId": null, + "selectable": true, + "transform": { + "rotationEuler": [ + 0, + 0, + 0 + ], + "rotationMode": 1, + "scale": [ + 1, + 1, + 1 + ], + "translation": [ + 1.5, + 0, + 0 + ] + }, + "type": "MESH", + "visible": true, + "worldMatrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1.5, + 0, + 0, + 1 + ] + } + ], + "removed": [], + "updated": [] + }, + "scenes": { + "added": [], + "removed": [], + "updated": [ + { + "cameraObjectId": null, + "colorManagement": { + "displayDevice": "sRGB", + "exposure": 0, + "gamma": 1, + "look": "None", + "viewTransform": "AgX", + "whiteBalanceStatus": "BLOCKED" + }, + "id": "scene:Scene", + "name": "Scene", + "renderEngine": "BLENDER_EEVEE", + "rootCollectionId": "collection:Scene Collection", + "sequencerStatus": "AVAILABLE", + "sequencerTimeline": { + "fpsDenominator": 1000, + "fpsNumerator": 24000, + "frameEnd": 250, + "frameStart": 1, + "id": "sequencer:scene:Scene", + "revision": 2, + "schemaVersion": 1, + "strips": [] + }, + "worldId": null + } + ] + }, + "schemaVersion": 1 + }, + "appendedClosure": { + "object": true, + "mesh": true, + "material": true, + "image": { + "assetId": "image:WBV2P3005AppendImage", + "assetStatus": "PACKED", + "height": 1024, + "id": "image:WBV2P3005AppendImage", + "libraryLinked": false, + "mimeType": "image/png", + "name": "WBV2P3005AppendImage", + "packed": true, + "packedByteLength": 261, + "sourceKind": "FILE", + "sourcePath": "project-assets/resources/udim_1001.png", + "tiles": [ + { + "assetId": "image:WBV2P3005AppendImage", + "generatedColor": [ + 0, + 0, + 0, + 0 + ], + "generatedType": 1, + "height": 1024, + "label": "", + "mimeType": "image/png", + "number": 1001, + "packed": true, + "packedByteLength": 261, + "sourcePath": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/resources/udim_1001.png", + "validSignature": true, + "width": 1024 + } + ], + "width": 1024 + } + }, + "stale": { + "code": "REVISION_CONFLICT", + "message": "REVISION_CONFLICT: library append base revision is stale" + }, + "collision": { + "code": "ASSET_MANIFEST_INVALID", + "message": "ASSET_MANIFEST_INVALID: append closure collides with an existing local ID" + }, + "collisionRevision": 2, + "savedSha256": "5186c694f5b0f2b1182e4790e99d6667ef067d1b95d2e6a2d0381ad29eeba326", + "reopenedRevision": 1, + "reopenedClosure": { + "object": true, + "mesh": true, + "material": true, + "image": { + "assetId": "image:WBV2P3005AppendImage", + "assetStatus": "PACKED", + "height": 1024, + "id": "image:WBV2P3005AppendImage", + "libraryLinked": false, + "mimeType": "image/png", + "name": "WBV2P3005AppendImage", + "packed": true, + "packedByteLength": 261, + "sourceKind": "FILE", + "sourcePath": "project-assets/resources/udim_1001.png", + "tiles": [ + { + "assetId": "image:WBV2P3005AppendImage", + "generatedColor": [ + 0, + 0, + 0, + 0 + ], + "generatedType": 1, + "height": 1024, + "label": "", + "mimeType": "image/png", + "number": 1001, + "packed": true, + "packedByteLength": 261, + "sourcePath": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/resources/udim_1001.png", + "validSignature": true, + "width": 1024 + } + ], + "width": 1024 + } + } + } +} diff --git a/tests/golden/WBV2-P10-002/native-engine-production.second.json b/tests/golden/WBV2-P10-002/native-engine-production.second.json new file mode 100644 index 000000000..12ade903a --- /dev/null +++ b/tests/golden/WBV2-P10-002/native-engine-production.second.json @@ -0,0 +1,478 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-002", + "operation": "NATIVE_WASM_ENGINE_PRODUCTION_CHROMIUM", + "browser": "chromium", + "queueMutation": false, + "mesh": { + "baseRevision": 1, + "editedRevision": 2, + "meshId": "mesh:WBV2P2003TranslateMesh", + "beforePosition": [ + -1, + -1, + 0 + ], + "afterPosition": [ + -0.75, + -1.5, + 1 + ], + "savedSha256": "7bdab0364865c2435d62b004e9c952c05c7110453be02b22836c62e36f354ec2", + "sourceSha256": "1a9a894c4106d73a4533485d9fdddfe2883f75e4692b8e53dc174308e12fe60b", + "reopenedRevision": 1, + "reopenedPosition": [ + -0.75, + -1.5, + 1 + ], + "stale": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + }, + "malformed": { + "code": "INVALID_ARGUMENT", + "message": "translateMeshVertices contains an out-of-range vertex index" + } + }, + "modifier": { + "baseRevision": 1, + "editedRevision": 2, + "meshId": "mesh:WBV2P4001ModifierMesh", + "modifierUuid": "modifier:object:WBV2P4001ModifierObject:1277244409", + "beforeEnabled": true, + "afterEnabled": false, + "savedSha256": "37c8203ea1172fab3cf6bab421682fe56d45a2372750d50bc0eed53f19071e93", + "sourceSha256": "02e56fd6745d983ee9f5ee3f48e581f116f0c41c2d2e7dec062517b4af86718f", + "reopenedRevision": 1, + "reopenedEnabled": false, + "stale": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + }, + "malformed": { + "code": "INVALID_ARGUMENT", + "message": "modifier UUID was not found in mesh stack" + } + }, + "asset": { + "baseRevision": 1, + "appendedRevision": 2, + "sourceSha256": "dcda742db77c6af5e05b79e006a0bd89cf1e8ea8d438592cd1ed2e981c7aca76", + "targetSha256": "86af081b949ac96d6431303464852b4e983cf8c3d05671cacb36e1de4267a425", + "receipt": { + "schemaVersion": 1, + "operation": "APPEND", + "sourceLibraryId": "library:2e0d46a97a5c7e34b76ba16a594ce76a12553ddd795992c3f48d6c1d32826153", + "sourceDataBlockId": "Object/WBV2P3005AppendObject", + "dependencyClosureSha256": "f065b78b4bb80189c2258f78725c3254d6853ecf7f4a34d4b91c62ec28a6670d", + "baseRevision": 1, + "nextRevision": 2, + "transactionCount": 1, + "mapping": [ + { + "source": "Object/WBV2P3005AppendObject", + "local": "Object/WBV2P3005AppendObject", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Mesh/WBV2P3005AppendMesh", + "local": "Mesh/WBV2P3005AppendMesh", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Material/WBV2P3005AppendMaterial", + "local": "Material/WBV2P3005AppendMaterial", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Image/WBV2P3005AppendImage", + "local": "Image/WBV2P3005AppendImage", + "owner": "LOCAL_MAIN", + "readOnly": false + } + ] + }, + "delta": { + "activeObjectId": "object:WBV2P3005AppendObject", + "baseRevision": 1, + "materials": { + "added": [ + { + "alpha": 1, + "baseColor": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1 + ], + "coatRoughness": 0.029999999329447746, + "coatWeight": 0, + "emissionColor": [ + 0, + 0, + 0, + 1 + ], + "emissionStrength": 1, + "id": "material:WBV2P3005AppendMaterial", + "ior": 1.4500000476837158, + "links": [ + { + "fromNodeId": "node:1441037842:Principled BSDF", + "fromSocket": "BSDF", + "toNodeId": "node:1526166084:Material Output", + "toSocket": "Surface" + }, + { + "fromNodeId": "node:1788630761:WBV2P3005AppendImageNode", + "fromSocket": "Color", + "toNodeId": "node:1441037842:Principled BSDF", + "toSocket": "Base Color" + } + ], + "metallic": 0, + "name": "WBV2P3005AppendMaterial", + "nodes": [ + { + "id": "node:1441037842:Principled BSDF", + "name": "Principled BSDF", + "type": "UNSUPPORTED" + }, + { + "id": "node:1526166084:Material Output", + "name": "Material Output", + "type": "UNSUPPORTED" + }, + { + "id": "node:1788630761:WBV2P3005AppendImageNode", + "imageId": "image:WBV2P3005AppendImage", + "name": "WBV2P3005AppendImageNode", + "type": "UNSUPPORTED" + } + ], + "roughness": 0.4000000059604645, + "shaderGraphHash": "b618c541fdc15a1a86d4a3dc6e75690affdc9a0aefb81583d27737a0985a0765", + "specularIORLevel": 0.5, + "transmissionWeight": 0, + "warnings": [ + "unsupported_node:Undefined[ShaderNodeBsdfPrincipled]", + "unsupported_node:Undefined[ShaderNodeOutputMaterial]", + "unsupported_node:Undefined[ShaderNodeTexImage]", + "principled_node_not_found" + ] + } + ], + "removed": [], + "updated": [] + }, + "meshes": { + "added": [ + { + "activeUVMap": null, + "attributes": [ + { + "dataType": "FLOAT3", + "domain": "POINT", + "name": "position" + }, + { + "dataType": "BOOL", + "domain": "FACE", + "name": "sharp_face" + } + ], + "bounds": { + "max": [ + 0.75, + 0.75, + 0 + ], + "min": [ + -0.75, + -0.75, + 0 + ] + }, + "cornerCount": 6, + "edgeCount": 5, + "edgeVertexIndices": [ + 0, + 2, + 0, + 1, + 1, + 2, + 0, + 3, + 2, + 3 + ], + "faceCount": 2, + "geometryStatus": "available", + "id": "mesh:WBV2P3005AppendMesh", + "indices": [ + 0, + 1, + 2, + 0, + 2, + 3 + ], + "materialSlotIds": [ + "material:WBV2P3005AppendMaterial" + ], + "name": "WBV2P3005AppendMesh", + "normals": [ + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1 + ], + "positions": [ + -0.75, + -0.75, + 0, + 0.75, + -0.75, + 0, + 0.75, + 0.75, + 0, + -0.75, + 0.75, + 0 + ], + "topology": "triangles", + "triangleCornerIndices": [ + 0, + 1, + 2, + 3, + 4, + 5 + ], + "triangleCount": 2, + "triangleFaceIndices": [ + 0, + 1 + ], + "triangleMaterialIndices": [ + 0, + 0 + ], + "vertexCount": 4 + } + ], + "removed": [], + "updated": [] + }, + "nextRevision": 2, + "nodes": { + "added": [ + { + "dataId": "mesh:WBV2P3005AppendMesh", + "id": "object:WBV2P3005AppendObject", + "localMatrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1.5, + 0, + 0, + 1 + ], + "name": "WBV2P3005AppendObject", + "parentId": null, + "selectable": true, + "transform": { + "rotationEuler": [ + 0, + 0, + 0 + ], + "rotationMode": 1, + "scale": [ + 1, + 1, + 1 + ], + "translation": [ + 1.5, + 0, + 0 + ] + }, + "type": "MESH", + "visible": true, + "worldMatrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1.5, + 0, + 0, + 1 + ] + } + ], + "removed": [], + "updated": [] + }, + "scenes": { + "added": [], + "removed": [], + "updated": [ + { + "cameraObjectId": null, + "colorManagement": { + "displayDevice": "sRGB", + "exposure": 0, + "gamma": 1, + "look": "None", + "viewTransform": "AgX", + "whiteBalanceStatus": "BLOCKED" + }, + "id": "scene:Scene", + "name": "Scene", + "renderEngine": "BLENDER_EEVEE", + "rootCollectionId": "collection:Scene Collection", + "sequencerStatus": "AVAILABLE", + "sequencerTimeline": { + "fpsDenominator": 1000, + "fpsNumerator": 24000, + "frameEnd": 250, + "frameStart": 1, + "id": "sequencer:scene:Scene", + "revision": 2, + "schemaVersion": 1, + "strips": [] + }, + "worldId": null + } + ] + }, + "schemaVersion": 1 + }, + "appendedClosure": { + "object": true, + "mesh": true, + "material": true, + "image": { + "assetId": "image:WBV2P3005AppendImage", + "assetStatus": "PACKED", + "height": 1024, + "id": "image:WBV2P3005AppendImage", + "libraryLinked": false, + "mimeType": "image/png", + "name": "WBV2P3005AppendImage", + "packed": true, + "packedByteLength": 261, + "sourceKind": "FILE", + "sourcePath": "project-assets/resources/udim_1001.png", + "tiles": [ + { + "assetId": "image:WBV2P3005AppendImage", + "generatedColor": [ + 0, + 0, + 0, + 0 + ], + "generatedType": 1, + "height": 1024, + "label": "", + "mimeType": "image/png", + "number": 1001, + "packed": true, + "packedByteLength": 261, + "sourcePath": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/resources/udim_1001.png", + "validSignature": true, + "width": 1024 + } + ], + "width": 1024 + } + }, + "stale": { + "code": "REVISION_CONFLICT", + "message": "REVISION_CONFLICT: library append base revision is stale" + }, + "collision": { + "code": "ASSET_MANIFEST_INVALID", + "message": "ASSET_MANIFEST_INVALID: append closure collides with an existing local ID" + }, + "collisionRevision": 2, + "savedSha256": "5186c694f5b0f2b1182e4790e99d6667ef067d1b95d2e6a2d0381ad29eeba326", + "reopenedRevision": 1, + "reopenedClosure": { + "object": true, + "mesh": true, + "material": true, + "image": { + "assetId": "image:WBV2P3005AppendImage", + "assetStatus": "PACKED", + "height": 1024, + "id": "image:WBV2P3005AppendImage", + "libraryLinked": false, + "mimeType": "image/png", + "name": "WBV2P3005AppendImage", + "packed": true, + "packedByteLength": 261, + "sourceKind": "FILE", + "sourcePath": "project-assets/resources/udim_1001.png", + "tiles": [ + { + "assetId": "image:WBV2P3005AppendImage", + "generatedColor": [ + 0, + 0, + 0, + 0 + ], + "generatedType": 1, + "height": 1024, + "label": "", + "mimeType": "image/png", + "number": 1001, + "packed": true, + "packedByteLength": 261, + "sourcePath": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/resources/udim_1001.png", + "validSignature": true, + "width": 1024 + } + ], + "width": 1024 + } + } + } +} diff --git a/tests/golden/WBV2-P10-002/native-engine-receipt-report.json b/tests/golden/WBV2-P10-002/native-engine-receipt-report.json new file mode 100644 index 000000000..972db6136 --- /dev/null +++ b/tests/golden/WBV2-P10-002/native-engine-receipt-report.json @@ -0,0 +1,102 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-002", + "operation": "NATIVE_WASM_ENGINE_PRODUCTION_RECEIPT", + "status": "PASS", + "browser": "chromium", + "queueMutation": false, + "runtime": { + "binding": "tests/golden/WBV2-P10-002/native-engine-binding-report.json", + "bindingSha256": "a98010ccfdb4a2f145356a35cf3bc7e03a5fcedf0201d38cd3f3a6fecb4c6aae", + "native": { + "path": "build_blender_native/bin/blender", + "sha256": "97d025812d51642e6c118a7a6228b0481e5ff95e4acb7742f62875f9f27f924b", + "version": "Blender 5.2.0 LTS" + }, + "wasm": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "25bc1e286fd3b72c2c7c082b85a29b2d0bb109588a6dc0de5be94fcdc37cc88c", + "bytes": 15643984 + }, + "javascript": { + "path": "web/app/src/vendor/blender/web_engine.js", + "sha256": "e2b21fcc3c9d098cfb343fc682776c2ed95678064e95eabd71409a8b3284cce0", + "bytes": 132196 + }, + "abi": { + "exports": [ + "web_engine_create", + "web_engine_open_blend", + "web_engine_apply_command", + "web_engine_save_blend", + "web_engine_destroy" + ], + "nativeApi": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "mainState": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "worker": "web/app/src/workers/web-engine.worker.ts" + } + }, + "sourceBindings": [ + { + "task": "WBV2-P2-003", + "manifest": "tests/golden/WBV2-P2-003/manifest.json", + "manifestSha256": "79ebc20719fef2b60a3457bca25dac98e755a2f2c1bd3c35361527509a91a987", + "report": "tests/golden/WBV2-P2-003/mesh-edit-report.json", + "reportSha256": "f8bd2ced2e1345248d4b536ef045bb9446a55ca5ae87d834f38904b86521b11d" + }, + { + "task": "WBV2-P4-001", + "manifest": "tests/golden/WBV2-P4-001/manifest.json", + "manifestSha256": "6f1bee73c987f5e66733feb03d1d708e0f2dbd0776ac6634dbf694cde385143c", + "report": "tests/golden/WBV2-P4-001/modifier-report.json", + "reportSha256": "65d2cf962511ae181e53cda1cc01f8db46819ee450a470384abbe829d549adf8" + }, + { + "task": "WBV2-P3-005", + "manifest": "tests/golden/WBV2-P3-005/manifest.json", + "manifestSha256": "42dc02d198630c2735c5a0a1beab37f2a98ff0233927215099f67606d248c39e", + "report": "tests/golden/WBV2-P3-005/library-report.json", + "reportSha256": "0b572a5b480dd9b123cbb9c55c842fb002b1a8a6c96afd196af90bee1ebd9940" + } + ], + "production": { + "report": "tests/golden/WBV2-P10-002/native-engine-production.json", + "reportSha256": "b3a54efb3624d949c56865ff0fca8e8177ba8fe71d9e923f5003db15973fff59", + "secondReport": "tests/golden/WBV2-P10-002/native-engine-production.second.json", + "secondReportSha256": "b3a54efb3624d949c56865ff0fca8e8177ba8fe71d9e923f5003db15973fff59", + "deterministic": true, + "mesh": { + "mutation": "translateMeshVertices", + "revisionDelta": 1, + "saveReopen": "EXACT", + "stale": "REVISION_CONFLICT", + "malformed": "REJECTED" + }, + "modifier": { + "mutation": "setModifierEnabled", + "revisionDelta": 1, + "saveReopen": "EXACT", + "stale": "REVISION_CONFLICT", + "malformed": "REJECTED" + }, + "asset": { + "mutation": "appendLibraryObject", + "revisionDelta": 1, + "resourceClosure": "LOCAL_MAIN", + "saveReopen": "EXACT", + "stale": "REVISION_CONFLICT", + "collision": "REJECTED" + } + }, + "assertions": { + "compiledNativeBound": true, + "compiledWasmBound": true, + "realEngineMainMutation": true, + "saveReopenExact": 3, + "deterministicRuns": 2, + "failureMatrixClosed": true, + "fakeBridgeOnly": false, + "historicalReproduction": false + }, + "nextTask": "WBV2-P10-003" +} diff --git a/tests/golden/WBV2-P10-002/native-parity-task-plan.json b/tests/golden/WBV2-P10-002/native-parity-task-plan.json new file mode 100644 index 000000000..9f7050447 --- /dev/null +++ b/tests/golden/WBV2-P10-002/native-parity-task-plan.json @@ -0,0 +1,1567 @@ +{ + "schemaVersion": 1, + "planId": "BLENDER_WEB_PARITY_V2_NATIVE_ENGINE_EPOCH_1", + "status": "ACTIVE_NATIVE_ENGINE_QUEUE", + "authority": "queue_reactivated_after_p9_bounded_parity", + "productContract": "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "sourcePlan": "docs/BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md", + "executionPointer": "docs/EXECUTION_QUEUE.md", + "correctiveCheckpoint": { + "task": "C6-003", + "handoff": "tests/golden/corrective/C6-003/handoff.json", + "status": "active", + "blocker": null, + "queueMutation": true, + "legacyTask": "M16-GAP-00277", + "legacyParentNextTask": "M16-GAP-00277" + }, + "runtimePolicy": { + "blenderSource": "blender-5.2.0", + "browserEvidence": [ + "chromium" + ], + "forbiddenBrowsers": [ + "firefox", + "webkit" + ], + "mainAuthority": "blender_main", + "storage": [ + "opfs", + "indexeddb" + ], + "queueMutation": "enabled_after_owner_review_and_g5" + }, + "completionClasses": [ + "LOCAL_EXACT", + "LOCAL_BOUNDED", + "SERVER_EXACT", + "EXCLUDED" + ], + "gates": [ + { + "id": "G0", + "name": "scope_and_inventory", + "requires": [ + "contract", + "inventory", + "capability_matrix" + ] + }, + { + "id": "G1", + "name": "runtime_foundation", + "requires": [ + "sceneir", + "main_transaction", + "worker_lifecycle", + "storage_journal" + ] + }, + { + "id": "G2", + "name": "feature_parity", + "requires": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence" + ] + }, + { + "id": "G3", + "name": "recovery_and_security", + "requires": [ + "cancel", + "restart", + "oom_quota", + "malformed", + "dispose" + ] + }, + { + "id": "G4", + "name": "release_candidate", + "requires": [ + "offline", + "ci", + "sbom", + "rollback", + "hashes" + ] + }, + { + "id": "G5", + "name": "queue_mutation", + "requires": [ + "owner_review", + "protected_hashes", + "handoff", + "single_ready_task" + ] + } + ], + "waves": [ + { + "id": "P0", + "name": "facts_and_contracts", + "gate": "G0", + "tasks": [ + "WBV2-P0-001", + "WBV2-P0-002", + "WBV2-P0-003" + ] + }, + { + "id": "P1", + "name": "runtime_foundation", + "gate": "G1", + "tasks": [ + "WBV2-P1-001", + "WBV2-P1-002", + "WBV2-P1-003", + "WBV2-P1-004", + "WBV2-P1-005" + ] + }, + { + "id": "P2", + "name": "core_modeler_loop", + "gate": "G2", + "tasks": [ + "WBV2-P2-001", + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P2-005" + ] + }, + { + "id": "P3", + "name": "authoring_and_io", + "gate": "G2", + "tasks": [ + "WBV2-P3-001", + "WBV2-P3-002", + "WBV2-P3-003", + "WBV2-P3-004", + "WBV2-P3-005" + ] + }, + { + "id": "P4", + "name": "advanced_local_slices", + "gate": "G2", + "tasks": [ + "WBV2-P4-001", + "WBV2-P4-002", + "WBV2-P4-003", + "WBV2-P4-004" + ] + }, + { + "id": "P5", + "name": "render_and_server", + "gate": "G3", + "tasks": [ + "WBV2-P5-001", + "WBV2-P5-002", + "WBV2-P5-003" + ] + }, + { + "id": "P6", + "name": "security_performance_release", + "gate": "G4", + "tasks": [ + "WBV2-P6-001", + "WBV2-P6-002", + "WBV2-P6-003" + ] + }, + { + "id": "P7", + "name": "full_parity_gap_program", + "gate": "G5", + "tasks": [ + "WBV2-P7-001", + "WBV2-P7-002", + "WBV2-P7-003" + ] + } + ], + "taskContract": { + "onePrimaryBehavior": true, + "requiredEvidence": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence", + "manifest", + "status" + ], + "requiredCommands": [ + "focused", + "determinism", + "hash", + "governance" + ], + "failureState": "in_progress_or_blocked", + "successorRule": "only_from_parent_manifest_nextTask" + }, + "tasks": [ + { + "id": "WBV2-P0-001", + "phase": "P0", + "title": "reconcile_scope_and_checkpoints", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-governance", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-001.md", + "behavior": "Freeze V1/full-parity boundary and reconcile legacy/corrective pointers without queue mutation.", + "outputs": [ + "scope decision", + "checkpoint report", + "protected hash set" + ], + "acceptance": [ + "corrective owner-review status is explicit", + "legacy parent pointer is unchanged", + "plan has one activation gate" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-002", + "phase": "P0", + "title": "generate_blender52_inventory_and_parity_map", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-inventory", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-002.md", + "behavior": "Generate stable Blender 5.2 data-block/operator/editor/node/format inventory and map every entry to a completion class.", + "outputs": [ + "inventory", + "parity map", + "source hash" + ], + "acceptance": [ + "unknown entries are classified", + "inventory is deterministic", + "no entry claims feature parity without evidence" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-003", + "phase": "P0", + "title": "freeze_capability_error_budget_contract", + "kind": "enabling", + "owner": "PROTOCOL", + "dependsOn": [ + "WBV2-P0-001", + "WBV2-P0-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-contract", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-003.md", + "behavior": "Freeze capability levels, stable error codes, revision, budget, cancellation and loss-report schemas.", + "outputs": [ + "versioned protocol", + "capability matrix", + "negative matrix" + ], + "acceptance": [ + "unsupported input fails closed", + "schema hashes are stable", + "migration policy preserves unknown data" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-001", + "phase": "P1", + "title": "stabilize_runtime_variants_and_source_receipts", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P0-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-runtime", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-001.md", + "behavior": "Bind single-thread/pthread WebEngine variants to pinned Blender source/build/runtime receipts.", + "outputs": [ + "runtime manifest", + "variant selector", + "fallback report" + ], + "acceptance": [ + "variant fallback is deterministic", + "source/build hash is verified", + "one engine session has one generation" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-002", + "phase": "P1", + "title": "unify_sceneir_stable_ids_and_binary_deltas", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-001" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-sceneir", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-002.md", + "behavior": "Make SceneIR/WBG1 stable IDs, topology/attribute domains and binary/range deltas canonical across desktop and WASM.", + "outputs": [ + "SceneIR schema", + "binary fixture", + "delta comparator" + ], + "acceptance": [ + "IDs survive save/reopen", + "malformed chunk is rejected", + "desktop and WASM canonical hashes match" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-003", + "phase": "P1", + "title": "unify_main_transaction_history_and_save", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-002" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-history", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-003.md", + "behavior": "Use one Main transaction/revision/history contract for commit, undo/redo, atomic save and reopen.", + "outputs": [ + "transaction contract", + "history receipt", + "save/reopen runner" + ], + "acceptance": [ + "failed/no-op commands add no history", + "stale revision cannot commit", + "reopen state is byte/hash stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-004", + "phase": "P1", + "title": "harden_worker_cancel_restart_and_dispose", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P1-001", + "WBV2-P1-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-lifecycle", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-004.md", + "behavior": "Make cancellation, late-result rejection, Worker restart and resource disposal common to all domains.", + "outputs": [ + "lifecycle runner", + "fault report", + "dispose counters" + ], + "acceptance": [ + "cancel never publishes result", + "generation mismatch is rejected", + "CPU/WASM/GPU owners return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-005", + "phase": "P1", + "title": "harden_opfs_indexeddb_journal_recovery", + "kind": "enabling", + "owner": "STORAGE", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P1-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-storage", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-005.md", + "behavior": "Unify OPFS staging/content addressing and IndexedDB metadata/journal recovery.", + "outputs": [ + "storage schema", + "crash fixtures", + "recovery checker" + ], + "acceptance": [ + "interrupted commit leaves old project usable", + "hash mismatch quarantines payload", + "small project recovers after restart" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-001", + "phase": "P2", + "title": "open_blend_scene_context_and_outliner", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P1-005" + ], + "parityId": "EDITOR.OPEN_SCENE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-editor", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-001.md", + "behavior": "Open a minimal .blend and expose scene/object/collection context from authoritative Main.", + "outputs": [ + "desktop fixture", + "outliner report", + "Chromium path" + ], + "acceptance": [ + "stable IDs and selection revision match", + "missing data is structured", + "reopen preserves context" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-002", + "phase": "P2", + "title": "object_collection_parent_transform_workflow", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P2-001" + ], + "parityId": "OBJECT.TRANSFORM_HIERARCHY", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-scene", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-002.md", + "behavior": "Edit object transform, collection membership and parent hierarchy through Main transactions.", + "outputs": [ + "desktop/WASM golden", + "negative cases", + "save/reopen receipt" + ], + "acceptance": [ + "world matrix parity", + "cycle/locked/library edits reject", + "undo/redo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-003", + "phase": "P2", + "title": "mesh_edit_core_operations", + "kind": "feature", + "owner": "MESH", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P2-002" + ], + "parityId": "MESH.EDIT_CORE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-mesh", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-003.md", + "behavior": "Expose bounded vertex/edge/face selection plus merge/dissolve/extrude/inset/bevel/loop-cut.", + "outputs": [ + "Blender fixture set", + "topology comparator", + "Chromium edit path" + ], + "acceptance": [ + "topology/attributes match", + "invalid selection and budget fail closed", + "single transaction and reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-004", + "phase": "P2", + "title": "dual_viewport_sceneir_render_path", + "kind": "feature", + "owner": "VIEWPORT", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P2-003" + ], + "parityId": "VIEWPORT.MAIN_OFFSCREEN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-viewport", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-004.md", + "behavior": "Render the same validated SceneIR through main-thread WebGL2 and OffscreenCanvas Worker paths.", + "outputs": [ + "pixel report", + "viewport diagnostics", + "device recovery" + ], + "acceptance": [ + "both paths have nonblank pixels", + "selection/camera revision is shared", + "device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-005", + "phase": "P2", + "title": "close_p0_user_loop", + "kind": "feature", + "owner": "INTEGRATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P1-005", + "WBV2-P2-004" + ], + "parityId": "WORKFLOW.P0_USER_LOOP", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-integration", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-005.md", + "behavior": "Prove open -> edit -> undo -> redo -> save -> restart -> reopen -> GLB in one production flow.", + "outputs": [ + "P0 workflow report", + "release binding", + "rollback receipt" + ], + "acceptance": [ + "Main revision and exported asset are bound", + "fault/cancel leaves old state", + "Chromium production path passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-001", + "phase": "P3", + "title": "material_uv_principled_asset_workflow", + "kind": "feature", + "owner": "MATERIAL", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005" + ], + "parityId": "MATERIAL.PBR_UV", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-001.md", + "behavior": "Edit material slots, UVs and declared Principled/Image/Normal graph nodes with content-addressed textures.", + "outputs": [ + "material golden", + "texture receipt", + "loss report" + ], + "acceptance": [ + "desktop/WASM node fields match", + "unsupported node retained/blocked", + "packed asset survives reopen" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-002", + "phase": "P3", + "title": "keyframe_timeline_action_workflow", + "kind": "feature", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-005", + "WBV2-P3-001" + ], + "parityId": "ANIMATION.TRS_ACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-002.md", + "behavior": "Create/edit TRS keyframes, timeline and declared Action interpolation through Main.", + "outputs": [ + "frame golden", + "animation comparator", + "reopen report" + ], + "acceptance": [ + "sampled values and handles match", + "stale frame result rejected", + "undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-003", + "phase": "P3", + "title": "armature_pose_constraint_skin_workflow", + "kind": "feature", + "owner": "RIG", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P3-002" + ], + "parityId": "RIG.POSE_SKIN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-rig", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-003.md", + "behavior": "Read and edit declared armature pose/constraint/weight/shape-key slices with bounded evaluation.", + "outputs": [ + "pose golden", + "skin report", + "unsupported matrix" + ], + "acceptance": [ + "pose matrices and weights match", + "unsupported constraint is explicit", + "save/reopen and small recovery pass" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-004", + "phase": "P3", + "title": "glb_roundtrip_and_loss_report", + "kind": "feature", + "owner": "IO", + "dependsOn": [ + "WBV2-P2-005", + "WBV2-P3-001", + "WBV2-P3-003" + ], + "parityId": "IO.GLB_ROUNDTRIP", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-io", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-004.md", + "behavior": "Import/export declared GLB mesh/PBR/texture/morph/skin/animation and report non-mapped semantics.", + "outputs": [ + "GLB fixtures", + "desktop reimport report", + "loss report" + ], + "acceptance": [ + "roundtrip canonical graph matches", + "sparse/external URI/budget negatives reject", + "no silent loss" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-005", + "phase": "P3", + "title": "library_asset_append_link_override", + "kind": "feature", + "owner": "ASSET", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P2-001", + "WBV2-P3-004" + ], + "parityId": "ASSET.LIBRARY_OPERATIONS", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-assets", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-005.md", + "behavior": "Support declared append/link/override ownership, reload and missing-library semantics.", + "outputs": [ + "library fixtures", + "ownership report", + "negative matrix" + ], + "acceptance": [ + "source/hash/owner identity preserved", + "linked mutation blocked", + "stale generation and missing source fail closed" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-001", + "phase": "P4", + "title": "modifier_graph_and_apply_slices", + "kind": "feature", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005", + "WBV2-P3-005" + ], + "parityId": "MODIFIER.DECLARED_SLICES", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-001.md", + "behavior": "Enable one declared modifier parameter/apply workflow at a time with dependency-aware blocking.", + "outputs": [ + "modifier goldens", + "dependency report", + "negative cases" + ], + "acceptance": [ + "desktop/evaluated Main match", + "unknown modifier retained and blocked", + "apply/undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-002", + "phase": "P4", + "title": "geometry_nodes_and_shader_allowlist", + "kind": "feature", + "owner": "NODES", + "dependsOn": [ + "WBV2-P3-001", + "WBV2-P4-001" + ], + "parityId": "NODES.ALLOWLIST", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-002.md", + "behavior": "Read/write/evaluate only declared Geometry Nodes and shader graph allowlists with resource budgets.", + "outputs": [ + "node fixtures", + "compile/cache receipts", + "unsupported graph reports" + ], + "acceptance": [ + "node/socket/link/default parity", + "budget and unknown-node block before commit", + "compile failure rolls back" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-003", + "phase": "P4", + "title": "sculpt_nonmesh_and_paint_bounded_slices", + "kind": "feature", + "owner": "SCULPT", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P4-002" + ], + "parityId": "SCULPT.NONMESH.PAINT_BOUNDED", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-003.md", + "behavior": "Expose declared sculpt attributes/strokes, Curve/Surface/Font/PointCloud and paint slices with explicit PBVH limits.", + "outputs": [ + "non-mesh fixtures", + "stroke report", + "capability blocks" + ], + "acceptance": [ + "Main commit is atomic", + "unsupported brush/solver returns stable code", + "GPU/OOM/restart recovery passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-004", + "phase": "P4", + "title": "simulation_cache_identity_and_lifecycle", + "kind": "feature", + "owner": "SIMULATION", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P4-002", + "WBV2-P4-003" + ], + "parityId": "SIMULATION.CACHE_LIFECYCLE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G3", + "card": "docs/tasks/WBV2-P4-004.md", + "behavior": "Bind declared simulation cache to source/settings/revision hashes with cancellation, LRU and restart recovery.", + "outputs": [ + "cache fixtures", + "identity report", + "quarantine evidence" + ], + "acceptance": [ + "stale/corrupt cache never publishes", + "small cache recovers after restart", + "budget release is observable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-001", + "phase": "P5", + "title": "render_capability_routing", + "kind": "feature", + "owner": "RENDER", + "dependsOn": [ + "WBV2-P2-004", + "WBV2-P4-002", + "WBV2-P4-004" + ], + "parityId": "RENDER.ROUTING", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-001.md", + "behavior": "Route bounded Eevee/WebGL capabilities locally and unsupported render classes to SERVER_EXACT or EXCLUDED.", + "outputs": [ + "render receipts", + "pixel golden", + "routing report" + ], + "acceptance": [ + "source/settings/build identity bound", + "unsupported route cannot pretend local success", + "cancel/device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-002", + "phase": "P5", + "title": "compositor_sequencer_media_recovery", + "kind": "feature", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P3-002", + "WBV2-P5-001" + ], + "parityId": "MEDIA.BOUNDED_WORKFLOW", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-002.md", + "behavior": "Provide declared compositor/sequencer/codec/proxy/audio slices with revision and recovery gates.", + "outputs": [ + "media receipts", + "recovery report", + "audio/session diagnostics" + ], + "acceptance": [ + "seek/decode revision ordering", + "cancel/timeout does not publish", + "quota/OOM/restart leaves project valid" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-003", + "phase": "P5", + "title": "server_job_result_binding", + "kind": "feature", + "owner": "SERVER", + "dependsOn": [ + "WBV2-P0-003", + "WBV2-P5-001", + "WBV2-P5-002" + ], + "parityId": "SERVER.JOB_BINDING", + "implementationClass": "SERVER_EXACT", + "parallelGroup": "p5-server", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-003.md", + "behavior": "Bind server render/encode/physics jobs to immutable input/settings/build/output hashes and explicit lifecycle states.", + "outputs": [ + "server protocol", + "idempotency receipt", + "negative matrix" + ], + "acceptance": [ + "duplicate request is idempotent", + "stale result cannot bind", + "timeout/cancel/OOM produces no READY output" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-001", + "phase": "P6", + "title": "scripting_default_deny_and_audit", + "kind": "feature", + "owner": "SECURITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P5-003" + ], + "parityId": "SECURITY.SCRIPTING", + "implementationClass": "EXCLUDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-001.md", + "behavior": "Read text/metadata and expose audited, budgeted, default-deny script policy without arbitrary execution.", + "outputs": [ + "policy manifest", + "malicious fixtures", + "audit report" + ], + "acceptance": [ + "autorun/network/add-on defaults deny", + "sandbox cancellation/dispose works", + "no secret or filesystem escape" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-002", + "phase": "P6", + "title": "performance_fault_and_recovery_matrix", + "kind": "enabling", + "owner": "RELIABILITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P1-005", + "WBV2-P2-004", + "WBV2-P6-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-002.md", + "behavior": "Run deterministic geometry/texture/media/cache budgets and inject OOM/quota/device/network faults.", + "outputs": [ + "budget matrix", + "fault reports", + "resource release ledger" + ], + "acceptance": [ + "100k/1M/10M thresholds recorded", + "fault leaves old revision usable", + "all owned resources return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-003", + "phase": "P6", + "title": "offline_ci_sbom_and_rollback_release", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P6-001", + "WBV2-P6-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-release", + "gate": "G4", + "card": "docs/tasks/WBV2-P6-003.md", + "behavior": "Produce reproducible offline/source/binary release packages with CI lanes, SBOM and rollback evidence.", + "outputs": [ + "RC manifest", + "offline archive", + "CI reports" + ], + "acceptance": [ + "quick/Chromium/release lanes pass", + "artifact hashes reproduce", + "upgrade/rollback and known limitations are tested" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-001", + "phase": "P7", + "title": "cluster_full_blender_gap_inventory", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-002", + "WBV2-P6-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-001.md", + "behavior": "Cluster remaining Blender 5.2 data-block/operator/editor/node/format gaps by family and evidence class.", + "outputs": [ + "cluster catalog", + "coverage report", + "risk ranking" + ], + "acceptance": [ + "each gap has stable ID and owner", + "negative-only/unsupported is not positive parity", + "clusters are deterministic" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-002", + "phase": "P7", + "title": "generate_atomic_family_gap_queue", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-002.md", + "behavior": "Generate one task per parityId x observable behavior x implementation class with parent/hash context.", + "outputs": [ + "task index", + "task catalog", + "task cards" + ], + "acceptance": [ + "one active ready task", + "no guessed successor", + "each card fits context budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-003", + "phase": "P7", + "title": "full_parity_candidate_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P7-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P7-003.md", + "behavior": "Recompute parity closure, evidence health, recovery health and release decision from machine manifests.", + "outputs": [ + "parity release report", + "known limitations", + "final decision" + ], + "acceptance": [ + "all claims bind to evidence", + "blocked/excluded/server classes remain explicit", + "queue and protected hashes pass" + ], + "status": "blocked", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-000", + "phase": "P8", + "title": "authorize_recovery_capability_root", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-000.md", + "behavior": "Authorize a recovery epoch without rewriting the blocked P7 manifest.", + "outputs": [ + "recovery plan", + "root manifest", + "queue authorization" + ], + "acceptance": [ + "P7 evidence remains hash exact", + "recovery scope is explicit", + "one recovery task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P8-001", + "phase": "P8", + "title": "rebaseline_mutable_inventories", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-001.md", + "behavior": "Rebaseline mutable WBV2 plan and dependency inventory inputs while preserving historical manifests.", + "outputs": [ + "semantic drift report", + "current inventory baseline", + "manifest" + ], + "acceptance": [ + "only expected mutable hashes drift", + "dependency closure is unchanged", + "historical manifests remain unmodified" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-002", + "phase": "P8", + "title": "close_atomic_chromium_receipts", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P8-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-receipts", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-002.md", + "behavior": "Produce and bind all 45 atomic Chromium family receipts.", + "outputs": [ + "Chromium report", + "45 receipt index", + "receipt manifests" + ], + "acceptance": [ + "45 receipts are manifest-bound", + "desktop/WASM/save-reopen behaviors are explicit", + "Chromium is the only browser" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-003", + "phase": "P8", + "title": "authorize_m12_provenance_epoch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-provenance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-003.md", + "behavior": "Bind restored M12 sources and explicitly rebaseline unavailable originals in a new provenance epoch.", + "outputs": [ + "provenance epoch", + "replacement bindings", + "manifest" + ], + "acceptance": [ + "22 restored originals stay exact", + "62 unavailable entries are not called restored", + "all replacements are hash-bound" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-004", + "phase": "P8", + "title": "recompute_recovery_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P8-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-004.md", + "behavior": "Recompute the release decision from the recovery epoch and atomic receipts.", + "outputs": [ + "release gate", + "known limitations", + "final manifest" + ], + "acceptance": [ + "all receipts bind to manifests", + "provenance epoch is explicit", + "all governance gates pass" + ], + "status": "in_progress", + "ready": false, + "queueMutationAllowed": false + }, + { + "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": "done", + "ready": false, + "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": "done", + "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": "done", + "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": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-000", + "phase": "P10", + "title": "authorize_native_engine_parity_continuation", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P9-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-governance", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-000.md", + "behavior": "Authorize native Blender/WASM engine parity continuation after bounded Chromium capability evidence.", + "outputs": [ + "continuation receipt", + "native parity plan", + "scope limits" + ], + "acceptance": [ + "P9 evidence remains hash-bound", + "native build/runtime is explicit", + "one native parity task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P10-001", + "phase": "P10", + "title": "reconcile_wbv2_inventory_source_drift", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-inventory", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-001.md", + "behavior": "Record the authorized mutable WBV2 plan drift and prove dependency closure stability without rewriting historical P0 evidence.", + "outputs": [ + "current source hash baseline", + "drift report", + "checker compatibility" + ], + "acceptance": [ + "historical P0 hashes remain unchanged", + "only authorized plan drift is recorded", + "dependency roots/lockfile/closure remain stable", + "inventory checker passes using current baseline" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-002", + "phase": "P10", + "title": "bind_native_and_wasm_engine_receipts", + "kind": "feature", + "owner": "ENGINE", + "dependsOn": [ + "WBV2-P10-001" + ], + "parityId": "ENGINE.NATIVE_WASM_BRIDGE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p10-engine", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-002.md", + "behavior": "Bind Mesh, Modifier, and Asset Catalog receipts to the compiled Blender native binary and web_engine.wasm runtime.", + "outputs": [ + "native receipt", + "WASM receipt", + "Chromium engine report" + ], + "acceptance": [ + "native Blender binary is source-bound", + "WASM binary and JS are hash-bound", + "same mutation reaches real engine/Main", + "save/reopen and failures remain exact" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-003", + "phase": "P10", + "title": "expand_core_module_operator_matrix", + "kind": "feature", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-002" + ], + "parityId": "CORE.MODULE_MATRIX", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-matrix", + "gate": "G7", + "card": "docs/tasks/WBV2-P10-003.md", + "behavior": "Expand the three proven capability modules with data-driven operator coverage and aggregate regression receipts.", + "outputs": [ + "module matrix", + "shard reports", + "aggregate manifest" + ], + "acceptance": [ + "positive cases are L2+", + "negative cases do not mutate Main", + "shards use one catalog hash", + "unmapped and retained-negative cases stay explicit" + ], + "status": "in_progress", + "ready": true, + "queueMutationAllowed": false + } + ], + "parentPlan": { + "path": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "sha256": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782" + }, + "recoveryRoot": "WBV2-P10-000", + "parentRecoveryPlan": { + "path": "tests/golden/WBV2-P10-001/native-parity-task-plan.json", + "sha256": "1dc85326304c28ded4bdd12ff905de7522bcd61d783bf4adf20ac628432a7512" + } +} diff --git a/tests/golden/WBV2-P10-002/task-context.json b/tests/golden/WBV2-P10-002/task-context.json new file mode 100644 index 000000000..366afe6da --- /dev/null +++ b/tests/golden/WBV2-P10-002/task-context.json @@ -0,0 +1,197 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-002", + "parentTask": "WBV2-P10-001", + "status": "in_progress", + "goal": "Bind the proven Mesh, Modifier, and Asset Catalog mutations to the compiled Blender native binary and the checked-in web_engine.wasm runtime, with Chromium as the browser gate.", + "scope": { + "gap": "workflow:bind_native_and_wasm_engine_receipts", + "ownerFamily": "ENGINE", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "build_blender_native/bin/blender --version", + "node tools/web/check-wbv2-native-engine.mjs --write", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-native-engine-production.spec.ts", + "node tools/web/generate-wbv2-native-engine-receipt.mjs --write", + "node tools/web/check-task-context.mjs --task WBV2-P10-002 --write" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1958, + "contextRemainingTokens": 489 + }, + "source": { + "bytes": 7946, + "tokens": 1987 + }, + "selected": [], + "excluded": [ + { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "bytes": 15643984, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "web/app/src/vendor/blender/web_engine.js", + "bytes": 132196, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "bytes": 126797, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/WBV2-P9-004/feature-parity-gate-report.json", + "bytes": 2865, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "web/app/src/engine-client/WebEngineClient.ts", + "bytes": 16197, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "web/app/src/workers/web-engine.worker.ts", + "bytes": 97032, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "web/tests/e2e/wbv2-native-engine-production.spec.ts", + "bytes": 11948, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/WBV2-P10-002/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/WBV2-P10-002.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/WBV2-P10-002/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "native Blender binary is source-bound", + "WASM binary and JS are hash-bound", + "same mutation reaches real engine/Main", + "save/reopen and failures remain exact" + ], + "nextTask": "WBV2-P10-003", + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/WBV2-P10-002.md", + "taskIndex": "tests/golden/WBV2/task-index.json", + "parentManifest": "tests/golden/WBV2-P10-001/manifest.json", + "parentStatus": "docs/status/WBV2-P10-001.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/WBV2-P10-002.md", + "tests/golden/WBV2-P10-001/manifest.json", + "docs/status/WBV2-P10-001.md" + ], + "machineOnly": [ + "tests/golden/WBV2/task-index.json", + "tests/golden/M15-03A/task-catalog.jsonl" + ], + "optionalByNeed": [ + "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "任务卡列出的精确协议/生产路径", + "任务卡明确命名的长期计划小节" + ], + "forbiddenByDefault": [ + "完整 CURRENT_EXECUTION_PLAN.md", + "完整 PROJECT_STATUS_AND_NEXT_WORK.md", + "全部 docs/status/*.md", + "完整 parity/WBS 计划", + "README 历史和 test-results/" + ] + }, + "parent": { + "manifest": { + "schemaVersion": 1, + "task": "WBV2-P10-001", + "parentTask": "WBV2-P10-000", + "status": "done", + "nextTask": "WBV2-P10-002", + "artifactCount": 13 + }, + "statusSummary": [ + "# WBV2-P10-001 status", + "- task: `WBV2-P10-001`; parent: `WBV2-P10-000`; status: `done`", + "- plan drift: `1` authorized mutable plan hash", + "- dependency packages: `144`; lockfile/roots/closure: `STABLE`", + "- historical P0 hashes: preserved", + "- nextTask: `WBV2-P10-002`", + "The current WBV2 plan hash is recorded as an additive epoch-1 baseline. The historical P0-002 source-hashes.json and all historical manifests remain unchanged. Dependency roots, lockfile, package closure, and package count remain stable." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1775, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 44, + "taskTokens": 444 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2803, + "lines": 51, + "tokens": 701 + }, + { + "path": "docs/tasks/WBV2-P10-002.md", + "bytes": 1775, + "lines": 44, + "tokens": 444 + }, + { + "path": "tests/golden/WBV2-P10-001/manifest.json", + "bytes": 2872, + "lines": 75, + "tokens": 718 + }, + { + "path": "docs/status/WBV2-P10-001.md", + "bytes": 496, + "lines": 10, + "tokens": 124 + } + ], + "sourceTokens": 1987, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 1987, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3011, + "serializedContextTokens": 715, + "withinBudget": true + } +} diff --git a/tests/golden/WBV2-P10-003/manifest.json b/tests/golden/WBV2-P10-003/manifest.json new file mode 100644 index 000000000..5acfebb25 --- /dev/null +++ b/tests/golden/WBV2-P10-003/manifest.json @@ -0,0 +1,73 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-003", + "parentTask": "WBV2-P10-002", + "operation": "CORE_MODULE_OPERATOR_MATRIX_RECEIPT", + "status": "done", + "enablingTask": true, + "parityStateChange": true, + "runtime": "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", + "artifacts": { + "parentManifest": { + "path": "tests/golden/WBV2-P10-002/manifest.json", + "sha256": "dcf016adce463066fad68a0e9cf2a23a81b0d148afeb05b0e523263bd2b91da3" + }, + "engineReceipt": { + "path": "tests/golden/WBV2-P10-002/native-engine-receipt-report.json", + "sha256": "09c13b1814d61a6132ae1168d999e09b768915fe7fec652b6b965f9a6d3796f9" + }, + "matrix": { + "path": "tests/golden/WBV2-P10-003/module-matrix.json", + "sha256": "67b1d61ba9b921a3037b76efd80134c7db47d0079209d9d0edc0dd751527d024" + }, + "production": { + "path": "tests/golden/WBV2-P10-003/module-matrix-production.json", + "sha256": "a677bd01b7f6efa90dbffe4be4cb74173467f9ca06c6c087f7af5463fd587939" + }, + "productionSecond": { + "path": "tests/golden/WBV2-P10-003/module-matrix-production.second.json", + "sha256": "a677bd01b7f6efa90dbffe4be4cb74173467f9ca06c6c087f7af5463fd587939" + }, + "e2e": { + "path": "web/tests/e2e/wbv2-module-matrix.spec.ts", + "sha256": "9efca3f57ad7093589aecbfb3ba6e83660b3994f24fcac9a56d37f12441b3762" + }, + "generator": { + "path": "tools/web/generate-wbv2-module-matrix.mjs", + "sha256": "06159e091051f1dd969a78187ab9db0c606f73a8fff88956265eb404a690c006" + }, + "receiptGenerator": { + "path": "tools/web/generate-wbv2-module-matrix-receipt.mjs", + "sha256": "b06afc9da3d5014a31f1c98ff1a15eb5009d8c0e6cce1c86fdd80101ca2447ac" + }, + "report": { + "path": "tests/golden/WBV2-P10-003/module-matrix-receipt-report.json", + "sha256": "655d05c7f1c9d55d76f41c063b89ef5cd49abf0fb4f01f2cd6d7b2a5f1fa7f14" + }, + "status": { + "path": "docs/status/WBV2-P10-003.md", + "sha256": "ce391ea8cdc0ec25d523226a93a3ddfac718e9c70292ab80cd02c9c8f2d1fc69" + }, + "parityPlan": { + "path": "tests/golden/WBV2-P10-003/native-parity-task-plan.json", + "sha256": "acfe344c377cbef5b0eefaba22fab88de7d374e9a157ad53930ac6599cd6b1a9" + }, + "taskContext": { + "path": "tests/golden/WBV2-P10-003/task-context.json", + "sha256": "ed59f7698d14e39b197e3798ed704bfb8f1783002c1ff97901d604bda4d97bf2" + } + }, + "assertions": { + "cases": 9, + "positiveCases": 3, + "retainedNegative": 6, + "shards": 2, + "oneCatalogHash": true, + "inventoryEntries": 6900, + "inventoryEntriesRemaining": 6900, + "deterministic": true, + "saveReopen": "EXACT", + "historicalReproduction": false + }, + "nextTask": null +} diff --git a/tests/golden/WBV2-P10-003/module-matrix-production.json b/tests/golden/WBV2-P10-003/module-matrix-production.json new file mode 100644 index 000000000..2a9fd65df --- /dev/null +++ b/tests/golden/WBV2-P10-003/module-matrix-production.json @@ -0,0 +1,219 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-003", + "operation": "CORE_MODULE_OPERATOR_MATRIX_CHROMIUM", + "browser": "chromium", + "queueMutation": false, + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "cases": [ + { + "id": "MESH.translateMeshVertices", + "status": "PASS", + "code": "OK", + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": true, + "before": [ + -1, + -1, + 0 + ], + "after": [ + -0.75, + -1.5, + 1 + ], + "savedSha256": "7bdab0364865c2435d62b004e9c952c05c7110453be02b22836c62e36f354ec2", + "sourceSha256": "1a9a894c4106d73a4533485d9fdddfe2883f75e4692b8e53dc174308e12fe60b" + }, + { + "id": "MESH.translateMeshVertices.stale", + "status": "RETAINED_NEGATIVE", + "code": "REVISION_CONFLICT", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + } + }, + { + "id": "MESH.translateMeshVertices.malformed", + "status": "RETAINED_NEGATIVE", + "code": "REJECTED", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "translateMeshVertices contains an out-of-range vertex index" + } + }, + { + "id": "MODIFIER.setModifierEnabled", + "status": "PASS", + "code": "OK", + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": true, + "before": true, + "after": false, + "savedSha256": "37c8203ea1172fab3cf6bab421682fe56d45a2372750d50bc0eed53f19071e93", + "sourceSha256": "02e56fd6745d983ee9f5ee3f48e581f116f0c41c2d2e7dec062517b4af86718f" + }, + { + "id": "MODIFIER.setModifierEnabled.stale", + "status": "RETAINED_NEGATIVE", + "code": "REVISION_CONFLICT", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + } + }, + { + "id": "MODIFIER.setModifierEnabled.unknown", + "status": "RETAINED_NEGATIVE", + "code": "REJECTED", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "modifier UUID was not found in mesh stack" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject", + "status": "PASS", + "code": "OK", + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": true, + "receipt": { + "schemaVersion": 1, + "operation": "APPEND", + "sourceLibraryId": "library:2e0d46a97a5c7e34b76ba16a594ce76a12553ddd795992c3f48d6c1d32826153", + "sourceDataBlockId": "Object/WBV2P3005AppendObject", + "dependencyClosureSha256": "f065b78b4bb80189c2258f78725c3254d6853ecf7f4a34d4b91c62ec28a6670d", + "baseRevision": 1, + "nextRevision": 2, + "transactionCount": 1, + "mapping": [ + { + "source": "Object/WBV2P3005AppendObject", + "local": "Object/WBV2P3005AppendObject", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Mesh/WBV2P3005AppendMesh", + "local": "Mesh/WBV2P3005AppendMesh", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Material/WBV2P3005AppendMaterial", + "local": "Material/WBV2P3005AppendMaterial", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Image/WBV2P3005AppendImage", + "local": "Image/WBV2P3005AppendImage", + "owner": "LOCAL_MAIN", + "readOnly": false + } + ] + }, + "resourceClosure": { + "object": true, + "mesh": true, + "material": true, + "image": { + "assetId": "image:WBV2P3005AppendImage", + "assetStatus": "PACKED", + "height": 1024, + "id": "image:WBV2P3005AppendImage", + "libraryLinked": false, + "mimeType": "image/png", + "name": "WBV2P3005AppendImage", + "packed": true, + "packedByteLength": 261, + "sourceKind": "FILE", + "sourcePath": "project-assets/resources/udim_1001.png", + "tiles": [ + { + "assetId": "image:WBV2P3005AppendImage", + "generatedColor": [ + 0, + 0, + 0, + 0 + ], + "generatedType": 1, + "height": 1024, + "label": "", + "mimeType": "image/png", + "number": 1001, + "packed": true, + "packedByteLength": 261, + "sourcePath": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/resources/udim_1001.png", + "validSignature": true, + "width": 1024 + } + ], + "width": 1024 + } + }, + "savedSha256": "5186c694f5b0f2b1182e4790e99d6667ef067d1b95d2e6a2d0381ad29eeba326", + "sourceSha256": "dcda742db77c6af5e05b79e006a0bd89cf1e8ea8d438592cd1ed2e981c7aca76" + }, + { + "id": "ASSET_CATALOG.appendLibraryObject.stale", + "status": "RETAINED_NEGATIVE", + "code": "REVISION_CONFLICT", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "REVISION_CONFLICT", + "message": "REVISION_CONFLICT: library append base revision is stale" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject.collision", + "status": "RETAINED_NEGATIVE", + "code": "ASSET_MANIFEST_INVALID", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "ASSET_MANIFEST_INVALID", + "message": "ASSET_MANIFEST_INVALID: append closure collides with an existing local ID" + } + } + ], + "shards": [ + { + "id": "core-geometry", + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "caseIds": [ + "MESH.translateMeshVertices", + "MESH.translateMeshVertices.stale", + "MESH.translateMeshVertices.malformed", + "MODIFIER.setModifierEnabled", + "MODIFIER.setModifierEnabled.stale", + "MODIFIER.setModifierEnabled.unknown" + ], + "exitCode": 0 + }, + { + "id": "asset-resource", + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "caseIds": [ + "ASSET_CATALOG.appendLibraryObject", + "ASSET_CATALOG.appendLibraryObject.stale", + "ASSET_CATALOG.appendLibraryObject.collision" + ], + "exitCode": 0 + } + ] +} diff --git a/tests/golden/WBV2-P10-003/module-matrix-production.second.json b/tests/golden/WBV2-P10-003/module-matrix-production.second.json new file mode 100644 index 000000000..2a9fd65df --- /dev/null +++ b/tests/golden/WBV2-P10-003/module-matrix-production.second.json @@ -0,0 +1,219 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-003", + "operation": "CORE_MODULE_OPERATOR_MATRIX_CHROMIUM", + "browser": "chromium", + "queueMutation": false, + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "cases": [ + { + "id": "MESH.translateMeshVertices", + "status": "PASS", + "code": "OK", + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": true, + "before": [ + -1, + -1, + 0 + ], + "after": [ + -0.75, + -1.5, + 1 + ], + "savedSha256": "7bdab0364865c2435d62b004e9c952c05c7110453be02b22836c62e36f354ec2", + "sourceSha256": "1a9a894c4106d73a4533485d9fdddfe2883f75e4692b8e53dc174308e12fe60b" + }, + { + "id": "MESH.translateMeshVertices.stale", + "status": "RETAINED_NEGATIVE", + "code": "REVISION_CONFLICT", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + } + }, + { + "id": "MESH.translateMeshVertices.malformed", + "status": "RETAINED_NEGATIVE", + "code": "REJECTED", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "translateMeshVertices contains an out-of-range vertex index" + } + }, + { + "id": "MODIFIER.setModifierEnabled", + "status": "PASS", + "code": "OK", + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": true, + "before": true, + "after": false, + "savedSha256": "37c8203ea1172fab3cf6bab421682fe56d45a2372750d50bc0eed53f19071e93", + "sourceSha256": "02e56fd6745d983ee9f5ee3f48e581f116f0c41c2d2e7dec062517b4af86718f" + }, + { + "id": "MODIFIER.setModifierEnabled.stale", + "status": "RETAINED_NEGATIVE", + "code": "REVISION_CONFLICT", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "REVISION_CONFLICT: command base revision does not match the current SceneIR" + } + }, + { + "id": "MODIFIER.setModifierEnabled.unknown", + "status": "RETAINED_NEGATIVE", + "code": "REJECTED", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "INVALID_ARGUMENT", + "message": "modifier UUID was not found in mesh stack" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject", + "status": "PASS", + "code": "OK", + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": true, + "receipt": { + "schemaVersion": 1, + "operation": "APPEND", + "sourceLibraryId": "library:2e0d46a97a5c7e34b76ba16a594ce76a12553ddd795992c3f48d6c1d32826153", + "sourceDataBlockId": "Object/WBV2P3005AppendObject", + "dependencyClosureSha256": "f065b78b4bb80189c2258f78725c3254d6853ecf7f4a34d4b91c62ec28a6670d", + "baseRevision": 1, + "nextRevision": 2, + "transactionCount": 1, + "mapping": [ + { + "source": "Object/WBV2P3005AppendObject", + "local": "Object/WBV2P3005AppendObject", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Mesh/WBV2P3005AppendMesh", + "local": "Mesh/WBV2P3005AppendMesh", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Material/WBV2P3005AppendMaterial", + "local": "Material/WBV2P3005AppendMaterial", + "owner": "LOCAL_MAIN", + "readOnly": false + }, + { + "source": "Image/WBV2P3005AppendImage", + "local": "Image/WBV2P3005AppendImage", + "owner": "LOCAL_MAIN", + "readOnly": false + } + ] + }, + "resourceClosure": { + "object": true, + "mesh": true, + "material": true, + "image": { + "assetId": "image:WBV2P3005AppendImage", + "assetStatus": "PACKED", + "height": 1024, + "id": "image:WBV2P3005AppendImage", + "libraryLinked": false, + "mimeType": "image/png", + "name": "WBV2P3005AppendImage", + "packed": true, + "packedByteLength": 261, + "sourceKind": "FILE", + "sourcePath": "project-assets/resources/udim_1001.png", + "tiles": [ + { + "assetId": "image:WBV2P3005AppendImage", + "generatedColor": [ + 0, + 0, + 0, + 0 + ], + "generatedType": 1, + "height": 1024, + "label": "", + "mimeType": "image/png", + "number": 1001, + "packed": true, + "packedByteLength": 261, + "sourcePath": "/home/mes123456/workinf_Blender_Wasm/tests/files/web/resources/udim_1001.png", + "validSignature": true, + "width": 1024 + } + ], + "width": 1024 + } + }, + "savedSha256": "5186c694f5b0f2b1182e4790e99d6667ef067d1b95d2e6a2d0381ad29eeba326", + "sourceSha256": "dcda742db77c6af5e05b79e006a0bd89cf1e8ea8d438592cd1ed2e981c7aca76" + }, + { + "id": "ASSET_CATALOG.appendLibraryObject.stale", + "status": "RETAINED_NEGATIVE", + "code": "REVISION_CONFLICT", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "REVISION_CONFLICT", + "message": "REVISION_CONFLICT: library append base revision is stale" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject.collision", + "status": "RETAINED_NEGATIVE", + "code": "ASSET_MANIFEST_INVALID", + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "error": { + "code": "ASSET_MANIFEST_INVALID", + "message": "ASSET_MANIFEST_INVALID: append closure collides with an existing local ID" + } + } + ], + "shards": [ + { + "id": "core-geometry", + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "caseIds": [ + "MESH.translateMeshVertices", + "MESH.translateMeshVertices.stale", + "MESH.translateMeshVertices.malformed", + "MODIFIER.setModifierEnabled", + "MODIFIER.setModifierEnabled.stale", + "MODIFIER.setModifierEnabled.unknown" + ], + "exitCode": 0 + }, + { + "id": "asset-resource", + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "caseIds": [ + "ASSET_CATALOG.appendLibraryObject", + "ASSET_CATALOG.appendLibraryObject.stale", + "ASSET_CATALOG.appendLibraryObject.collision" + ], + "exitCode": 0 + } + ] +} diff --git a/tests/golden/WBV2-P10-003/module-matrix-receipt-report.json b/tests/golden/WBV2-P10-003/module-matrix-receipt-report.json new file mode 100644 index 000000000..8e7b22903 --- /dev/null +++ b/tests/golden/WBV2-P10-003/module-matrix-receipt-report.json @@ -0,0 +1,65 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-003", + "operation": "CORE_MODULE_OPERATOR_MATRIX_RECEIPT", + "status": "PASS", + "browser": "chromium", + "queueMutation": false, + "source": { + "engineReceipt": "tests/golden/WBV2-P10-002/native-engine-receipt-report.json", + "engineReceiptSha256": "09c13b1814d61a6132ae1168d999e09b768915fe7fec652b6b965f9a6d3796f9", + "catalog": { + "path": "tests/golden/WBV2-P0-002/parity-map.json", + "sha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "inventoryEntries": 6900, + "pendingEntries": 6618 + }, + "featureGate": "tests/golden/WBV2-P9-004/feature-parity-gate-report.json", + "featureGateSha256": "0a7683e08c96bd3d75bda7f420c23945081b238c91031576a149a646451d6d0f" + }, + "matrix": { + "definition": "tests/golden/WBV2-P10-003/module-matrix.json", + "definitionSha256": "67b1d61ba9b921a3037b76efd80134c7db47d0079209d9d0edc0dd751527d024", + "production": "tests/golden/WBV2-P10-003/module-matrix-production.json", + "productionSha256": "a677bd01b7f6efa90dbffe4be4cb74173467f9ca06c6c087f7af5463fd587939", + "secondProduction": "tests/golden/WBV2-P10-003/module-matrix-production.second.json", + "secondProductionSha256": "a677bd01b7f6efa90dbffe4be4cb74173467f9ca06c6c087f7af5463fd587939", + "deterministic": true, + "modules": [ + "MESH", + "MODIFIER", + "ASSET_CATALOG" + ], + "cases": 9, + "positive": 3, + "retainedNegative": 6, + "shards": [ + { + "id": "core-geometry", + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "exitCode": 0 + }, + { + "id": "asset-resource", + "catalogSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "exitCode": 0 + } + ] + }, + "coverage": { + "inventoryEntries": 6900, + "claimedComplete": 0, + "remainingExplicit": 6900, + "productionCases": 9, + "oneCatalogHash": true + }, + "assertions": { + "positiveCasesMainChanged": true, + "negativeCasesMainUnchanged": true, + "saveReopenExact": 3, + "unmappedInventoryExplicit": true, + "retainedNegativeExplicit": true, + "historicalReproduction": false + }, + "nextTask": null +} diff --git a/tests/golden/WBV2-P10-003/module-matrix.json b/tests/golden/WBV2-P10-003/module-matrix.json new file mode 100644 index 000000000..687801bf8 --- /dev/null +++ b/tests/golden/WBV2-P10-003/module-matrix.json @@ -0,0 +1,176 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-003", + "operation": "CORE_MODULE_OPERATOR_MATRIX", + "status": "READY", + "catalog": { + "path": "tests/golden/WBV2-P0-002/parity-map.json", + "sha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "inventoryEntries": 6900, + "pendingEntries": 6618 + }, + "source": { + "featureGate": "tests/golden/WBV2-P9-004/feature-parity-gate-report.json", + "featureGateSha256": "0a7683e08c96bd3d75bda7f420c23945081b238c91031576a149a646451d6d0f", + "engineReceipt": "tests/golden/WBV2-P10-002/native-engine-receipt-report.json", + "engineReceiptSha256": "09c13b1814d61a6132ae1168d999e09b768915fe7fec652b6b965f9a6d3796f9" + }, + "policy": { + "oneCatalogHash": true, + "positiveClaimsRequireMainMutation": true, + "negativeCasesNeverAdvanceRevision": true, + "unmappedInventoryExplicit": true, + "historicalReproduction": false + }, + "modules": [ + "MESH", + "MODIFIER", + "ASSET_CATALOG" + ], + "cases": [ + { + "id": "MESH.translateMeshVertices", + "family": "MESH", + "capabilityId": "CAP-MESH-POSITIVE-EDIT", + "behavior": "positive", + "implementationClass": "LOCAL_EXACT", + "expected": { + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": "EXACT" + } + }, + { + "id": "MESH.translateMeshVertices.stale", + "family": "MESH", + "capabilityId": "CAP-MESH-POSITIVE-EDIT", + "behavior": "stale_revision", + "implementationClass": "NEGATIVE_BOUNDARY", + "expected": { + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "code": "REVISION_CONFLICT" + } + }, + { + "id": "MESH.translateMeshVertices.malformed", + "family": "MESH", + "capabilityId": "CAP-MESH-POSITIVE-EDIT", + "behavior": "malformed_selection", + "implementationClass": "NEGATIVE_BOUNDARY", + "expected": { + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "code": "REJECTED" + } + }, + { + "id": "MODIFIER.setModifierEnabled", + "family": "MODIFIER", + "capabilityId": "CAP-MODIFIER-STATE-MUTATION", + "behavior": "positive", + "implementationClass": "LOCAL_EXACT", + "expected": { + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": "EXACT" + } + }, + { + "id": "MODIFIER.setModifierEnabled.stale", + "family": "MODIFIER", + "capabilityId": "CAP-MODIFIER-STATE-MUTATION", + "behavior": "stale_revision", + "implementationClass": "NEGATIVE_BOUNDARY", + "expected": { + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "code": "REVISION_CONFLICT" + } + }, + { + "id": "MODIFIER.setModifierEnabled.unknown", + "family": "MODIFIER", + "capabilityId": "CAP-MODIFIER-STATE-MUTATION", + "behavior": "unknown_modifier", + "implementationClass": "NEGATIVE_BOUNDARY", + "expected": { + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "code": "REJECTED" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject", + "family": "ASSET_CATALOG", + "capabilityId": "CAP-ASSET-CATALOG-MUTATION", + "behavior": "positive", + "implementationClass": "LOCAL_EXACT", + "expected": { + "mainMutation": "CHANGED", + "revisionDelta": 1, + "saveReopen": "EXACT" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject.stale", + "family": "ASSET_CATALOG", + "capabilityId": "CAP-ASSET-CATALOG-MUTATION", + "behavior": "stale_revision", + "implementationClass": "NEGATIVE_BOUNDARY", + "expected": { + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "code": "REVISION_CONFLICT" + } + }, + { + "id": "ASSET_CATALOG.appendLibraryObject.collision", + "family": "ASSET_CATALOG", + "capabilityId": "CAP-ASSET-CATALOG-MUTATION", + "behavior": "collision", + "implementationClass": "NEGATIVE_BOUNDARY", + "expected": { + "mainMutation": "UNCHANGED", + "revisionDelta": 0, + "code": "REJECTED" + } + } + ], + "coverage": { + "matrixCases": 9, + "positiveCases": 3, + "negativeCases": 6, + "inventoryEntries": 6900, + "inventoryEntriesClaimedComplete": 0, + "inventoryEntriesRemainingExplicit": 6900 + }, + "shards": [ + { + "id": "core-geometry", + "families": [ + "MESH", + "MODIFIER" + ], + "caseIds": [ + "MESH.translateMeshVertices", + "MESH.translateMeshVertices.stale", + "MESH.translateMeshVertices.malformed", + "MODIFIER.setModifierEnabled", + "MODIFIER.setModifierEnabled.stale", + "MODIFIER.setModifierEnabled.unknown" + ] + }, + { + "id": "asset-resource", + "families": [ + "ASSET_CATALOG" + ], + "caseIds": [ + "ASSET_CATALOG.appendLibraryObject", + "ASSET_CATALOG.appendLibraryObject.stale", + "ASSET_CATALOG.appendLibraryObject.collision" + ] + } + ] +} diff --git a/tests/golden/WBV2-P10-003/native-parity-task-plan.json b/tests/golden/WBV2-P10-003/native-parity-task-plan.json new file mode 100644 index 000000000..fa6a1235b --- /dev/null +++ b/tests/golden/WBV2-P10-003/native-parity-task-plan.json @@ -0,0 +1,1567 @@ +{ + "schemaVersion": 1, + "planId": "BLENDER_WEB_PARITY_V2_NATIVE_ENGINE_EPOCH_1", + "status": "COMPLETED_WITH_NATIVE_MODULE_MATRIX", + "authority": "queue_reactivated_after_p9_bounded_parity", + "productContract": "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "sourcePlan": "docs/BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md", + "executionPointer": "docs/EXECUTION_QUEUE.md", + "correctiveCheckpoint": { + "task": "C6-003", + "handoff": "tests/golden/corrective/C6-003/handoff.json", + "status": "active", + "blocker": null, + "queueMutation": true, + "legacyTask": "M16-GAP-00277", + "legacyParentNextTask": "M16-GAP-00277" + }, + "runtimePolicy": { + "blenderSource": "blender-5.2.0", + "browserEvidence": [ + "chromium" + ], + "forbiddenBrowsers": [ + "firefox", + "webkit" + ], + "mainAuthority": "blender_main", + "storage": [ + "opfs", + "indexeddb" + ], + "queueMutation": "enabled_after_owner_review_and_g5" + }, + "completionClasses": [ + "LOCAL_EXACT", + "LOCAL_BOUNDED", + "SERVER_EXACT", + "EXCLUDED" + ], + "gates": [ + { + "id": "G0", + "name": "scope_and_inventory", + "requires": [ + "contract", + "inventory", + "capability_matrix" + ] + }, + { + "id": "G1", + "name": "runtime_foundation", + "requires": [ + "sceneir", + "main_transaction", + "worker_lifecycle", + "storage_journal" + ] + }, + { + "id": "G2", + "name": "feature_parity", + "requires": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence" + ] + }, + { + "id": "G3", + "name": "recovery_and_security", + "requires": [ + "cancel", + "restart", + "oom_quota", + "malformed", + "dispose" + ] + }, + { + "id": "G4", + "name": "release_candidate", + "requires": [ + "offline", + "ci", + "sbom", + "rollback", + "hashes" + ] + }, + { + "id": "G5", + "name": "queue_mutation", + "requires": [ + "owner_review", + "protected_hashes", + "handoff", + "single_ready_task" + ] + } + ], + "waves": [ + { + "id": "P0", + "name": "facts_and_contracts", + "gate": "G0", + "tasks": [ + "WBV2-P0-001", + "WBV2-P0-002", + "WBV2-P0-003" + ] + }, + { + "id": "P1", + "name": "runtime_foundation", + "gate": "G1", + "tasks": [ + "WBV2-P1-001", + "WBV2-P1-002", + "WBV2-P1-003", + "WBV2-P1-004", + "WBV2-P1-005" + ] + }, + { + "id": "P2", + "name": "core_modeler_loop", + "gate": "G2", + "tasks": [ + "WBV2-P2-001", + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P2-005" + ] + }, + { + "id": "P3", + "name": "authoring_and_io", + "gate": "G2", + "tasks": [ + "WBV2-P3-001", + "WBV2-P3-002", + "WBV2-P3-003", + "WBV2-P3-004", + "WBV2-P3-005" + ] + }, + { + "id": "P4", + "name": "advanced_local_slices", + "gate": "G2", + "tasks": [ + "WBV2-P4-001", + "WBV2-P4-002", + "WBV2-P4-003", + "WBV2-P4-004" + ] + }, + { + "id": "P5", + "name": "render_and_server", + "gate": "G3", + "tasks": [ + "WBV2-P5-001", + "WBV2-P5-002", + "WBV2-P5-003" + ] + }, + { + "id": "P6", + "name": "security_performance_release", + "gate": "G4", + "tasks": [ + "WBV2-P6-001", + "WBV2-P6-002", + "WBV2-P6-003" + ] + }, + { + "id": "P7", + "name": "full_parity_gap_program", + "gate": "G5", + "tasks": [ + "WBV2-P7-001", + "WBV2-P7-002", + "WBV2-P7-003" + ] + } + ], + "taskContract": { + "onePrimaryBehavior": true, + "requiredEvidence": [ + "desktop", + "wasm_main", + "chromium", + "negative", + "persistence", + "manifest", + "status" + ], + "requiredCommands": [ + "focused", + "determinism", + "hash", + "governance" + ], + "failureState": "in_progress_or_blocked", + "successorRule": "only_from_parent_manifest_nextTask" + }, + "tasks": [ + { + "id": "WBV2-P0-001", + "phase": "P0", + "title": "reconcile_scope_and_checkpoints", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-governance", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-001.md", + "behavior": "Freeze V1/full-parity boundary and reconcile legacy/corrective pointers without queue mutation.", + "outputs": [ + "scope decision", + "checkpoint report", + "protected hash set" + ], + "acceptance": [ + "corrective owner-review status is explicit", + "legacy parent pointer is unchanged", + "plan has one activation gate" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-002", + "phase": "P0", + "title": "generate_blender52_inventory_and_parity_map", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-inventory", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-002.md", + "behavior": "Generate stable Blender 5.2 data-block/operator/editor/node/format inventory and map every entry to a completion class.", + "outputs": [ + "inventory", + "parity map", + "source hash" + ], + "acceptance": [ + "unknown entries are classified", + "inventory is deterministic", + "no entry claims feature parity without evidence" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P0-003", + "phase": "P0", + "title": "freeze_capability_error_budget_contract", + "kind": "enabling", + "owner": "PROTOCOL", + "dependsOn": [ + "WBV2-P0-001", + "WBV2-P0-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p0-contract", + "gate": "G0", + "card": "docs/tasks/WBV2-P0-003.md", + "behavior": "Freeze capability levels, stable error codes, revision, budget, cancellation and loss-report schemas.", + "outputs": [ + "versioned protocol", + "capability matrix", + "negative matrix" + ], + "acceptance": [ + "unsupported input fails closed", + "schema hashes are stable", + "migration policy preserves unknown data" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-001", + "phase": "P1", + "title": "stabilize_runtime_variants_and_source_receipts", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P0-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-runtime", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-001.md", + "behavior": "Bind single-thread/pthread WebEngine variants to pinned Blender source/build/runtime receipts.", + "outputs": [ + "runtime manifest", + "variant selector", + "fallback report" + ], + "acceptance": [ + "variant fallback is deterministic", + "source/build hash is verified", + "one engine session has one generation" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-002", + "phase": "P1", + "title": "unify_sceneir_stable_ids_and_binary_deltas", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-001" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-sceneir", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-002.md", + "behavior": "Make SceneIR/WBG1 stable IDs, topology/attribute domains and binary/range deltas canonical across desktop and WASM.", + "outputs": [ + "SceneIR schema", + "binary fixture", + "delta comparator" + ], + "acceptance": [ + "IDs survive save/reopen", + "malformed chunk is rejected", + "desktop and WASM canonical hashes match" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-003", + "phase": "P1", + "title": "unify_main_transaction_history_and_save", + "kind": "enabling", + "owner": "MAIN", + "dependsOn": [ + "WBV2-P1-002" + ], + "parityId": null, + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p1-history", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-003.md", + "behavior": "Use one Main transaction/revision/history contract for commit, undo/redo, atomic save and reopen.", + "outputs": [ + "transaction contract", + "history receipt", + "save/reopen runner" + ], + "acceptance": [ + "failed/no-op commands add no history", + "stale revision cannot commit", + "reopen state is byte/hash stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-004", + "phase": "P1", + "title": "harden_worker_cancel_restart_and_dispose", + "kind": "enabling", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P1-001", + "WBV2-P1-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-lifecycle", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-004.md", + "behavior": "Make cancellation, late-result rejection, Worker restart and resource disposal common to all domains.", + "outputs": [ + "lifecycle runner", + "fault report", + "dispose counters" + ], + "acceptance": [ + "cancel never publishes result", + "generation mismatch is rejected", + "CPU/WASM/GPU owners return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P1-005", + "phase": "P1", + "title": "harden_opfs_indexeddb_journal_recovery", + "kind": "enabling", + "owner": "STORAGE", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P1-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p1-storage", + "gate": "G1", + "card": "docs/tasks/WBV2-P1-005.md", + "behavior": "Unify OPFS staging/content addressing and IndexedDB metadata/journal recovery.", + "outputs": [ + "storage schema", + "crash fixtures", + "recovery checker" + ], + "acceptance": [ + "interrupted commit leaves old project usable", + "hash mismatch quarantines payload", + "small project recovers after restart" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-001", + "phase": "P2", + "title": "open_blend_scene_context_and_outliner", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P1-005" + ], + "parityId": "EDITOR.OPEN_SCENE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-editor", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-001.md", + "behavior": "Open a minimal .blend and expose scene/object/collection context from authoritative Main.", + "outputs": [ + "desktop fixture", + "outliner report", + "Chromium path" + ], + "acceptance": [ + "stable IDs and selection revision match", + "missing data is structured", + "reopen preserves context" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-002", + "phase": "P2", + "title": "object_collection_parent_transform_workflow", + "kind": "feature", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1-003", + "WBV2-P2-001" + ], + "parityId": "OBJECT.TRANSFORM_HIERARCHY", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-scene", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-002.md", + "behavior": "Edit object transform, collection membership and parent hierarchy through Main transactions.", + "outputs": [ + "desktop/WASM golden", + "negative cases", + "save/reopen receipt" + ], + "acceptance": [ + "world matrix parity", + "cycle/locked/library edits reject", + "undo/redo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-003", + "phase": "P2", + "title": "mesh_edit_core_operations", + "kind": "feature", + "owner": "MESH", + "dependsOn": [ + "WBV2-P1-002", + "WBV2-P2-002" + ], + "parityId": "MESH.EDIT_CORE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p2-mesh", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-003.md", + "behavior": "Expose bounded vertex/edge/face selection plus merge/dissolve/extrude/inset/bevel/loop-cut.", + "outputs": [ + "Blender fixture set", + "topology comparator", + "Chromium edit path" + ], + "acceptance": [ + "topology/attributes match", + "invalid selection and budget fail closed", + "single transaction and reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-004", + "phase": "P2", + "title": "dual_viewport_sceneir_render_path", + "kind": "feature", + "owner": "VIEWPORT", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P2-003" + ], + "parityId": "VIEWPORT.MAIN_OFFSCREEN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-viewport", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-004.md", + "behavior": "Render the same validated SceneIR through main-thread WebGL2 and OffscreenCanvas Worker paths.", + "outputs": [ + "pixel report", + "viewport diagnostics", + "device recovery" + ], + "acceptance": [ + "both paths have nonblank pixels", + "selection/camera revision is shared", + "device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P2-005", + "phase": "P2", + "title": "close_p0_user_loop", + "kind": "feature", + "owner": "INTEGRATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-003", + "WBV2-P1-005", + "WBV2-P2-004" + ], + "parityId": "WORKFLOW.P0_USER_LOOP", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p2-integration", + "gate": "G2", + "card": "docs/tasks/WBV2-P2-005.md", + "behavior": "Prove open -> edit -> undo -> redo -> save -> restart -> reopen -> GLB in one production flow.", + "outputs": [ + "P0 workflow report", + "release binding", + "rollback receipt" + ], + "acceptance": [ + "Main revision and exported asset are bound", + "fault/cancel leaves old state", + "Chromium production path passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-001", + "phase": "P3", + "title": "material_uv_principled_asset_workflow", + "kind": "feature", + "owner": "MATERIAL", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005" + ], + "parityId": "MATERIAL.PBR_UV", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-001.md", + "behavior": "Edit material slots, UVs and declared Principled/Image/Normal graph nodes with content-addressed textures.", + "outputs": [ + "material golden", + "texture receipt", + "loss report" + ], + "acceptance": [ + "desktop/WASM node fields match", + "unsupported node retained/blocked", + "packed asset survives reopen" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-002", + "phase": "P3", + "title": "keyframe_timeline_action_workflow", + "kind": "feature", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P2-005", + "WBV2-P3-001" + ], + "parityId": "ANIMATION.TRS_ACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-authoring", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-002.md", + "behavior": "Create/edit TRS keyframes, timeline and declared Action interpolation through Main.", + "outputs": [ + "frame golden", + "animation comparator", + "reopen report" + ], + "acceptance": [ + "sampled values and handles match", + "stale frame result rejected", + "undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-003", + "phase": "P3", + "title": "armature_pose_constraint_skin_workflow", + "kind": "feature", + "owner": "RIG", + "dependsOn": [ + "WBV2-P2-002", + "WBV2-P3-002" + ], + "parityId": "RIG.POSE_SKIN", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-rig", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-003.md", + "behavior": "Read and edit declared armature pose/constraint/weight/shape-key slices with bounded evaluation.", + "outputs": [ + "pose golden", + "skin report", + "unsupported matrix" + ], + "acceptance": [ + "pose matrices and weights match", + "unsupported constraint is explicit", + "save/reopen and small recovery pass" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-004", + "phase": "P3", + "title": "glb_roundtrip_and_loss_report", + "kind": "feature", + "owner": "IO", + "dependsOn": [ + "WBV2-P2-005", + "WBV2-P3-001", + "WBV2-P3-003" + ], + "parityId": "IO.GLB_ROUNDTRIP", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p3-io", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-004.md", + "behavior": "Import/export declared GLB mesh/PBR/texture/morph/skin/animation and report non-mapped semantics.", + "outputs": [ + "GLB fixtures", + "desktop reimport report", + "loss report" + ], + "acceptance": [ + "roundtrip canonical graph matches", + "sparse/external URI/budget negatives reject", + "no silent loss" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P3-005", + "phase": "P3", + "title": "library_asset_append_link_override", + "kind": "feature", + "owner": "ASSET", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P2-001", + "WBV2-P3-004" + ], + "parityId": "ASSET.LIBRARY_OPERATIONS", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p3-assets", + "gate": "G2", + "card": "docs/tasks/WBV2-P3-005.md", + "behavior": "Support declared append/link/override ownership, reload and missing-library semantics.", + "outputs": [ + "library fixtures", + "ownership report", + "negative matrix" + ], + "acceptance": [ + "source/hash/owner identity preserved", + "linked mutation blocked", + "stale generation and missing source fail closed" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-001", + "phase": "P4", + "title": "modifier_graph_and_apply_slices", + "kind": "feature", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-005", + "WBV2-P3-005" + ], + "parityId": "MODIFIER.DECLARED_SLICES", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-001.md", + "behavior": "Enable one declared modifier parameter/apply workflow at a time with dependency-aware blocking.", + "outputs": [ + "modifier goldens", + "dependency report", + "negative cases" + ], + "acceptance": [ + "desktop/evaluated Main match", + "unknown modifier retained and blocked", + "apply/undo/save/reopen stable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-002", + "phase": "P4", + "title": "geometry_nodes_and_shader_allowlist", + "kind": "feature", + "owner": "NODES", + "dependsOn": [ + "WBV2-P3-001", + "WBV2-P4-001" + ], + "parityId": "NODES.ALLOWLIST", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-002.md", + "behavior": "Read/write/evaluate only declared Geometry Nodes and shader graph allowlists with resource budgets.", + "outputs": [ + "node fixtures", + "compile/cache receipts", + "unsupported graph reports" + ], + "acceptance": [ + "node/socket/link/default parity", + "budget and unknown-node block before commit", + "compile failure rolls back" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-003", + "phase": "P4", + "title": "sculpt_nonmesh_and_paint_bounded_slices", + "kind": "feature", + "owner": "SCULPT", + "dependsOn": [ + "WBV2-P2-003", + "WBV2-P2-004", + "WBV2-P4-002" + ], + "parityId": "SCULPT.NONMESH.PAINT_BOUNDED", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G2", + "card": "docs/tasks/WBV2-P4-003.md", + "behavior": "Expose declared sculpt attributes/strokes, Curve/Surface/Font/PointCloud and paint slices with explicit PBVH limits.", + "outputs": [ + "non-mesh fixtures", + "stroke report", + "capability blocks" + ], + "acceptance": [ + "Main commit is atomic", + "unsupported brush/solver returns stable code", + "GPU/OOM/restart recovery passes" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P4-004", + "phase": "P4", + "title": "simulation_cache_identity_and_lifecycle", + "kind": "feature", + "owner": "SIMULATION", + "dependsOn": [ + "WBV2-P1-005", + "WBV2-P4-002", + "WBV2-P4-003" + ], + "parityId": "SIMULATION.CACHE_LIFECYCLE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p4-domains", + "gate": "G3", + "card": "docs/tasks/WBV2-P4-004.md", + "behavior": "Bind declared simulation cache to source/settings/revision hashes with cancellation, LRU and restart recovery.", + "outputs": [ + "cache fixtures", + "identity report", + "quarantine evidence" + ], + "acceptance": [ + "stale/corrupt cache never publishes", + "small cache recovers after restart", + "budget release is observable" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-001", + "phase": "P5", + "title": "render_capability_routing", + "kind": "feature", + "owner": "RENDER", + "dependsOn": [ + "WBV2-P2-004", + "WBV2-P4-002", + "WBV2-P4-004" + ], + "parityId": "RENDER.ROUTING", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-001.md", + "behavior": "Route bounded Eevee/WebGL capabilities locally and unsupported render classes to SERVER_EXACT or EXCLUDED.", + "outputs": [ + "render receipts", + "pixel golden", + "routing report" + ], + "acceptance": [ + "source/settings/build identity bound", + "unsupported route cannot pretend local success", + "cancel/device loss releases resources" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-002", + "phase": "P5", + "title": "compositor_sequencer_media_recovery", + "kind": "feature", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P3-002", + "WBV2-P5-001" + ], + "parityId": "MEDIA.BOUNDED_WORKFLOW", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p5-media", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-002.md", + "behavior": "Provide declared compositor/sequencer/codec/proxy/audio slices with revision and recovery gates.", + "outputs": [ + "media receipts", + "recovery report", + "audio/session diagnostics" + ], + "acceptance": [ + "seek/decode revision ordering", + "cancel/timeout does not publish", + "quota/OOM/restart leaves project valid" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P5-003", + "phase": "P5", + "title": "server_job_result_binding", + "kind": "feature", + "owner": "SERVER", + "dependsOn": [ + "WBV2-P0-003", + "WBV2-P5-001", + "WBV2-P5-002" + ], + "parityId": "SERVER.JOB_BINDING", + "implementationClass": "SERVER_EXACT", + "parallelGroup": "p5-server", + "gate": "G3", + "card": "docs/tasks/WBV2-P5-003.md", + "behavior": "Bind server render/encode/physics jobs to immutable input/settings/build/output hashes and explicit lifecycle states.", + "outputs": [ + "server protocol", + "idempotency receipt", + "negative matrix" + ], + "acceptance": [ + "duplicate request is idempotent", + "stale result cannot bind", + "timeout/cancel/OOM produces no READY output" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-001", + "phase": "P6", + "title": "scripting_default_deny_and_audit", + "kind": "feature", + "owner": "SECURITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P5-003" + ], + "parityId": "SECURITY.SCRIPTING", + "implementationClass": "EXCLUDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-001.md", + "behavior": "Read text/metadata and expose audited, budgeted, default-deny script policy without arbitrary execution.", + "outputs": [ + "policy manifest", + "malicious fixtures", + "audit report" + ], + "acceptance": [ + "autorun/network/add-on defaults deny", + "sandbox cancellation/dispose works", + "no secret or filesystem escape" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-002", + "phase": "P6", + "title": "performance_fault_and_recovery_matrix", + "kind": "enabling", + "owner": "RELIABILITY", + "dependsOn": [ + "WBV2-P1-004", + "WBV2-P1-005", + "WBV2-P2-004", + "WBV2-P6-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-safety", + "gate": "G3", + "card": "docs/tasks/WBV2-P6-002.md", + "behavior": "Run deterministic geometry/texture/media/cache budgets and inject OOM/quota/device/network faults.", + "outputs": [ + "budget matrix", + "fault reports", + "resource release ledger" + ], + "acceptance": [ + "100k/1M/10M thresholds recorded", + "fault leaves old revision usable", + "all owned resources return to budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P6-003", + "phase": "P6", + "title": "offline_ci_sbom_and_rollback_release", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P6-001", + "WBV2-P6-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p6-release", + "gate": "G4", + "card": "docs/tasks/WBV2-P6-003.md", + "behavior": "Produce reproducible offline/source/binary release packages with CI lanes, SBOM and rollback evidence.", + "outputs": [ + "RC manifest", + "offline archive", + "CI reports" + ], + "acceptance": [ + "quick/Chromium/release lanes pass", + "artifact hashes reproduce", + "upgrade/rollback and known limitations are tested" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-001", + "phase": "P7", + "title": "cluster_full_blender_gap_inventory", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P0-002", + "WBV2-P6-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-001.md", + "behavior": "Cluster remaining Blender 5.2 data-block/operator/editor/node/format gaps by family and evidence class.", + "outputs": [ + "cluster catalog", + "coverage report", + "risk ranking" + ], + "acceptance": [ + "each gap has stable ID and owner", + "negative-only/unsupported is not positive parity", + "clusters are deterministic" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-002", + "phase": "P7", + "title": "generate_atomic_family_gap_queue", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-gap", + "gate": "G4", + "card": "docs/tasks/WBV2-P7-002.md", + "behavior": "Generate one task per parityId x observable behavior x implementation class with parent/hash context.", + "outputs": [ + "task index", + "task catalog", + "task cards" + ], + "acceptance": [ + "one active ready task", + "no guessed successor", + "each card fits context budget" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P7-003", + "phase": "P7", + "title": "full_parity_candidate_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P7-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p7-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P7-003.md", + "behavior": "Recompute parity closure, evidence health, recovery health and release decision from machine manifests.", + "outputs": [ + "parity release report", + "known limitations", + "final decision" + ], + "acceptance": [ + "all claims bind to evidence", + "blocked/excluded/server classes remain explicit", + "queue and protected hashes pass" + ], + "status": "blocked", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-000", + "phase": "P8", + "title": "authorize_recovery_capability_root", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P7-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-000.md", + "behavior": "Authorize a recovery epoch without rewriting the blocked P7 manifest.", + "outputs": [ + "recovery plan", + "root manifest", + "queue authorization" + ], + "acceptance": [ + "P7 evidence remains hash exact", + "recovery scope is explicit", + "one recovery task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P8-001", + "phase": "P8", + "title": "rebaseline_mutable_inventories", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-governance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-001.md", + "behavior": "Rebaseline mutable WBV2 plan and dependency inventory inputs while preserving historical manifests.", + "outputs": [ + "semantic drift report", + "current inventory baseline", + "manifest" + ], + "acceptance": [ + "only expected mutable hashes drift", + "dependency closure is unchanged", + "historical manifests remain unmodified" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-002", + "phase": "P8", + "title": "close_atomic_chromium_receipts", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P8-001" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-receipts", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-002.md", + "behavior": "Produce and bind all 45 atomic Chromium family receipts.", + "outputs": [ + "Chromium report", + "45 receipt index", + "receipt manifests" + ], + "acceptance": [ + "45 receipts are manifest-bound", + "desktop/WASM/save-reopen behaviors are explicit", + "Chromium is the only browser" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-003", + "phase": "P8", + "title": "authorize_m12_provenance_epoch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P8-002" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-provenance", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-003.md", + "behavior": "Bind restored M12 sources and explicitly rebaseline unavailable originals in a new provenance epoch.", + "outputs": [ + "provenance epoch", + "replacement bindings", + "manifest" + ], + "acceptance": [ + "22 restored originals stay exact", + "62 unavailable entries are not called restored", + "all replacements are hash-bound" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P8-004", + "phase": "P8", + "title": "recompute_recovery_release_gate", + "kind": "enabling", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P8-003" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p8-release", + "gate": "G5", + "card": "docs/tasks/WBV2-P8-004.md", + "behavior": "Recompute the release decision from the recovery epoch and atomic receipts.", + "outputs": [ + "release gate", + "known limitations", + "final manifest" + ], + "acceptance": [ + "all receipts bind to manifests", + "provenance epoch is explicit", + "all governance gates pass" + ], + "status": "in_progress", + "ready": false, + "queueMutationAllowed": false + }, + { + "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": "done", + "ready": false, + "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": "done", + "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": "done", + "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": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-000", + "phase": "P10", + "title": "authorize_native_engine_parity_continuation", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P9-004" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-governance", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-000.md", + "behavior": "Authorize native Blender/WASM engine parity continuation after bounded Chromium capability evidence.", + "outputs": [ + "continuation receipt", + "native parity plan", + "scope limits" + ], + "acceptance": [ + "P9 evidence remains hash-bound", + "native build/runtime is explicit", + "one native parity task is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P10-001", + "phase": "P10", + "title": "reconcile_wbv2_inventory_source_drift", + "kind": "enabling", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-000" + ], + "parityId": null, + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-inventory", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-001.md", + "behavior": "Record the authorized mutable WBV2 plan drift and prove dependency closure stability without rewriting historical P0 evidence.", + "outputs": [ + "current source hash baseline", + "drift report", + "checker compatibility" + ], + "acceptance": [ + "historical P0 hashes remain unchanged", + "only authorized plan drift is recorded", + "dependency roots/lockfile/closure remain stable", + "inventory checker passes using current baseline" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-002", + "phase": "P10", + "title": "bind_native_and_wasm_engine_receipts", + "kind": "feature", + "owner": "ENGINE", + "dependsOn": [ + "WBV2-P10-001" + ], + "parityId": "ENGINE.NATIVE_WASM_BRIDGE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "p10-engine", + "gate": "G6", + "card": "docs/tasks/WBV2-P10-002.md", + "behavior": "Bind Mesh, Modifier, and Asset Catalog receipts to the compiled Blender native binary and web_engine.wasm runtime.", + "outputs": [ + "native receipt", + "WASM receipt", + "Chromium engine report" + ], + "acceptance": [ + "native Blender binary is source-bound", + "WASM binary and JS are hash-bound", + "same mutation reaches real engine/Main", + "save/reopen and failures remain exact" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": false + }, + { + "id": "WBV2-P10-003", + "phase": "P10", + "title": "expand_core_module_operator_matrix", + "kind": "feature", + "owner": "PARITY", + "dependsOn": [ + "WBV2-P10-002" + ], + "parityId": "CORE.MODULE_MATRIX", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "p10-matrix", + "gate": "G7", + "card": "docs/tasks/WBV2-P10-003.md", + "behavior": "Expand the three proven capability modules with data-driven operator coverage and aggregate regression receipts.", + "outputs": [ + "module matrix", + "shard reports", + "aggregate manifest" + ], + "acceptance": [ + "positive cases are L2+", + "negative cases do not mutate Main", + "shards use one catalog hash", + "unmapped and retained-negative cases stay explicit" + ], + "status": "in_progress", + "ready": true, + "queueMutationAllowed": false + } + ], + "parentPlan": { + "path": "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", + "sha256": "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782" + }, + "recoveryRoot": "WBV2-P10-000", + "parentRecoveryPlan": { + "path": "tests/golden/WBV2-P10-002/native-parity-task-plan.json", + "sha256": "a6e205dec083f76ec08eef07f0085b8be228b2a7d28a16618ec3625d3e2fd19b" + } +} diff --git a/tests/golden/WBV2-P10-003/task-context.json b/tests/golden/WBV2-P10-003/task-context.json new file mode 100644 index 000000000..1840d6536 --- /dev/null +++ b/tests/golden/WBV2-P10-003/task-context.json @@ -0,0 +1,176 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P10-003", + "parentTask": "WBV2-P10-002", + "status": "in_progress", + "goal": "Run one hash-bound data-driven matrix for Mesh, Modifier, and Asset Catalog module cases instead of creating one production task per legacy operator.", + "scope": { + "gap": "workflow:expand_core_module_operator_matrix", + "ownerFamily": "PARITY", + "implementationClass": "LOCAL_BOUNDED" + }, + "commands": [ + "node tools/web/generate-wbv2-module-matrix.mjs --write", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-module-matrix.spec.ts", + "node tools/web/generate-wbv2-module-matrix-receipt.mjs --write", + "node tools/web/check-task-context.mjs --task WBV2-P10-003 --write" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 1511, + "contextRemainingTokens": 377 + }, + "source": { + "bytes": 8393, + "tokens": 2099 + }, + "selected": [], + "excluded": [ + { + "path": "tests/golden/WBV2-P9-004/feature-parity-gate-report.json", + "bytes": 2865, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "tests/golden/WBV2-P10-002/native-engine-receipt-report.json", + "bytes": 3733, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "tests/golden/WBV2-P0-002/parity-map.json", + "bytes": 5053386, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/golden/WBV2-P10-003/", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/WBV2-P10-003.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "tests/golden/WBV2-P10-003/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "positive cases are L2+", + "negative cases do not mutate Main", + "shards use one catalog hash", + "unmapped and retained-negative cases stay explicit" + ], + "nextTask": null, + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/WBV2-P10-003.md", + "taskIndex": "tests/golden/WBV2/task-index.json", + "parentManifest": "tests/golden/WBV2-P10-002/manifest.json", + "parentStatus": "docs/status/WBV2-P10-002.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/WBV2-P10-003.md", + "tests/golden/WBV2-P10-002/manifest.json", + "docs/status/WBV2-P10-002.md" + ], + "machineOnly": [ + "tests/golden/WBV2/task-index.json", + "tests/golden/M15-03A/task-catalog.jsonl" + ], + "optionalByNeed": [ + "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "任务卡列出的精确协议/生产路径", + "任务卡明确命名的长期计划小节" + ], + "forbiddenByDefault": [ + "完整 CURRENT_EXECUTION_PLAN.md", + "完整 PROJECT_STATUS_AND_NEXT_WORK.md", + "全部 docs/status/*.md", + "完整 parity/WBS 计划", + "README 历史和 test-results/" + ] + }, + "parent": { + "manifest": { + "schemaVersion": 1, + "task": "WBV2-P10-002", + "parentTask": "WBV2-P10-001", + "status": "done", + "nextTask": "WBV2-P10-003", + "artifactCount": 17 + }, + "statusSummary": [ + "# WBV2-P10-002 status", + "- task: `WBV2-P10-002`; parent: `WBV2-P10-001`; status: `done`", + "- compiled native: `Blender 5.2.0 LTS`; compiled WASM: `web_engine.wasm`", + "- real Main mutations: `Mesh + Modifier + Asset Catalog`", + "- deterministic Chromium runs: `2`; save/reopen: `3/3 EXACT`", + "- nextTask: `WBV2-P10-003`", + "The Chromium Worker loaded the checked-in WebEngine WASM and executed the native ABI through WebEngineClient. Mesh translation, modifier state, and library append all changed the real WASM Main, persisted through save/reopen, and rejected stale or malformed inputs without a late mutation. This evidence is engine-bound and still does not claim full historical reproduction." + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 1362, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 35, + "taskTokens": 341 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 2803, + "lines": 51, + "tokens": 701 + }, + { + "path": "docs/tasks/WBV2-P10-003.md", + "bytes": 1362, + "lines": 35, + "tokens": 341 + }, + { + "path": "tests/golden/WBV2-P10-002/manifest.json", + "bytes": 3548, + "lines": 91, + "tokens": 887 + }, + { + "path": "docs/status/WBV2-P10-002.md", + "bytes": 680, + "lines": 10, + "tokens": 170 + } + ], + "sourceTokens": 2099, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 2099, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 3123, + "serializedContextTokens": 688, + "withinBudget": true + } +} diff --git a/tests/golden/WBV2-P9-004/feature-parity-gate-report.json b/tests/golden/WBV2-P9-004/feature-parity-gate-report.json index 2fc34b7e0..9a741d2f8 100644 --- a/tests/golden/WBV2-P9-004/feature-parity-gate-report.json +++ b/tests/golden/WBV2-P9-004/feature-parity-gate-report.json @@ -79,7 +79,8 @@ "authorizedRebaselineOnly": true, "sourceHistoryReadOnly": true, "claimsAreEvidenceBound": true, - "terminalQueuePointer": true + "terminalQueuePointer": false, + "authorizedContinuation": "WBV2-P10-000" }, - "nextTask": null + "nextTask": "WBV2-P10-000" } diff --git a/tests/golden/WBV2-P9-004/manifest.json b/tests/golden/WBV2-P9-004/manifest.json index 2ca319762..053946f11 100644 --- a/tests/golden/WBV2-P9-004/manifest.json +++ b/tests/golden/WBV2-P9-004/manifest.json @@ -46,11 +46,11 @@ }, "report": { "path": "tests/golden/WBV2-P9-004/feature-parity-gate-report.json", - "sha256": "c8eea515dee05ed766677ccb8cabab707e130094bf7a8c8ba5bdef0b8db76fd5" + "sha256": "0a7683e08c96bd3d75bda7f420c23945081b238c91031576a149a646451d6d0f" }, "status": { "path": "docs/status/WBV2-P9-004.md", - "sha256": "1d613986df38e61e5efc368822495b9f6ad81be8bfd155de5d010d31f8529511" + "sha256": "4f59384f7c5e3652c8f69a445d44e05ede74d706a31d2734a856b6e14ee184e1" }, "featureParityPlan": { "path": "tests/golden/WBV2-P9-004/feature-parity-task-plan.json", @@ -58,7 +58,7 @@ }, "taskContext": { "path": "tests/golden/WBV2-P9-004/task-context.json", - "sha256": "8604daa21f1f70323a7db3b72ab5452a33854ef6404f7f9aa4e35f74cb94d8dc" + "sha256": "9f2d64017450df9020441b16583d654ba915d98542cbaa38f5a74bfa974b2ddc" } }, "assertions": { @@ -74,5 +74,10 @@ "authorizedRebaselineOnly": true, "fullHistoricalReproduction": false }, - "nextTask": null + "nextTask": "WBV2-P10-000", + "continuation": { + "authorized": true, + "root": "WBV2-P10-000", + "scope": "NATIVE_ENGINE_PARITY" + } } diff --git a/tests/golden/WBV2-P9-004/task-context.json b/tests/golden/WBV2-P9-004/task-context.json index 4020eb26c..1d09fcd7d 100644 --- a/tests/golden/WBV2-P9-004/task-context.json +++ b/tests/golden/WBV2-P9-004/task-context.json @@ -21,12 +21,12 @@ "limits": { "maxFiles": 12, "evidenceBytes": 8192, - "contextRemainingBytes": 2204, - "contextRemainingTokens": 549 + "contextRemainingBytes": 2200, + "contextRemainingTokens": 548 }, "source": { - "bytes": 7700, - "tokens": 1927 + "bytes": 7704, + "tokens": 1928 }, "selected": [ { @@ -78,7 +78,7 @@ "authorized baseline remains explicit", "full historical reproduction remains false" ], - "nextTask": null, + "nextTask": "WBV2-P10-000", "sourceDocuments": { "queue": "docs/EXECUTION_QUEUE.md", "taskCard": "docs/tasks/WBV2-P9-004.md", @@ -145,9 +145,9 @@ "documents": [ { "path": "docs/EXECUTION_QUEUE.md", - "bytes": 2799, + "bytes": 2803, "lines": 51, - "tokens": 700 + "tokens": 701 }, { "path": "docs/tasks/WBV2-P9-004.md", @@ -168,14 +168,14 @@ "tokens": 140 } ], - "sourceTokens": 1927, + "sourceTokens": 1928, "evidenceFiles": 1, "evidenceBytes": 704, "evidenceTokens": 176, - "totalTokens": 2103, + "totalTokens": 2104, "reservedEnvelopeTokens": 1024, - "estimatedContextTokens": 3127, - "serializedContextTokens": 681, + "estimatedContextTokens": 3128, + "serializedContextTokens": 684, "withinBudget": true } } diff --git a/tests/golden/WBV2/task-catalog.jsonl b/tests/golden/WBV2/task-catalog.jsonl index 906d59eea..b28af5b70 100644 --- a/tests/golden/WBV2/task-catalog.jsonl +++ b/tests/golden/WBV2/task-catalog.jsonl @@ -38,4 +38,8 @@ {"id":"WBV2-P9-001","gapId":"CAP-MESH-POSITIVE-EDIT","ownerFamily":"MESH","sourceTask":"P9","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["real meshTranslateVertex command passes","desktop/WASM delta matches","save/reopen is exact","malformed/stale/unknown inputs fail closed"]} {"id":"WBV2-P9-002","gapId":"CAP-MODIFIER-STATE-MUTATION","ownerFamily":"MODIFIER","sourceTask":"P9","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["real modifierSetEnabled command passes","desktop/WASM delta matches","save/reopen is exact"]} {"id":"WBV2-P9-003","gapId":"CAP-ASSET-CATALOG-MUTATION","ownerFamily":"ASSET","sourceTask":"P9","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["real assetCatalogAppend command passes","resource hash is bound","save/reopen is exact"]} -{"id":"WBV2-P9-004","gapId":"workflow:recompute_feature_parity_gate","ownerFamily":"RELEASE","sourceTask":"P9","state":"active","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["only evidenced feature claims are emitted","authorized baseline remains explicit","full historical reproduction remains false"]} +{"id":"WBV2-P9-004","gapId":"workflow:recompute_feature_parity_gate","ownerFamily":"RELEASE","sourceTask":"P9","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["only evidenced feature claims are emitted","authorized baseline remains explicit","full historical reproduction remains false"]} +{"id":"WBV2-P10-000","gapId":"workflow:authorize_native_engine_parity_continuation","ownerFamily":"PROGRAM","sourceTask":"P10","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["P9 evidence remains hash-bound","native build/runtime is explicit","one native parity task is active"]} +{"id":"WBV2-P10-001","gapId":"workflow:reconcile_wbv2_inventory_source_drift","ownerFamily":"PARITY","sourceTask":"P10","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["historical P0 hashes remain unchanged","only authorized plan drift is recorded","dependency roots/lockfile/closure remain stable","inventory checker passes using current baseline"]} +{"id":"WBV2-P10-002","gapId":"ENGINE.NATIVE_WASM_BRIDGE","ownerFamily":"ENGINE","sourceTask":"P10","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["native Blender binary is source-bound","WASM binary and JS are hash-bound","same mutation reaches real engine/Main","save/reopen and failures remain exact"]} +{"id":"WBV2-P10-003","gapId":"CORE.MODULE_MATRIX","ownerFamily":"PARITY","sourceTask":"P10","state":"active","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["positive cases are L2+","negative cases do not mutate Main","shards use one catalog hash","unmapped and retained-negative cases stay explicit"]} diff --git a/tests/golden/WBV2/task-index.json b/tests/golden/WBV2/task-index.json index 6a5149044..8330c6421 100644 --- a/tests/golden/WBV2/task-index.json +++ b/tests/golden/WBV2/task-index.json @@ -1 +1 @@ -{"schemaVersion":1,"operation":"BLENDER_WEB_CAPABILITY_TASK_INDEX","source":{"path":"tests/golden/WBV2-P9-004/feature-parity-task-plan.json","sha256":"d754f21d4923eec7cdb497caa7ed77300db81f2ccff965c2690f7734aafb135d"},"catalog":{"path":"tests/golden/WBV2/task-catalog.jsonl","sha256":"6b9506476dd36550fb13f745dadd5f3fb63c3629934c9f8f853edc2b035b38a2"},"taskCount":41,"activeTask":"WBV2-P9-004","entries":{"WBV2-P0-001":{"line":0,"offset":0,"length":308,"previous":null,"next":"WBV2-P0-002"},"WBV2-P0-002":{"line":1,"offset":308,"length":318,"previous":"WBV2-P0-001","next":"WBV2-P0-003"},"WBV2-P0-003":{"line":2,"offset":626,"length":306,"previous":"WBV2-P0-002","next":"WBV2-P1-001"},"WBV2-P1-001":{"line":3,"offset":932,"length":318,"previous":"WBV2-P0-003","next":"WBV2-P1-002"},"WBV2-P1-002":{"line":4,"offset":1250,"length":299,"previous":"WBV2-P1-001","next":"WBV2-P1-003"},"WBV2-P1-003":{"line":5,"offset":1549,"length":303,"previous":"WBV2-P1-002","next":"WBV2-P1-004"},"WBV2-P1-004":{"line":6,"offset":1852,"length":309,"previous":"WBV2-P1-003","next":"WBV2-P1-005"},"WBV2-P1-005":{"line":7,"offset":2161,"length":324,"previous":"WBV2-P1-004","next":"WBV2-P2-001"},"WBV2-P2-001":{"line":8,"offset":2485,"length":267,"previous":"WBV2-P1-005","next":"WBV2-P2-002"},"WBV2-P2-002":{"line":9,"offset":2752,"length":267,"previous":"WBV2-P2-001","next":"WBV2-P2-003"},"WBV2-P2-003":{"line":10,"offset":3019,"length":274,"previous":"WBV2-P2-002","next":"WBV2-P2-004"},"WBV2-P2-004":{"line":11,"offset":3293,"length":284,"previous":"WBV2-P2-003","next":"WBV2-P2-005"},"WBV2-P2-005":{"line":12,"offset":3577,"length":291,"previous":"WBV2-P2-004","next":"WBV2-P3-001"},"WBV2-P3-001":{"line":13,"offset":3868,"length":271,"previous":"WBV2-P2-005","next":"WBV2-P3-002"},"WBV2-P3-002":{"line":14,"offset":4139,"length":266,"previous":"WBV2-P3-001","next":"WBV2-P3-003"},"WBV2-P3-003":{"line":15,"offset":4405,"length":273,"previous":"WBV2-P3-002","next":"WBV2-P3-004"},"WBV2-P3-004":{"line":16,"offset":4678,"length":263,"previous":"WBV2-P3-003","next":"WBV2-P3-005"},"WBV2-P3-005":{"line":17,"offset":4941,"length":292,"previous":"WBV2-P3-004","next":"WBV2-P4-001"},"WBV2-P4-001":{"line":18,"offset":5233,"length":283,"previous":"WBV2-P3-005","next":"WBV2-P4-002"},"WBV2-P4-002":{"line":19,"offset":5516,"length":277,"previous":"WBV2-P4-001","next":"WBV2-P4-003"},"WBV2-P4-003":{"line":20,"offset":5793,"length":287,"previous":"WBV2-P4-002","next":"WBV2-P4-004"},"WBV2-P4-004":{"line":21,"offset":6080,"length":290,"previous":"WBV2-P4-003","next":"WBV2-P5-001"},"WBV2-P5-001":{"line":22,"offset":6370,"length":296,"previous":"WBV2-P4-004","next":"WBV2-P5-002"},"WBV2-P5-002":{"line":23,"offset":6666,"length":282,"previous":"WBV2-P5-001","next":"WBV2-P5-003"},"WBV2-P5-003":{"line":24,"offset":6948,"length":278,"previous":"WBV2-P5-002","next":"WBV2-P6-001"},"WBV2-P6-001":{"line":25,"offset":7226,"length":278,"previous":"WBV2-P5-003","next":"WBV2-P6-002"},"WBV2-P6-002":{"line":26,"offset":7504,"length":313,"previous":"WBV2-P6-001","next":"WBV2-P6-003"},"WBV2-P6-003":{"line":27,"offset":7817,"length":316,"previous":"WBV2-P6-002","next":"WBV2-P7-001"},"WBV2-P7-001":{"line":28,"offset":8133,"length":312,"previous":"WBV2-P6-003","next":"WBV2-P7-002"},"WBV2-P7-002":{"line":29,"offset":8445,"length":275,"previous":"WBV2-P7-001","next":"WBV2-P7-003"},"WBV2-P7-003":{"line":30,"offset":8720,"length":310,"previous":"WBV2-P7-002","next":"WBV2-P8-000"},"WBV2-P8-000":{"line":31,"offset":9030,"length":290,"previous":"WBV2-P7-003","next":"WBV2-P8-001"},"WBV2-P8-001":{"line":32,"offset":9320,"length":306,"previous":"WBV2-P8-000","next":"WBV2-P8-002"},"WBV2-P8-002":{"line":33,"offset":9626,"length":307,"previous":"WBV2-P8-001","next":"WBV2-P8-003"},"WBV2-P8-003":{"line":34,"offset":9933,"length":312,"previous":"WBV2-P8-002","next":"WBV2-P8-004"},"WBV2-P8-004":{"line":35,"offset":10245,"length":285,"previous":"WBV2-P8-003","next":"WBV2-P9-000"},"WBV2-P9-000":{"line":36,"offset":10530,"length":303,"previous":"WBV2-P8-004","next":"WBV2-P9-001"},"WBV2-P9-001":{"line":37,"offset":10833,"length":311,"previous":"WBV2-P9-000","next":"WBV2-P9-002"},"WBV2-P9-002":{"line":38,"offset":11144,"length":274,"previous":"WBV2-P9-001","next":"WBV2-P9-003"},"WBV2-P9-003":{"line":39,"offset":11418,"length":266,"previous":"WBV2-P9-002","next":"WBV2-P9-004"},"WBV2-P9-004":{"line":40,"offset":11684,"length":318,"previous":"WBV2-P9-003","next":null}}} +{"schemaVersion":1,"operation":"BLENDER_WEB_CAPABILITY_TASK_INDEX","source":{"path":"tests/golden/WBV2-P10-003/native-parity-task-plan.json","sha256":"acfe344c377cbef5b0eefaba22fab88de7d374e9a157ad53930ac6599cd6b1a9"},"catalog":{"path":"tests/golden/WBV2/task-catalog.jsonl","sha256":"604c45bfe19d24c6f4e21ae1bbec00e15489c713452428223cda26ee2a5f4318"},"taskCount":45,"activeTask":"WBV2-P10-003","entries":{"WBV2-P0-001":{"line":0,"offset":0,"length":308,"previous":null,"next":"WBV2-P0-002"},"WBV2-P0-002":{"line":1,"offset":308,"length":318,"previous":"WBV2-P0-001","next":"WBV2-P0-003"},"WBV2-P0-003":{"line":2,"offset":626,"length":306,"previous":"WBV2-P0-002","next":"WBV2-P1-001"},"WBV2-P1-001":{"line":3,"offset":932,"length":318,"previous":"WBV2-P0-003","next":"WBV2-P1-002"},"WBV2-P1-002":{"line":4,"offset":1250,"length":299,"previous":"WBV2-P1-001","next":"WBV2-P1-003"},"WBV2-P1-003":{"line":5,"offset":1549,"length":303,"previous":"WBV2-P1-002","next":"WBV2-P1-004"},"WBV2-P1-004":{"line":6,"offset":1852,"length":309,"previous":"WBV2-P1-003","next":"WBV2-P1-005"},"WBV2-P1-005":{"line":7,"offset":2161,"length":324,"previous":"WBV2-P1-004","next":"WBV2-P2-001"},"WBV2-P2-001":{"line":8,"offset":2485,"length":267,"previous":"WBV2-P1-005","next":"WBV2-P2-002"},"WBV2-P2-002":{"line":9,"offset":2752,"length":267,"previous":"WBV2-P2-001","next":"WBV2-P2-003"},"WBV2-P2-003":{"line":10,"offset":3019,"length":274,"previous":"WBV2-P2-002","next":"WBV2-P2-004"},"WBV2-P2-004":{"line":11,"offset":3293,"length":284,"previous":"WBV2-P2-003","next":"WBV2-P2-005"},"WBV2-P2-005":{"line":12,"offset":3577,"length":291,"previous":"WBV2-P2-004","next":"WBV2-P3-001"},"WBV2-P3-001":{"line":13,"offset":3868,"length":271,"previous":"WBV2-P2-005","next":"WBV2-P3-002"},"WBV2-P3-002":{"line":14,"offset":4139,"length":266,"previous":"WBV2-P3-001","next":"WBV2-P3-003"},"WBV2-P3-003":{"line":15,"offset":4405,"length":273,"previous":"WBV2-P3-002","next":"WBV2-P3-004"},"WBV2-P3-004":{"line":16,"offset":4678,"length":263,"previous":"WBV2-P3-003","next":"WBV2-P3-005"},"WBV2-P3-005":{"line":17,"offset":4941,"length":292,"previous":"WBV2-P3-004","next":"WBV2-P4-001"},"WBV2-P4-001":{"line":18,"offset":5233,"length":283,"previous":"WBV2-P3-005","next":"WBV2-P4-002"},"WBV2-P4-002":{"line":19,"offset":5516,"length":277,"previous":"WBV2-P4-001","next":"WBV2-P4-003"},"WBV2-P4-003":{"line":20,"offset":5793,"length":287,"previous":"WBV2-P4-002","next":"WBV2-P4-004"},"WBV2-P4-004":{"line":21,"offset":6080,"length":290,"previous":"WBV2-P4-003","next":"WBV2-P5-001"},"WBV2-P5-001":{"line":22,"offset":6370,"length":296,"previous":"WBV2-P4-004","next":"WBV2-P5-002"},"WBV2-P5-002":{"line":23,"offset":6666,"length":282,"previous":"WBV2-P5-001","next":"WBV2-P5-003"},"WBV2-P5-003":{"line":24,"offset":6948,"length":278,"previous":"WBV2-P5-002","next":"WBV2-P6-001"},"WBV2-P6-001":{"line":25,"offset":7226,"length":278,"previous":"WBV2-P5-003","next":"WBV2-P6-002"},"WBV2-P6-002":{"line":26,"offset":7504,"length":313,"previous":"WBV2-P6-001","next":"WBV2-P6-003"},"WBV2-P6-003":{"line":27,"offset":7817,"length":316,"previous":"WBV2-P6-002","next":"WBV2-P7-001"},"WBV2-P7-001":{"line":28,"offset":8133,"length":312,"previous":"WBV2-P6-003","next":"WBV2-P7-002"},"WBV2-P7-002":{"line":29,"offset":8445,"length":275,"previous":"WBV2-P7-001","next":"WBV2-P7-003"},"WBV2-P7-003":{"line":30,"offset":8720,"length":310,"previous":"WBV2-P7-002","next":"WBV2-P8-000"},"WBV2-P8-000":{"line":31,"offset":9030,"length":290,"previous":"WBV2-P7-003","next":"WBV2-P8-001"},"WBV2-P8-001":{"line":32,"offset":9320,"length":306,"previous":"WBV2-P8-000","next":"WBV2-P8-002"},"WBV2-P8-002":{"line":33,"offset":9626,"length":307,"previous":"WBV2-P8-001","next":"WBV2-P8-003"},"WBV2-P8-003":{"line":34,"offset":9933,"length":312,"previous":"WBV2-P8-002","next":"WBV2-P8-004"},"WBV2-P8-004":{"line":35,"offset":10245,"length":285,"previous":"WBV2-P8-003","next":"WBV2-P9-000"},"WBV2-P9-000":{"line":36,"offset":10530,"length":303,"previous":"WBV2-P8-004","next":"WBV2-P9-001"},"WBV2-P9-001":{"line":37,"offset":10833,"length":311,"previous":"WBV2-P9-000","next":"WBV2-P9-002"},"WBV2-P9-002":{"line":38,"offset":11144,"length":274,"previous":"WBV2-P9-001","next":"WBV2-P9-003"},"WBV2-P9-003":{"line":39,"offset":11418,"length":266,"previous":"WBV2-P9-002","next":"WBV2-P9-004"},"WBV2-P9-004":{"line":40,"offset":11684,"length":321,"previous":"WBV2-P9-003","next":"WBV2-P10-000"},"WBV2-P10-000":{"line":41,"offset":12005,"length":312,"previous":"WBV2-P9-004","next":"WBV2-P10-001"},"WBV2-P10-001":{"line":42,"offset":12317,"length":383,"previous":"WBV2-P10-000","next":"WBV2-P10-002"},"WBV2-P10-002":{"line":43,"offset":12700,"length":336,"previous":"WBV2-P10-001","next":"WBV2-P10-003"},"WBV2-P10-003":{"line":44,"offset":13036,"length":315,"previous":"WBV2-P10-002","next":null}}} diff --git a/tools/web/check-v2-handoff.mjs b/tools/web/check-v2-handoff.mjs index f04ccd67f..252af52cf 100644 --- a/tools/web/check-v2-handoff.mjs +++ b/tools/web/check-v2-handoff.mjs @@ -10,7 +10,7 @@ const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(path const queue = read("docs/EXECUTION_QUEUE.md"); const requested = process.argv.indexOf("--task"); const current = requested >= 0 ? process.argv[requested + 1] : queue.match(/\|\s*当前任务\s*\|\s*`([^`]+)`/u)?.[1]; -assert.match(current ?? "", /^WBV2-P\d-\d{3}$/u); +assert.match(current ?? "", /^WBV2-P\d+-\d{3}$/u); const currentCard = `docs/tasks/${current}.md`; assert.ok(fs.existsSync(path.join(root, currentCard)), `${currentCard} must exist`); const parentPath = requested >= 0 diff --git a/tools/web/check-wbv2-inventory-rebaseline.mjs b/tools/web/check-wbv2-inventory-rebaseline.mjs new file mode 100644 index 000000000..f6ef3ad78 --- /dev/null +++ b/tools/web/check-wbv2-inventory-rebaseline.mjs @@ -0,0 +1,50 @@ +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 absolute = (file) => path.join(root, file); +const read = (file) => fs.readFileSync(absolute(file), "utf8"); +const json = (file) => JSON.parse(read(file)); +const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex"); + +const historicalPath = "tests/golden/WBV2-P0-002/source-hashes.json"; +const currentPath = "tests/golden/WBV2-P10-001/current-source-hashes.json"; +const reportPath = "tests/golden/WBV2-P10-001/inventory-rebaseline-report.json"; +const dependencyPath = "tests/golden/WBV2-P10-001/dependency-inventory.current.json"; +const historicalDependencyPath = "tests/golden/M13-05C/dependency-inventory.json"; +const historical = json(historicalPath); +const current = json(currentPath); +const report = json(reportPath); +const dependency = json(dependencyPath); +const historicalDependency = json(historicalDependencyPath); + +assert.equal(current.schemaVersion, 1); +assert.equal(current.task, "WBV2-P10-001"); +assert.equal(current.operation, "CURRENT_WBV2_SOURCE_HASH_BASELINE"); +assert.equal(current.historicalSourceHashesSha256, sha256(historicalPath)); +const drift = []; +for (const [file, expected] of Object.entries(historical.sources)) { + const actual = sha256(file); + assert.equal(current.sources[file], actual, `current source hash drift: ${file}`); + if (actual !== expected) drift.push({ file, expected, actual }); +} +assert.deepEqual(drift, current.drift.map(({ file, expected, actual }) => ({ file, expected, actual }))); +assert.deepEqual(drift.map((entry) => entry.file), ["docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json"]); +assert.equal(drift[0].actual, "0f4750e45f2d1ca7d68faa35743e5b758ea8091f18d1d0e312ab548228d6f782"); +assert.equal(report.status, "PASS"); +assert.equal(report.task, "WBV2-P10-001"); +assert.equal(report.currentSourceBaseline.sha256, sha256(currentPath)); +assert.equal(report.currentSourceBaseline.planSha256, drift[0].actual); +assert.equal(report.historical.sourceHashesSha256, sha256(historicalPath)); +assert.equal(report.dependency.lockfileHashStable, true); +assert.equal(report.dependency.rootsStable, true); +assert.equal(report.dependency.closureStable, true); +assert.deepEqual(dependency.roots, historicalDependency.roots); +assert.deepEqual(dependency.categoryCounts, historicalDependency.categoryCounts); +assert.deepEqual(dependency.packages, historicalDependency.packages); +assert.equal(dependency.lockfile.sha256, historicalDependency.lockfile.sha256); +assert.equal(dependency.packages.length, 144); +process.stdout.write(`wbv2-inventory-rebaseline-ok task=WBV2-P10-001 planDrift=${drift.length} dependencyPackages=${dependency.packages.length} closureStable=1 historicalHashesPreserved=1\n`); diff --git a/tools/web/check-wbv2-native-engine.mjs b/tools/web/check-wbv2-native-engine.mjs new file mode 100644 index 000000000..41656aba1 --- /dev/null +++ b/tools/web/check-wbv2-native-engine.mjs @@ -0,0 +1,73 @@ +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 outputPath = "tests/golden/WBV2-P10-002/native-engine-binding-report.json"; +const parentPath = "tests/golden/WBV2-P10-001/manifest.json"; +const nativeBinary = "build_blender_native/bin/blender"; +const wasmBinary = "web/app/src/vendor/blender/web_engine.wasm"; +const wasmJavaScript = "web/app/src/vendor/blender/web_engine.js"; + +const parent = readJson(parentPath); +assert.equal(parent.task, "WBV2-P10-001"); +assert.equal(parent.status, "done"); +assert.equal(parent.nextTask, "WBV2-P10-002"); +for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); +for (const source of ["tests/golden/WBV2-P2-003/manifest.json", "tests/golden/WBV2-P4-001/manifest.json", "tests/golden/WBV2-P3-005/manifest.json"]) { + const manifest = readJson(source); + assert.equal(manifest.status, "done", `${source} is not complete`); +} +assert.ok(fs.existsSync(absolute(nativeBinary)), "native Blender binary is missing"); +assert.ok(fs.statSync(absolute(nativeBinary)).size > 0, "native Blender binary is empty"); +assert.ok(fs.existsSync(absolute(wasmBinary)), "web_engine.wasm is missing"); +assert.ok(fs.existsSync(absolute(wasmJavaScript)), "web_engine.js is missing"); +const version = execFileSync(absolute(nativeBinary), ["--version"], { cwd: root, encoding: "utf8" }).split("\n")[0].trim(); +assert.equal(version, "Blender 5.2.0 LTS"); +const binding = { + schemaVersion: 1, + task: "WBV2-P10-002", + operation: "NATIVE_WASM_ENGINE_BINDING", + status: "PASS", + runtime: { + native: { path: nativeBinary, sha256: sha256(nativeBinary), version }, + wasm: { path: wasmBinary, sha256: sha256(wasmBinary), bytes: fs.statSync(absolute(wasmBinary)).size }, + javascript: { path: wasmJavaScript, sha256: sha256(wasmJavaScript), bytes: fs.statSync(absolute(wasmJavaScript)).size }, + browser: "chromium", + }, + abi: { + exports: ["web_engine_create", "web_engine_open_blend", "web_engine_apply_command", "web_engine_save_blend", "web_engine_destroy"], + nativeApi: "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + mainState: "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + worker: "web/app/src/workers/web-engine.worker.ts", + }, + sourceBindings: [ + { task: "WBV2-P2-003", manifest: "tests/golden/WBV2-P2-003/manifest.json", report: "tests/golden/WBV2-P2-003/mesh-edit-report.json" }, + { task: "WBV2-P4-001", manifest: "tests/golden/WBV2-P4-001/manifest.json", report: "tests/golden/WBV2-P4-001/modifier-report.json" }, + { task: "WBV2-P3-005", manifest: "tests/golden/WBV2-P3-005/manifest.json", report: "tests/golden/WBV2-P3-005/library-report.json" }, + ], + requirements: { compiledNativePresent: true, wasmBinaryPresent: true, wasmLoaderPresent: true, sourceBound: true, fakeBridgeOnly: false }, + nextTask: "WBV2-P10-002", +}; +for (const source of binding.sourceBindings) { + const manifest = readJson(source.manifest); + const report = readJson(source.report); + assert.equal(report.desktop?.status, "EXACT", `${source.task} desktop evidence is not exact`); + assert.equal(report.wasm?.status, "EXACT", `${source.task} WASM evidence is not exact`); + const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === source.report); + assert.ok(bound, `${source.task} report is not manifest-bound`); + assert.equal(bound.sha256, sha256(source.report), `${source.task} report hash drift`); +} +if (write) { + fs.mkdirSync(path.dirname(absolute(outputPath)), { recursive: true }); + fs.writeFileSync(absolute(outputPath), `${JSON.stringify(binding, null, 2)}\n`); +} +process.stdout.write(`wbv2-native-engine-binding-ok task=WBV2-P10-002 native=${version} wasmBytes=${binding.runtime.wasm.bytes} browser=chromium${write ? ` output=${outputPath}` : ""}\n`); diff --git a/tools/web/generate-wbv2-inventory-rebaseline.mjs b/tools/web/generate-wbv2-inventory-rebaseline.mjs new file mode 100644 index 000000000..14848966a --- /dev/null +++ b/tools/web/generate-wbv2-inventory-rebaseline.mjs @@ -0,0 +1,92 @@ +import assert from "node:assert/strict"; +import crypto from "node:crypto"; +import fs from "node:fs"; +import os from "node:os"; +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-P10-001"; +const historicalPath = "tests/golden/WBV2-P0-002/source-hashes.json"; +const currentPath = `${outputRoot}/current-source-hashes.json`; +const dependencyPath = `${outputRoot}/dependency-inventory.current.json`; +const reportPath = `${outputRoot}/inventory-rebaseline-report.json`; +const statusPath = "docs/status/WBV2-P10-001.md"; +const planPath = `${outputRoot}/native-parity-task-plan.json`; +const manifestPath = `${outputRoot}/manifest.json`; +const parentManifestPath = "tests/golden/WBV2-P10-000/manifest.json"; +const historicalDependencyPath = "tests/golden/M13-05C/dependency-inventory.json"; +const previousReportPath = "tests/golden/WBV2-P8-001/recovery-baseline-report.json"; + +const parent = readJson(parentManifestPath); +assert.equal(parent.task, "WBV2-P10-000"); +assert.equal(parent.status, "done"); +assert.equal(parent.nextTask, "WBV2-P10-001"); +for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); +const historical = readJson(historicalPath); +const previous = readJson(previousReportPath); +const drift = Object.entries(historical.sources).map(([file, expected]) => ({ file, expected, actual: sha256(file) })).filter((entry) => entry.expected !== entry.actual); +assert.deepEqual(drift.map((entry) => entry.file), ["docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json"]); +assert.equal(previous.wbv2.drift.length, 1); +assert.equal(previous.wbv2.drift[0].file, drift[0].file); +assert.equal(previous.wbv2.drift[0].actual, drift[0].actual); + +const historicalDependency = readJson(historicalDependencyPath); +const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "wbv2-p10-dependency-")); +const generatedPath = path.join(temporary, "dependency-inventory.json"); +try { + execFileSync(process.execPath, [absolute("tools/web/generate-dependency-inventory.mjs"), generatedPath], { cwd: root, stdio: "pipe" }); +} finally { + // The generated bytes are read before cleanup; the temporary directory is + // deliberately outside the repository and never becomes evidence. +} +const dependency = JSON.parse(fs.readFileSync(generatedPath, "utf8")); +assert.deepEqual(dependency.roots, historicalDependency.roots); +assert.deepEqual(dependency.categoryCounts, historicalDependency.categoryCounts); +assert.deepEqual(dependency.packages, historicalDependency.packages); +assert.equal(dependency.lockfile.sha256, historicalDependency.lockfile.sha256); +assert.equal(dependency.packages.length, 144); + +const current = { schemaVersion: 1, task: "WBV2-P10-001", operation: "CURRENT_WBV2_SOURCE_HASH_BASELINE", historicalSourceHashes: historicalPath, historicalSourceHashesSha256: sha256(historicalPath), sources: Object.fromEntries(Object.keys(historical.sources).map((file) => [file, sha256(file)])), drift: drift.map(({ file, expected, actual }) => ({ file, expected, actual, classification: "AUTHORIZED_MUTABLE_PLAN" })) }; +const report = { schemaVersion: 1, task: "WBV2-P10-001", operation: "RECONCILE_WBV2_INVENTORY_SOURCE_DRIFT", status: "PASS", historical: { sourceHashes: historicalPath, sourceHashesSha256: sha256(historicalPath), manifestsRewritten: false, baselinePreserved: true }, currentSourceBaseline: { path: currentPath, sha256: "PENDING", planPath: "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", planSha256: sha256("docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json") }, drift: { count: drift.length, entries: current.drift, onlyAuthorizedMutablePlan: true }, dependency: { historicalInventory: historicalDependencyPath, currentInventory: dependencyPath, packageCount: dependency.packages.length, packageHashChanged: dependency.package.sha256 !== historicalDependency.package.sha256, lockfileHashStable: dependency.lockfile.sha256 === historicalDependency.lockfile.sha256, rootsStable: JSON.stringify(dependency.roots) === JSON.stringify(historicalDependency.roots), closureStable: JSON.stringify(dependency.packages) === JSON.stringify(historicalDependency.packages), packagesAdded: 0 }, policy: { historicalP0Unchanged: true, historicalP8Unchanged: true, additiveCurrentBaseline: true, falseHistoricalRestoration: false }, nextTask: "WBV2-P10-002" }; + +if (!write) { + process.stdout.write(`wbv2-inventory-rebaseline-dry-ok task=WBV2-P10-001 planDrift=${drift.length} dependencyPackages=${dependency.packages.length} closureStable=1\n`); + process.exit(0); +} +fs.mkdirSync(absolute(outputRoot), { recursive: true }); +fs.writeFileSync(absolute(currentPath), `${JSON.stringify(current, null, 2)}\n`); +fs.copyFileSync(generatedPath, absolute(dependencyPath)); +fs.rmSync(temporary, { recursive: true, force: true }); +report.currentSourceBaseline.sha256 = sha256(currentPath); +fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`); +fs.writeFileSync(absolute(statusPath), `# WBV2-P10-001 status\n\n- task: \`WBV2-P10-001\`; parent: \`WBV2-P10-000\`; status: \`done\`\n- plan drift: \`1\` authorized mutable plan hash\n- dependency packages: \`144\`; lockfile/roots/closure: \`STABLE\`\n- historical P0 hashes: preserved\n- nextTask: \`WBV2-P10-002\`\n\nThe current WBV2 plan hash is recorded as an additive epoch-1 baseline. The historical P0-002 source-hashes.json and all historical manifests remain unchanged. Dependency roots, lockfile, package closure, and package count remain stable.\n`); + +const previousPlan = readJson("tests/golden/WBV2-P10-000/native-parity-task-plan.json"); +const nextPlan = structuredClone(previousPlan); +nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P10-000/native-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P10-000/native-parity-task-plan.json") }; +nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P10-001" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P10-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-P10-002.md"; +const nextCard = read(nextCardPath).replace("- status: planned", "- status: in_progress"); +fs.writeFileSync(absolute(nextCardPath), 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-P10-001", "--write"], { cwd: root, stdio: "inherit" }); +execFileSync(process.execPath, [absolute("tools/web/check-wbv2-inventory-rebaseline.mjs")], { cwd: root, stdio: "inherit" }); + +const artifactPaths = { parentManifest: parentManifestPath, historicalSourceHashes: historicalPath, historicalDependencyManifest: "tests/golden/M13-05C/manifest.json", historicalRecoveryReport: previousReportPath, currentSourceHashes: currentPath, currentDependencyInventory: dependencyPath, sourcePlan: "docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json", generator: "tools/web/generate-wbv2-inventory-rebaseline.mjs", checker: "tools/web/check-wbv2-inventory-rebaseline.mjs", report: reportPath, status: statusPath, parityPlan: 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-P10-001", parentTask: "WBV2-P10-000", operation: "RECONCILE_WBV2_INVENTORY_SOURCE_DRIFT", status: "done", enablingTask: true, parityStateChange: false, artifacts, assertions: { historicalP0Preserved: true, historicalP8Preserved: true, authorizedPlanDrift: 1, currentBaseline: true, dependencyPackages: 144, dependencyClosureStable: true, lockfileStable: true, nextEngineTask: "WBV2-P10-002" }, nextTask: "WBV2-P10-002" }; +fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`); +let queue = read("docs/EXECUTION_QUEUE.md"); +queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P10-002` |") + .replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P10-001/manifest.json` |") + .replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P10-002.md`](tasks/WBV2-P10-002.md) |"); +fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue); +process.stdout.write(`wbv2-inventory-rebaseline-written task=WBV2-P10-001 planDrift=1 dependencyPackages=144 closureStable=1 next=WBV2-P10-002 artifacts=${Object.keys(artifacts).length}\n`); diff --git a/tools/web/generate-wbv2-module-matrix-receipt.mjs b/tools/web/generate-wbv2-module-matrix-receipt.mjs new file mode 100644 index 000000000..45c7d279d --- /dev/null +++ b/tools/web/generate-wbv2-module-matrix-receipt.mjs @@ -0,0 +1,95 @@ +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-P10-003"; +const matrixPath = `${outputRoot}/module-matrix.json`; +const productionPath = `${outputRoot}/module-matrix-production.json`; +const productionSecondPath = `${outputRoot}/module-matrix-production.second.json`; +const engineReceiptPath = "tests/golden/WBV2-P10-002/native-engine-receipt-report.json"; +const parentManifestPath = "tests/golden/WBV2-P10-002/manifest.json"; +const reportPath = `${outputRoot}/module-matrix-receipt-report.json`; +const statusPath = "docs/status/WBV2-P10-003.md"; +const planPath = `${outputRoot}/native-parity-task-plan.json`; +const manifestPath = `${outputRoot}/manifest.json`; + +const parent = readJson(parentManifestPath); +assert.equal(parent.task, "WBV2-P10-002"); +assert.equal(parent.status, "done"); +assert.equal(parent.nextTask, "WBV2-P10-003"); +for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); +const engineReceipt = readJson(engineReceiptPath); +assert.equal(engineReceipt.status, "PASS"); +assert.equal(engineReceipt.assertions.realEngineMainMutation, true); +const matrix = readJson(matrixPath); +assert.equal(matrix.task, "WBV2-P10-003"); +assert.equal(matrix.status, "READY"); +assert.equal(matrix.catalog.inventoryEntries, 6900); +assert.equal(matrix.catalog.pendingEntries, 6618); +assert.equal(matrix.policy.unmappedInventoryExplicit, true); +assert.equal(sha256(matrix.catalog.path), matrix.catalog.sha256); +const production = readJson(productionPath); +assert.equal(sha256(productionPath), sha256(productionSecondPath), "module matrix report is not deterministic"); +assert.equal(production.task, "WBV2-P10-003"); +assert.equal(production.operation, "CORE_MODULE_OPERATOR_MATRIX_CHROMIUM"); +assert.equal(production.browser, "chromium"); +assert.equal(production.queueMutation, false); +assert.equal(production.catalogSha256, matrix.catalog.sha256); +assert.equal(production.cases.length, matrix.cases.length); +assert.equal(production.cases.filter((entry) => entry.status === "PASS").length, 3); +assert.equal(production.cases.filter((entry) => entry.status === "RETAINED_NEGATIVE").length, 6); +for (const entry of production.cases) { + assert.ok(matrix.cases.some((candidate) => candidate.id === entry.id), `case is not catalog-bound: ${entry.id}`); + assert.equal(entry.mainMutation, entry.status === "PASS" ? "CHANGED" : "UNCHANGED"); + assert.equal(entry.revisionDelta, entry.status === "PASS" ? 1 : 0); + if (entry.status === "PASS") assert.equal(entry.saveReopen, true); +} +assert.equal(production.shards.length, 2); +assert.ok(production.shards.every((shard) => shard.catalogSha256 === matrix.catalog.sha256 && shard.exitCode === 0)); + +const receipt = { + schemaVersion: 1, + task: "WBV2-P10-003", + operation: "CORE_MODULE_OPERATOR_MATRIX_RECEIPT", + status: "PASS", + browser: "chromium", + queueMutation: false, + source: { engineReceipt: engineReceiptPath, engineReceiptSha256: sha256(engineReceiptPath), catalog: matrix.catalog, featureGate: matrix.source.featureGate, featureGateSha256: matrix.source.featureGateSha256 }, + matrix: { definition: matrixPath, definitionSha256: sha256(matrixPath), production: productionPath, productionSha256: sha256(productionPath), secondProduction: productionSecondPath, secondProductionSha256: sha256(productionSecondPath), deterministic: true, modules: matrix.modules, cases: production.cases.length, positive: 3, retainedNegative: 6, shards: production.shards.map((shard) => ({ id: shard.id, catalogSha256: shard.catalogSha256, exitCode: shard.exitCode })) }, + coverage: { inventoryEntries: matrix.coverage.inventoryEntries, claimedComplete: matrix.coverage.inventoryEntriesClaimedComplete, remainingExplicit: matrix.coverage.inventoryEntriesRemainingExplicit, productionCases: production.cases.length, oneCatalogHash: true }, + assertions: { positiveCasesMainChanged: true, negativeCasesMainUnchanged: true, saveReopenExact: 3, unmappedInventoryExplicit: true, retainedNegativeExplicit: true, historicalReproduction: false }, + nextTask: null, +}; + +if (!write) { + process.stdout.write("wbv2-module-matrix-receipt-ok task=WBV2-P10-003 cases=9 positive=3 negative=6 shards=2 deterministic=true terminal=true\n"); + process.exit(0); +} + +fs.mkdirSync(absolute(outputRoot), { recursive: true }); +fs.writeFileSync(absolute(reportPath), `${JSON.stringify(receipt, null, 2)}\n`); +fs.writeFileSync(absolute(statusPath), `# WBV2-P10-003 status\n\n- task: \`WBV2-P10-003\`; parent: \`WBV2-P10-002\`; status: \`done\`\n- module cases: \`9\`; positive Main mutations: \`3\`; retained negatives: \`6\`\n- shards: \`2\`; one catalog hash; exit codes: \`0/0\`\n- inventory: \`6900\` total, \`6900\` explicitly remaining; no false completion claim\n- nextTask: \`NONE\`\n\nThe data-driven Mesh, Modifier, and Asset Catalog matrix re-runs the real WebEngine WASM Main path with one catalog hash. Positive cases change Main and pass save/reopen; stale, malformed, unknown, and collision cases remain explicit retained negatives. The matrix does not claim all inventory entries are complete or reproduce unavailable historical bytes. P10-003 is the terminal pointer until a separately authorized continuation is created.\n`); + +const previousPlan = readJson("tests/golden/WBV2-P10-002/native-parity-task-plan.json"); +const nextPlan = structuredClone(previousPlan); +nextPlan.status = "COMPLETED_WITH_NATIVE_MODULE_MATRIX"; +nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P10-002/native-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P10-002/native-parity-task-plan.json") }; +nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P10-003" ? { ...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-P10-003", "--write"], { cwd: root, stdio: "inherit" }); + +const artifactPaths = { parentManifest: parentManifestPath, engineReceipt: engineReceiptPath, matrix: matrixPath, production: productionPath, productionSecond: productionSecondPath, e2e: "web/tests/e2e/wbv2-module-matrix.spec.ts", generator: "tools/web/generate-wbv2-module-matrix.mjs", receiptGenerator: "tools/web/generate-wbv2-module-matrix-receipt.mjs", report: reportPath, status: statusPath, parityPlan: 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-P10-003", parentTask: "WBV2-P10-002", operation: "CORE_MODULE_OPERATOR_MATRIX_RECEIPT", status: "done", enablingTask: true, parityStateChange: true, runtime: "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", artifacts, assertions: { cases: 9, positiveCases: 3, retainedNegative: 6, shards: 2, oneCatalogHash: true, inventoryEntries: 6900, inventoryEntriesRemaining: 6900, deterministic: true, saveReopen: "EXACT", historicalReproduction: false }, nextTask: null }; +fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`); +process.stdout.write(`wbv2-module-matrix-receipt-written task=WBV2-P10-003 cases=9 positive=3 negative=6 shards=2 deterministic=true terminal=true artifacts=${Object.keys(artifacts).length}\n`); diff --git a/tools/web/generate-wbv2-module-matrix.mjs b/tools/web/generate-wbv2-module-matrix.mjs new file mode 100644 index 000000000..acd87eb09 --- /dev/null +++ b/tools/web/generate-wbv2-module-matrix.mjs @@ -0,0 +1,60 @@ +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 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-P10-003"; +const matrixPath = `${outputRoot}/module-matrix.json`; +const parentPath = "tests/golden/WBV2-P10-002/manifest.json"; +const inventoryPath = "tests/golden/WBV2-P0-002/parity-map.json"; +const engineReceiptPath = "tests/golden/WBV2-P10-002/native-engine-receipt-report.json"; +const gatePath = "tests/golden/WBV2-P9-004/feature-parity-gate-report.json"; + +const parent = readJson(parentPath); +assert.equal(parent.task, "WBV2-P10-002"); +assert.equal(parent.status, "done"); +assert.equal(parent.nextTask, "WBV2-P10-003"); +for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); +const inventory = readJson(inventoryPath); +const engineReceipt = readJson(engineReceiptPath); +const gate = readJson(gatePath); +assert.equal(engineReceipt.status, "PASS"); +assert.equal(engineReceipt.assertions.realEngineMainMutation, true); +assert.equal(gate.status, "PASS"); +const cases = [ + { id: "MESH.translateMeshVertices", family: "MESH", capabilityId: "CAP-MESH-POSITIVE-EDIT", behavior: "positive", implementationClass: "LOCAL_EXACT", expected: { mainMutation: "CHANGED", revisionDelta: 1, saveReopen: "EXACT" } }, + { id: "MESH.translateMeshVertices.stale", family: "MESH", capabilityId: "CAP-MESH-POSITIVE-EDIT", behavior: "stale_revision", implementationClass: "NEGATIVE_BOUNDARY", expected: { mainMutation: "UNCHANGED", revisionDelta: 0, code: "REVISION_CONFLICT" } }, + { id: "MESH.translateMeshVertices.malformed", family: "MESH", capabilityId: "CAP-MESH-POSITIVE-EDIT", behavior: "malformed_selection", implementationClass: "NEGATIVE_BOUNDARY", expected: { mainMutation: "UNCHANGED", revisionDelta: 0, code: "REJECTED" } }, + { id: "MODIFIER.setModifierEnabled", family: "MODIFIER", capabilityId: "CAP-MODIFIER-STATE-MUTATION", behavior: "positive", implementationClass: "LOCAL_EXACT", expected: { mainMutation: "CHANGED", revisionDelta: 1, saveReopen: "EXACT" } }, + { id: "MODIFIER.setModifierEnabled.stale", family: "MODIFIER", capabilityId: "CAP-MODIFIER-STATE-MUTATION", behavior: "stale_revision", implementationClass: "NEGATIVE_BOUNDARY", expected: { mainMutation: "UNCHANGED", revisionDelta: 0, code: "REVISION_CONFLICT" } }, + { id: "MODIFIER.setModifierEnabled.unknown", family: "MODIFIER", capabilityId: "CAP-MODIFIER-STATE-MUTATION", behavior: "unknown_modifier", implementationClass: "NEGATIVE_BOUNDARY", expected: { mainMutation: "UNCHANGED", revisionDelta: 0, code: "REJECTED" } }, + { id: "ASSET_CATALOG.appendLibraryObject", family: "ASSET_CATALOG", capabilityId: "CAP-ASSET-CATALOG-MUTATION", behavior: "positive", implementationClass: "LOCAL_EXACT", expected: { mainMutation: "CHANGED", revisionDelta: 1, saveReopen: "EXACT" } }, + { id: "ASSET_CATALOG.appendLibraryObject.stale", family: "ASSET_CATALOG", capabilityId: "CAP-ASSET-CATALOG-MUTATION", behavior: "stale_revision", implementationClass: "NEGATIVE_BOUNDARY", expected: { mainMutation: "UNCHANGED", revisionDelta: 0, code: "REVISION_CONFLICT" } }, + { id: "ASSET_CATALOG.appendLibraryObject.collision", family: "ASSET_CATALOG", capabilityId: "CAP-ASSET-CATALOG-MUTATION", behavior: "collision", implementationClass: "NEGATIVE_BOUNDARY", expected: { mainMutation: "UNCHANGED", revisionDelta: 0, code: "REJECTED" } }, +]; +const matrix = { + schemaVersion: 1, + task: "WBV2-P10-003", + operation: "CORE_MODULE_OPERATOR_MATRIX", + status: "READY", + catalog: { path: inventoryPath, sha256: sha256(inventoryPath), inventoryEntries: inventory.summary.inventoryEntries, pendingEntries: inventory.summary.pendingLegacyEntries }, + source: { featureGate: gatePath, featureGateSha256: sha256(gatePath), engineReceipt: engineReceiptPath, engineReceiptSha256: sha256(engineReceiptPath) }, + policy: { oneCatalogHash: true, positiveClaimsRequireMainMutation: true, negativeCasesNeverAdvanceRevision: true, unmappedInventoryExplicit: true, historicalReproduction: false }, + modules: ["MESH", "MODIFIER", "ASSET_CATALOG"], + cases, + coverage: { matrixCases: cases.length, positiveCases: cases.filter((entry) => entry.behavior === "positive").length, negativeCases: cases.filter((entry) => entry.behavior !== "positive").length, inventoryEntries: inventory.summary.inventoryEntries, inventoryEntriesClaimedComplete: 0, inventoryEntriesRemainingExplicit: inventory.summary.inventoryEntries }, + shards: [{ id: "core-geometry", families: ["MESH", "MODIFIER"], caseIds: cases.filter((entry) => ["MESH", "MODIFIER"].includes(entry.family)).map((entry) => entry.id) }, { id: "asset-resource", families: ["ASSET_CATALOG"], caseIds: cases.filter((entry) => entry.family === "ASSET_CATALOG").map((entry) => entry.id) }], +}; +assert.equal(matrix.cases.length, 9); +if (write) { + fs.mkdirSync(absolute(outputRoot), { recursive: true }); + fs.writeFileSync(absolute(matrixPath), `${JSON.stringify(matrix, null, 2)}\n`); +} +process.stdout.write(`wbv2-module-matrix-${write ? "written" : "ready"} task=WBV2-P10-003 cases=${cases.length} positive=3 negative=6 inventory=${inventory.summary.inventoryEntries} catalogSha256=${sha256(inventoryPath)}\n`); diff --git a/tools/web/generate-wbv2-native-engine-receipt.mjs b/tools/web/generate-wbv2-native-engine-receipt.mjs new file mode 100644 index 000000000..ec5ce2091 --- /dev/null +++ b/tools/web/generate-wbv2-native-engine-receipt.mjs @@ -0,0 +1,132 @@ +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-P10-002"; +const bindingPath = `${outputRoot}/native-engine-binding-report.json`; +const productionPath = `${outputRoot}/native-engine-production.json`; +const productionSecondPath = `${outputRoot}/native-engine-production.second.json`; +const reportPath = `${outputRoot}/native-engine-receipt-report.json`; +const statusPath = "docs/status/WBV2-P10-002.md"; +const planPath = `${outputRoot}/native-parity-task-plan.json`; +const manifestPath = `${outputRoot}/manifest.json`; +const parentManifestPath = "tests/golden/WBV2-P10-001/manifest.json"; + +const parent = readJson(parentManifestPath); +assert.equal(parent.task, "WBV2-P10-001"); +assert.equal(parent.status, "done"); +assert.equal(parent.nextTask, "WBV2-P10-002"); +for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); + +const binding = readJson(bindingPath); +assert.equal(binding.task, "WBV2-P10-002"); +assert.equal(binding.status, "PASS"); +assert.equal(binding.runtime.browser, "chromium"); +assert.equal(binding.requirements.compiledNativePresent, true); +assert.equal(binding.requirements.wasmBinaryPresent, true); +assert.equal(binding.requirements.wasmLoaderPresent, true); +assert.equal(binding.requirements.fakeBridgeOnly, false); +for (const file of [binding.runtime.native.path, binding.runtime.wasm.path, binding.runtime.javascript.path, binding.abi.nativeApi, binding.abi.mainState, binding.abi.worker]) assert.ok(fs.existsSync(absolute(file)), file); +assert.equal(sha256(binding.runtime.native.path), binding.runtime.native.sha256); +assert.equal(sha256(binding.runtime.wasm.path), binding.runtime.wasm.sha256); +assert.equal(sha256(binding.runtime.javascript.path), binding.runtime.javascript.sha256); + +assert.equal(sha256(productionPath), sha256(productionSecondPath), "native engine Chromium report is not deterministic"); +const production = readJson(productionPath); +assert.equal(production.task, "WBV2-P10-002"); +assert.equal(production.operation, "NATIVE_WASM_ENGINE_PRODUCTION_CHROMIUM"); +assert.equal(production.browser, "chromium"); +assert.equal(production.queueMutation, false); +assert.equal(production.mesh.editedRevision, production.mesh.baseRevision + 1); +assert.equal(production.mesh.afterPosition.length, 3); +assert.deepEqual(production.mesh.afterPosition.map((value, index) => Number((value - production.mesh.beforePosition[index]).toFixed(6))), [0.25, -0.5, 1]); +assert.deepEqual(production.mesh.reopenedPosition, production.mesh.afterPosition); +assert.match(production.mesh.savedSha256, /^[a-f0-9]{64}$/u); +assert.notEqual(production.mesh.savedSha256, production.mesh.sourceSha256); +assert.equal(production.mesh.stale.code, "INVALID_ARGUMENT"); +assert.match(production.mesh.stale.message, /REVISION_CONFLICT/u); +assert.equal(production.mesh.malformed.code, "INVALID_ARGUMENT"); +assert.equal(production.modifier.editedRevision, production.modifier.baseRevision + 1); +assert.equal(production.modifier.afterEnabled, !production.modifier.beforeEnabled); +assert.equal(production.modifier.reopenedEnabled, production.modifier.afterEnabled); +assert.match(production.modifier.savedSha256, /^[a-f0-9]{64}$/u); +assert.notEqual(production.modifier.savedSha256, production.modifier.sourceSha256); +assert.match(production.modifier.stale.message, /REVISION_CONFLICT/u); +assert.equal(production.modifier.malformed.code, "INVALID_ARGUMENT"); +assert.equal(production.asset.appendedRevision, production.asset.baseRevision + 1); +assert.equal(production.asset.receipt.operation, "APPEND"); +assert.equal(production.asset.receipt.transactionCount, 1); +assert.equal(production.asset.appendedClosure.object, true); +assert.equal(production.asset.appendedClosure.mesh, true); +assert.equal(production.asset.appendedClosure.material, true); +assert.equal(production.asset.appendedClosure.image.libraryLinked, false); +assert.equal(production.asset.appendedClosure.image.packed, true); +assert.deepEqual(production.asset.reopenedClosure, production.asset.appendedClosure); +assert.match(production.asset.stale.message, /REVISION_CONFLICT/u); +assert.equal(production.asset.collision.code, "ASSET_MANIFEST_INVALID"); +assert.equal(production.asset.collisionRevision, production.asset.appendedRevision); + +const sourceBindings = binding.sourceBindings.map((source) => { + const manifest = readJson(source.manifest); + const report = readJson(source.report); + assert.equal(manifest.status, "done", `${source.task} source manifest is not done`); + assert.equal(report.desktop?.status, "EXACT", `${source.task} desktop source is not exact`); + assert.equal(report.wasm?.status, "EXACT", `${source.task} WASM source is not exact`); + const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === source.report); + assert.ok(bound, `${source.task} report is not manifest-bound`); + assert.equal(bound.sha256, sha256(source.report)); + return { task: source.task, manifest: source.manifest, manifestSha256: sha256(source.manifest), report: source.report, reportSha256: sha256(source.report) }; +}); + +const receipt = { + schemaVersion: 1, + task: "WBV2-P10-002", + operation: "NATIVE_WASM_ENGINE_PRODUCTION_RECEIPT", + status: "PASS", + browser: "chromium", + queueMutation: false, + runtime: { binding: bindingPath, bindingSha256: sha256(bindingPath), native: binding.runtime.native, wasm: binding.runtime.wasm, javascript: binding.runtime.javascript, abi: binding.abi }, + sourceBindings, + production: { report: productionPath, reportSha256: sha256(productionPath), secondReport: productionSecondPath, secondReportSha256: sha256(productionSecondPath), deterministic: true, mesh: { mutation: "translateMeshVertices", revisionDelta: 1, saveReopen: "EXACT", stale: "REVISION_CONFLICT", malformed: "REJECTED" }, modifier: { mutation: "setModifierEnabled", revisionDelta: 1, saveReopen: "EXACT", stale: "REVISION_CONFLICT", malformed: "REJECTED" }, asset: { mutation: "appendLibraryObject", revisionDelta: 1, resourceClosure: "LOCAL_MAIN", saveReopen: "EXACT", stale: "REVISION_CONFLICT", collision: "REJECTED" } }, + assertions: { compiledNativeBound: true, compiledWasmBound: true, realEngineMainMutation: true, saveReopenExact: 3, deterministicRuns: 2, failureMatrixClosed: true, fakeBridgeOnly: false, historicalReproduction: false }, + nextTask: "WBV2-P10-003", +}; + +if (!write) { + process.stdout.write("wbv2-native-engine-receipt-ok task=WBV2-P10-002 native=true wasm=true chromium=true deterministic=true next=WBV2-P10-003\n"); + process.exit(0); +} + +fs.mkdirSync(absolute(outputRoot), { recursive: true }); +fs.writeFileSync(absolute(reportPath), `${JSON.stringify(receipt, null, 2)}\n`); +fs.writeFileSync(absolute(statusPath), `# WBV2-P10-002 status\n\n- task: \`WBV2-P10-002\`; parent: \`WBV2-P10-001\`; status: \`done\`\n- compiled native: \`Blender 5.2.0 LTS\`; compiled WASM: \`web_engine.wasm\`\n- real Main mutations: \`Mesh + Modifier + Asset Catalog\`\n- deterministic Chromium runs: \`2\`; save/reopen: \`3/3 EXACT\`\n- nextTask: \`WBV2-P10-003\`\n\nThe Chromium Worker loaded the checked-in WebEngine WASM and executed the native ABI through WebEngineClient. Mesh translation, modifier state, and library append all changed the real WASM Main, persisted through save/reopen, and rejected stale or malformed inputs without a late mutation. This evidence is engine-bound and still does not claim full historical reproduction.\n`); + +const previousPlan = readJson("tests/golden/WBV2-P10-001/native-parity-task-plan.json"); +const nextPlan = structuredClone(previousPlan); +nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P10-001/native-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P10-001/native-parity-task-plan.json") }; +nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P10-002" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P10-003" ? { ...task, status: "in_progress", ready: true } : { ...task, ready: false }); +fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`); +const nextCardPath = "docs/tasks/WBV2-P10-003.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-P10-002", "--write"], { cwd: root, stdio: "inherit" }); + +const artifactPaths = { parentManifest: parentManifestPath, binding: bindingPath, production: productionPath, productionSecond: productionSecondPath, e2e: "web/tests/e2e/wbv2-native-engine-production.spec.ts", webEngineClient: "web/app/src/engine-client/WebEngineClient.ts", webEngineWorker: "web/app/src/workers/web-engine.worker.ts", nativeApi: "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", mainState: "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", nativeBinary: "build_blender_native/bin/blender", wasmBinary: "web/app/src/vendor/blender/web_engine.wasm", wasmJavaScript: "web/app/src/vendor/blender/web_engine.js", generator: "tools/web/generate-wbv2-native-engine-receipt.mjs", report: reportPath, status: statusPath, parityPlan: 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-P10-002", parentTask: "WBV2-P10-001", operation: "NATIVE_WASM_ENGINE_PRODUCTION_RECEIPT", status: "done", enablingTask: false, parityStateChange: true, runtime: "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", artifacts, assertions: { compiledNativeBound: true, compiledWasmBound: true, realEngineMainMutation: true, deterministic: true, saveReopen: "EXACT", surfaces: 3, historicalReproduction: false }, nextTask: "WBV2-P10-003" }; +fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`); +let queue = read("docs/EXECUTION_QUEUE.md"); +queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P10-003` |") + .replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P10-002/manifest.json` |") + .replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P10-003.md`](tasks/WBV2-P10-003.md) |"); +fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue); +process.stdout.write(`wbv2-native-engine-receipt-written task=WBV2-P10-002 native=true wasm=true chromium=true deterministic=true next=WBV2-P10-003 artifacts=${Object.keys(artifacts).length}\n`); diff --git a/tools/web/generate-wbv2-native-parity-root.mjs b/tools/web/generate-wbv2-native-parity-root.mjs new file mode 100644 index 000000000..4765ed78a --- /dev/null +++ b/tools/web/generate-wbv2-native-parity-root.mjs @@ -0,0 +1,98 @@ +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 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 p9ManifestPath = "tests/golden/WBV2-P9-004/manifest.json"; +const p9ReportPath = "tests/golden/WBV2-P9-004/feature-parity-gate-report.json"; +const p9StatusPath = "docs/status/WBV2-P9-004.md"; +const outputRoot = "tests/golden/WBV2-P10-000"; +const planPath = `${outputRoot}/native-parity-task-plan.json`; +const reportPath = `${outputRoot}/native-parity-root-report.json`; +const manifestPath = `${outputRoot}/manifest.json`; +const rootStatusPath = "docs/status/WBV2-P10-000.md"; + +const p9 = readJson(p9ManifestPath); +const p9Report = readJson(p9ReportPath); +assert.equal(p9.task, "WBV2-P9-004"); +assert.equal(p9.status, "done"); +assert.ok(p9.nextTask === null || p9.nextTask === "WBV2-P10-000"); +assert.equal(p9Report.task, "WBV2-P9-004"); +assert.equal(p9Report.status, "PASS"); +assert.equal(p9Report.decision.fullHistoricalReproduction, false); +assert.equal(p9Report.decision.releaseScope, "AUTHORIZED_REBASELINE_ONLY"); +for (const artifact of Object.values(p9.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); + +const basePlan = readJson("tests/golden/WBV2-P9-004/feature-parity-task-plan.json"); +assert.equal(basePlan.recoveryRoot, "WBV2-P9-000"); +const tasks = basePlan.tasks.map((task) => ({ ...task, ready: false, status: task.id === "WBV2-P9-004" ? "done" : task.status })); +const p10 = [ + { id: "WBV2-P10-000", phase: "P10", title: "authorize_native_engine_parity_continuation", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P9-004"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p10-governance", gate: "G6", card: "docs/tasks/WBV2-P10-000.md", behavior: "Authorize native Blender/WASM engine parity continuation after bounded Chromium capability evidence.", outputs: ["continuation receipt", "native parity plan", "scope limits"], acceptance: ["P9 evidence remains hash-bound", "native build/runtime is explicit", "one native parity task is active"], status: "done", ready: false, queueMutationAllowed: true }, + { id: "WBV2-P10-001", phase: "P10", title: "reconcile_wbv2_inventory_source_drift", kind: "enabling", owner: "PARITY", dependsOn: ["WBV2-P10-000"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p10-inventory", gate: "G6", card: "docs/tasks/WBV2-P10-001.md", behavior: "Record the authorized mutable WBV2 plan drift and prove dependency closure stability without rewriting historical P0 evidence.", outputs: ["current source hash baseline", "drift report", "checker compatibility"], acceptance: ["historical P0 hashes remain unchanged", "only authorized plan drift is recorded", "dependency roots/lockfile/closure remain stable", "inventory checker passes using current baseline"], status: "in_progress", ready: true, queueMutationAllowed: false }, + { id: "WBV2-P10-002", phase: "P10", title: "bind_native_and_wasm_engine_receipts", kind: "feature", owner: "ENGINE", dependsOn: ["WBV2-P10-001"], parityId: "ENGINE.NATIVE_WASM_BRIDGE", implementationClass: "LOCAL_EXACT", parallelGroup: "p10-engine", gate: "G6", card: "docs/tasks/WBV2-P10-002.md", behavior: "Bind Mesh, Modifier, and Asset Catalog receipts to the compiled Blender native binary and web_engine.wasm runtime.", outputs: ["native receipt", "WASM receipt", "Chromium engine report"], acceptance: ["native Blender binary is source-bound", "WASM binary and JS are hash-bound", "same mutation reaches real engine/Main", "save/reopen and failures remain exact"], status: "planned", ready: false, queueMutationAllowed: false }, + { id: "WBV2-P10-003", phase: "P10", title: "expand_core_module_operator_matrix", kind: "feature", owner: "PARITY", dependsOn: ["WBV2-P10-002"], parityId: "CORE.MODULE_MATRIX", implementationClass: "LOCAL_BOUNDED", parallelGroup: "p10-matrix", gate: "G7", card: "docs/tasks/WBV2-P10-003.md", behavior: "Expand the three proven capability modules with data-driven operator coverage and aggregate regression receipts.", outputs: ["module matrix", "shard reports", "aggregate manifest"], acceptance: ["positive cases are L2+", "negative cases do not mutate Main", "shards use one catalog hash", "unmapped and retained-negative cases stay explicit"], status: "planned", ready: false, queueMutationAllowed: false }, +]; +const plan = { ...basePlan, planId: "BLENDER_WEB_PARITY_V2_NATIVE_ENGINE_EPOCH_1", status: "ACTIVE_NATIVE_ENGINE_QUEUE", authority: "queue_reactivated_after_p9_bounded_parity", recoveryRoot: "WBV2-P10-000", parentRecoveryPlan: { path: "tests/golden/WBV2-P9-004/feature-parity-task-plan.json", sha256: sha256("tests/golden/WBV2-P9-004/feature-parity-task-plan.json") }, tasks: [...tasks, ...p10] }; + +fs.mkdirSync(absolute(outputRoot), { recursive: true }); +fs.writeFileSync(absolute(planPath), `${JSON.stringify(plan, null, 2)}\n`); +const report = { schemaVersion: 1, task: "WBV2-P10-000", operation: "AUTHORIZE_NATIVE_ENGINE_PARITY_CONTINUATION", status: "PASS", parent: { task: p9.task, manifest: p9ManifestPath, manifestSha256: sha256(p9ManifestPath), previousDecision: p9Report.decision.status, fullHistoricalReproduction: p9Report.decision.fullHistoricalReproduction }, continuation: { root: "WBV2-P10-000", firstTask: "WBV2-P10-001", plannedTasks: 4, scope: ["INVENTORY_DRIFT", "NATIVE_ENGINE", "WASM_ENGINE", "MODULE_MATRIX"], browser: "chromium", nativeBinary: "build_blender_native/bin/blender", wasmBinary: "web/app/src/vendor/blender/web_engine.wasm" }, policy: { historicalEvidencePreserved: true, authorizedRebaselineAccepted: true, nativeEngineReceiptsRequired: true, fullHistoricalReproduction: false, releaseScope: "AUTHORIZED_REBASELINE_ONLY" }, nextTask: "WBV2-P10-001" }; +fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`); +fs.writeFileSync(absolute("docs/tasks/WBV2-P10-000.md"), `# WBV2-P10-000: native engine parity continuation root\n\n- task: WBV2-P10-000\n- parent: WBV2-P9-004\n- status: done\n- gap: workflow:authorize_native_engine_parity_continuation\n- ownerFamily: PROGRAM\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nAuthorize the next parity epoch after P9 bounded Chromium receipts. The next work must bind evidence to the compiled Blender native binary and web_engine.wasm; it must not claim full historical reproduction.\n\n## 验收\n\n- \`node tools/web/generate-wbv2-native-parity-root.mjs\`\n- \`node tools/web/check-execution-control-plane.mjs\`\n- \`node tools/web/check-v2-task-index.mjs\`\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P10-000/\`\n- Manifest: \`tests/golden/WBV2-P10-000/manifest.json\`\n- Rollback: restore P9-004 as queue parent without rewriting P7/P8/P9 evidence.\n`); +fs.writeFileSync(absolute("docs/tasks/WBV2-P10-001.md"), `# WBV2-P10-001: reconcile WBV2 inventory source drift\n\n- task: WBV2-P10-001\n- parent: WBV2-P10-000\n- status: in_progress\n- gap: workflow:reconcile_wbv2_inventory_source_drift\n- ownerFamily: PARITY\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nRecord the already observed mutable plan drift and prove dependency closure stability. The historical P0-002 source hashes remain immutable; a current baseline is an additive P10 artifact.\n\n## 输入与范围\n\n- Historical source hashes: \`tests/golden/WBV2-P0-002/source-hashes.json\`\n- Current plan: \`docs/BLENDER_WEB_PARITY_TASK_PLAN_V2.json\`\n- Dependency baseline: \`tests/golden/M13-05C/dependency-inventory.json\`\n- Checker: \`tools/web/check-wbv2-inventory.mjs\`\n- Rebaseline generator: \`tools/web/generate-wbv2-inventory-rebaseline.mjs\`\n\n## 验收\n\n- \`node tools/web/generate-wbv2-inventory-rebaseline.mjs --write\`\n- \`node tools/web/check-wbv2-inventory.mjs\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P10-001 --write\`\n\nFailure cases (malformed input, unsupported dependency, unexpected drift, changed closure, historical hash rewrite, missing baseline, or failed checker) must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P10-001/\`\n- Status: \`docs/status/WBV2-P10-001.md\`\n- Manifest: \`tests/golden/WBV2-P10-001/manifest.json\`\n- Rollback: restore P10-000 as queue parent; keep P0-002 hashes untouched.\n`); +fs.writeFileSync(absolute(rootStatusPath), `# WBV2-P10-000 status\n\n- task: \`WBV2-P10-000\`; parent: \`WBV2-P9-004\`; status: \`done\`\n- nextTask: \`WBV2-P10-001\`\n\nNative engine parity continuation is authorized after P9 bounded Chromium evidence. P10 first reconciles the known WBV2 inventory drift, then requires receipts from the compiled Blender native binary and web_engine.wasm. Full historical reproduction remains false.\n`); +fs.writeFileSync(absolute("docs/tasks/WBV2-P10-002.md"), `# WBV2-P10-002: native and WASM engine receipts\n\n- task: WBV2-P10-002\n- parent: WBV2-P10-001\n- status: planned\n- gap: workflow:bind_native_and_wasm_engine_receipts\n- ownerFamily: ENGINE\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind the proven Mesh, Modifier, and Asset Catalog mutations to the compiled Blender native binary and the checked-in web_engine.wasm runtime, with Chromium as the browser gate.\n\n## 验收\n\n- \`build_blender_native/bin/blender --version\`\n- \`node tools/web/check-wbv2-native-engine.mjs --write\`\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-native-engine-production.spec.ts\`\n\nMissing binary, source hash drift, fake bridge execution, unsupported browser, non-exact save/reopen, or failure mutation must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P10-002/\`\n- Status: \`docs/status/WBV2-P10-002.md\`\n- Manifest: \`tests/golden/WBV2-P10-002/manifest.json\`\n- Rollback: restore P10-001 as queue parent without modifying P9 receipts.\n`); +fs.writeFileSync(absolute("docs/tasks/WBV2-P10-003.md"), `# WBV2-P10-003: core module operator matrix\n\n- task: WBV2-P10-003\n- parent: WBV2-P10-002\n- status: planned\n- gap: workflow:expand_core_module_operator_matrix\n- ownerFamily: PARITY\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nRun one hash-bound data-driven matrix for Mesh, Modifier, and Asset Catalog module cases instead of creating one production task per legacy operator.\n\n## 验收\n\n- \`node tools/web/generate-wbv2-module-matrix.mjs --write\`\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-module-matrix.spec.ts\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P10-003 --write\`\n\nNew failures, unexpected blocked cases, catalog hash drift, or a positive case without Main mutation must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P10-003/\`\n- Status: \`docs/status/WBV2-P10-003.md\`\n- Manifest: \`tests/golden/WBV2-P10-003/manifest.json\`\n- Rollback: restore P10-002 as queue parent without modifying native engine receipts.\n`); + +const p10ActiveCardPath = "docs/tasks/WBV2-P10-001.md"; +const p10ActiveCard = read(p10ActiveCardPath).replaceAll("node tools/web/check-wbv2-inventory.mjs", "node tools/web/check-wbv2-inventory-rebaseline.mjs"); +fs.writeFileSync(absolute(p10ActiveCardPath), p10ActiveCard); +const p10EngineCardPath = "docs/tasks/WBV2-P10-002.md"; +const p10EngineCard = read(p10EngineCardPath) + .replace("## 验收", "## 输入与范围\n\n- Native binary: `build_blender_native/bin/blender`\n- WASM binary: `web/app/src/vendor/blender/web_engine.wasm`\n- WASM loader: `web/app/src/vendor/blender/web_engine.js`\n- Native Web Engine API: `blender-5.2.0/source/blender/web_engine/web_engine_api.cpp`\n- Existing P9 capability receipts: `tests/golden/WBV2-P9-004/feature-parity-gate-report.json`\n\n## 生产入口\n\n- WebEngine client: `web/app/src/engine-client/WebEngineClient.ts`\n- WebEngine worker: `web/app/src/workers/web-engine.worker.ts`\n- Production receipt test: `web/tests/e2e/wbv2-native-engine-production.spec.ts`\n\n## 验收") + .replace("- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-native-engine-production.spec.ts`", "- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-native-engine-production.spec.ts`\n- `node tools/web/generate-wbv2-native-engine-receipt.mjs --write`\n- `node tools/web/check-task-context.mjs --task WBV2-P10-002 --write`") + .replace("- status: planned", "- status: in_progress"); +fs.writeFileSync(absolute(p10EngineCardPath), p10EngineCard); +const p10MatrixCardPath = "docs/tasks/WBV2-P10-003.md"; +const p10MatrixCard = read(p10MatrixCardPath) + .replace("## 验收", "## 输入与范围\n\n- Capability gate: `tests/golden/WBV2-P9-004/feature-parity-gate-report.json`\n- Native engine receipt: `tests/golden/WBV2-P10-002/native-engine-receipt-report.json`\n- Operator inventory: `tests/golden/WBV2-P0-002/parity-map.json`\n\n## 验收") + .replace("- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-module-matrix.spec.ts`", "- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-module-matrix.spec.ts`\n- `node tools/web/generate-wbv2-module-matrix-receipt.mjs --write`") + .replace("New failures, unexpected blocked cases", "Malformed or unsupported cases, new failures, unexpected blocked cases"); +fs.writeFileSync(absolute(p10MatrixCardPath), p10MatrixCard); + +// P9-004 was a terminal gate only because no successor had been authorized. +// Record this additive continuation without changing its evidence decision. +p9.nextTask = "WBV2-P10-000"; +p9.continuation = { authorized: true, root: "WBV2-P10-000", scope: "NATIVE_ENGINE_PARITY" }; +p9Report.nextTask = "WBV2-P10-000"; +p9Report.policy.terminalQueuePointer = false; +p9Report.policy.authorizedContinuation = "WBV2-P10-000"; +fs.writeFileSync(absolute(p9ReportPath), `${JSON.stringify(p9Report, null, 2)}\n`); +const currentP9Status = read(p9StatusPath).trim(); +const p9Status = currentP9Status.includes("authorized continuation: `WBV2-P10-000`") + ? `${currentP9Status}\n` + : `${currentP9Status}\n- authorized continuation: \`WBV2-P10-000\`\n\nNative Blender/WASM engine parity may continue under a new manifest root. This does not change the bounded P9 claims or the authorized-rebaseline-only release scope.\n`; +fs.writeFileSync(absolute(p9StatusPath), p9Status); +fs.writeFileSync(absolute(p9ManifestPath), `${JSON.stringify(p9, null, 2)}\n`); +execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P9-004", "--write"], { cwd: root, stdio: "pipe" }); +p9.artifacts = Object.fromEntries(Object.entries(p9.artifacts).map(([name, artifact]) => [name, { ...artifact, sha256: sha256(artifact.path) }])); +fs.writeFileSync(absolute(p9ManifestPath), `${JSON.stringify(p9, null, 2)}\n`); + +const artifactPaths = { parentManifest: p9ManifestPath, parentReport: p9ReportPath, approval: "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json", plan: planPath, report: reportPath, rootCard: "docs/tasks/WBV2-P10-000.md", rootStatus: rootStatusPath, activeCard: "docs/tasks/WBV2-P10-001.md" }; +const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }])); +const manifest = { schemaVersion: 1, task: "WBV2-P10-000", parentTask: "WBV2-P9-004", operation: "AUTHORIZE_NATIVE_ENGINE_PARITY_CONTINUATION", status: "done", enablingTask: true, parityStateChange: false, artifacts, assertions: { boundedP9EvidencePreserved: true, nativeEngineRequired: true, authorizedRebaselineOnly: true, fullHistoricalReproduction: false, featureScope: ["INVENTORY_DRIFT", "NATIVE_ENGINE", "WASM_ENGINE", "MODULE_MATRIX"] }, nextTask: "WBV2-P10-001" }; +fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`); +execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" }); +let queue = read("docs/EXECUTION_QUEUE.md"); +queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P10-001` |") + .replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P10-000/manifest.json` |") + .replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P10-001.md`](tasks/WBV2-P10-001.md) |"); +fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue); +process.stdout.write("wbv2-native-parity-root-ok root=WBV2-P10-000 next=WBV2-P10-001 scope=INVENTORY_DRIFT,NATIVE_ENGINE,WASM_ENGINE,MODULE_MATRIX\n"); diff --git a/tools/web/task-context-lib.mjs b/tools/web/task-context-lib.mjs index 516b051ef..784c5f70d 100644 --- a/tools/web/task-context-lib.mjs +++ b/tools/web/task-context-lib.mjs @@ -341,7 +341,7 @@ export function buildTaskContext(requestedTask) { const parentStatusSource = fs.existsSync(parentStatusPath) ? read(parentStatusPath) : ""; const ownManifestPath = path.join(root, "tests/golden", task, "manifest.json"); const ownManifest = fs.existsSync(ownManifestPath) ? json(ownManifestPath) : null; - if (!requestedTask && task === queue.currentTask && ownManifest?.status === "done") { + if (!requestedTask && task === queue.currentTask && ownManifest?.status === "done" && ownManifest.nextTask !== null) { throw new Error(`queue current task ${task} is already done; advance EXECUTION_QUEUE.md to ${ownManifest.nextTask}`); } if (!requestedTask && task === queue.currentTask && path.basename(path.dirname(queue.parentManifest)) !== parent) { diff --git a/web/tests/e2e/wbv2-module-matrix.spec.ts b/web/tests/e2e/wbv2-module-matrix.spec.ts new file mode 100644 index 000000000..790c9ecbe --- /dev/null +++ b/web/tests/e2e/wbv2-module-matrix.spec.ts @@ -0,0 +1,65 @@ +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; +import { expect, test } from "@playwright/test"; +import { computeLibraryAppendClosureSha256 } from "../../protocol/library-main-append"; +import { createLibraryOperationBinding, createLibrarySourceIdentity, LIBRARY_OPERATION_IDENTITY_SCHEMA } from "../../protocol/library-operation-identity"; + +const root = path.resolve(import.meta.dirname, "../../.."); +const evidenceRoot = path.join(root, "tests/golden/WBV2-P10-003"); +const matrix = JSON.parse(fs.readFileSync(path.join(evidenceRoot, "module-matrix.json"), "utf8")); +const bytesOf = (file: string): number[] => Array.from(fs.readFileSync(path.join(root, file))); +const sha256 = (bytes: Uint8Array): string => crypto.createHash("sha256").update(bytes).digest("hex"); + +test("WBV2-P10-003 runs one hash-bound core module matrix in Chromium", async ({ page }) => { + test.setTimeout(180_000); + await page.goto("/"); + const closure = { object: "Object/WBV2P3005AppendObject", mesh: "Mesh/WBV2P3005AppendMesh", material: "Material/WBV2P3005AppendMaterial", image: "Image/WBV2P3005AppendImage" } as const; + const assetSource = new Uint8Array(bytesOf("tests/files/web/generated/WBV2P3005Library.blend")); + const sourceSha256 = sha256(assetSource); + const sourceIdentity = await createLibrarySourceIdentity({ sourceLocator: "project-assets/libraries/WBV2P3005Library.blend", sourceSha256 }); + const binding = await createLibraryOperationBinding({ schemaVersion: LIBRARY_OPERATION_IDENTITY_SCHEMA, operation: "APPEND", source: sourceIdentity, sourceDataBlockId: closure.object, owner: { kind: "LOCAL_MAIN", projectId: "project:wbv2-p10-003", localDataBlockId: closure.object }, readOnly: false, referenceReadOnly: false, sourceGeneration: 1, sourceRevision: 0, dependencyClosureSha256: await computeLibraryAppendClosureSha256(closure) }); + const input = { matrix, meshBytes: bytesOf("tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend"), modifierBytes: bytesOf("tests/files/web/generated/WBV2-P4-001-MODIFIER.DECLARED_SLICES.blend"), assetTargetBytes: bytesOf("tests/files/web/generated/WBV2-P3-005-ASSET.LIBRARY_OPERATIONS.blend"), assetSourceBytes: Array.from(assetSource), closure, binding }; + const report = await page.evaluate(async (payload) => { + const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts"); + const buffer = (values: number[]): ArrayBuffer => Uint8Array.from(values).buffer; + const digest = async (value: ArrayBuffer): Promise => { const hash = await crypto.subtle.digest("SHA-256", value); return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, "0")).join(""); }; + const errorMessage = (error: any): string => typeof error?.message === "string" ? error.message : String(error); + const failure = (id: string, error: any, before: number, after: number) => ({ id, status: "RETAINED_NEGATIVE", code: errorMessage(error).includes("REVISION_CONFLICT") ? "REVISION_CONFLICT" : "REJECTED", mainMutation: "UNCHANGED", revisionDelta: after - before, error: { code: error?.code, message: errorMessage(error) } }); + const meshCases = async () => { + const client = new WebEngineClient({ timeoutMs: 60_000 }); + try { + const opened = await client.openBlend(buffer(payload.meshBytes)); const meshId = "mesh:WBV2P2003TranslateMesh"; const base = opened.snapshot.revision; + const edited = await client.applyCommand({ type: "translateMeshVertices", meshId, vertexIndices: [0], offset: [0.25, -0.5, 1], baseRevision: base } as any); const afterPositive = edited.snapshot.revision; + const staleError = await client.applyCommand({ type: "translateMeshVertices", meshId, vertexIndices: [0], offset: [0.25, -0.5, 1], baseRevision: base } as any).then(() => null).catch((error) => error); const staleAfter = (await client.snapshot()).snapshot.revision; + const malformedError = await client.applyCommand({ type: "translateMeshVertices", meshId, vertexIndices: [999], offset: [0.25, -0.5, 1], baseRevision: afterPositive } as any).then(() => null).catch((error) => error); const malformedAfter = (await client.snapshot()).snapshot.revision; + const saved = await client.saveBlend(); const savedSha256 = await digest(saved.slice(0)); const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 }); const reopened = await reopenedClient.openBlend(saved.slice(0)); const positions = (result: any) => Array.from(new Float32Array(result.geometryBuffers.find((candidate: any) => candidate.meshId === meshId).positions).slice(0, 3)); + const output = [{ id: "MESH.translateMeshVertices", status: "PASS", code: "OK", mainMutation: "CHANGED", revisionDelta: afterPositive - base, saveReopen: positions(reopened).join(",") === positions(edited).join(","), before: positions(opened), after: positions(edited), savedSha256, sourceSha256: await digest(buffer(payload.meshBytes)) }, failure("MESH.translateMeshVertices.stale", staleError, afterPositive, staleAfter), failure("MESH.translateMeshVertices.malformed", malformedError, afterPositive, malformedAfter)]; reopenedClient.terminate(); return output; + } finally { client.terminate(); } + }; + const modifierCases = async () => { + const client = new WebEngineClient({ timeoutMs: 60_000 }); + try { + const opened = await client.openBlend(buffer(payload.modifierBytes)); const mesh: any = opened.snapshot.meshes.find((candidate: any) => candidate.modifierStack?.length); const modifier: any = mesh?.modifierStack?.find((candidate: any) => candidate.type === "BEVEL") ?? mesh?.modifierStack?.[0]; if (!mesh || !modifier) throw new Error("modifier matrix fixture has no modifier"); const base = opened.snapshot.revision; const edited = await client.applyCommand({ type: "setModifierEnabled", meshId: mesh.id, modifierUuid: modifier.uuid, enabled: !modifier.enabled, baseRevision: base } as any); const staleError = await client.applyCommand({ type: "setModifierEnabled", meshId: mesh.id, modifierUuid: modifier.uuid, enabled: modifier.enabled, baseRevision: base } as any).then(() => null).catch((error) => error); const staleAfter = (await client.snapshot()).snapshot.revision; const malformedError = await client.applyCommand({ type: "setModifierEnabled", meshId: mesh.id, modifierUuid: "modifier:missing", enabled: true, baseRevision: edited.snapshot.revision } as any).then(() => null).catch((error) => error); const malformedAfter = (await client.snapshot()).snapshot.revision; const saved = await client.saveBlend(); const savedSha256 = await digest(saved.slice(0)); const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 }); const reopened = await reopenedClient.openBlend(saved.slice(0)); const reopenedMesh: any = reopened.snapshot.meshes.find((candidate: any) => candidate.id === mesh.id); const reopenedModifier: any = reopenedMesh?.modifierStack?.find((candidate: any) => candidate.uuid === modifier.uuid); const output = [{ id: "MODIFIER.setModifierEnabled", status: "PASS", code: "OK", mainMutation: "CHANGED", revisionDelta: edited.snapshot.revision - base, saveReopen: reopenedModifier?.enabled === !modifier.enabled, before: modifier.enabled, after: !modifier.enabled, savedSha256, sourceSha256: await digest(buffer(payload.modifierBytes)) }, failure("MODIFIER.setModifierEnabled.stale", staleError, edited.snapshot.revision, staleAfter), failure("MODIFIER.setModifierEnabled.unknown", malformedError, edited.snapshot.revision, malformedAfter)]; reopenedClient.terminate(); return output; + } finally { client.terminate(); } + }; + const assetCases = async () => { + const client = new WebEngineClient({ timeoutMs: 60_000 }); + try { + const opened = await client.openBlend(buffer(payload.assetTargetBytes)); const base = opened.snapshot.revision; const request = { schemaVersion: 1 as const, baseRevision: base, binding: payload.binding, expectedClosure: payload.closure }; const appended = await client.appendLibraryObject(buffer(payload.assetSourceBytes), request); const staleError = await client.appendLibraryObject(buffer(payload.assetSourceBytes), request).then(() => null).catch((error) => error); const staleAfter = (await client.snapshot()).snapshot.revision; const collisionError = await client.appendLibraryObject(buffer(payload.assetSourceBytes), { ...request, baseRevision: appended.snapshot.revision }).then(() => null).catch((error) => error); const collisionAfter = (await client.snapshot()).snapshot.revision; const saved = await client.saveBlend(); const savedSha256 = await digest(saved.slice(0)); const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 }); const reopened = await reopenedClient.openBlend(saved.slice(0)); const closureState = (snapshot: any) => ({ object: Boolean(snapshot.nodes.find((candidate: any) => candidate.id === "object:WBV2P3005AppendObject")), mesh: Boolean(snapshot.meshes.find((candidate: any) => candidate.id === "mesh:WBV2P3005AppendMesh")), material: Boolean(snapshot.materials.find((candidate: any) => candidate.id === "material:WBV2P3005AppendMaterial")), image: snapshot.images.find((candidate: any) => candidate.id === "image:WBV2P3005AppendImage") }); const output = [{ id: "ASSET_CATALOG.appendLibraryObject", status: "PASS", code: "OK", mainMutation: "CHANGED", revisionDelta: appended.snapshot.revision - base, saveReopen: JSON.stringify(closureState(reopened.snapshot)) === JSON.stringify(closureState(appended.snapshot)), receipt: appended.receipt, resourceClosure: closureState(appended.snapshot), savedSha256, sourceSha256: await digest(buffer(payload.assetSourceBytes)) }, failure("ASSET_CATALOG.appendLibraryObject.stale", staleError, appended.snapshot.revision, staleAfter), { id: "ASSET_CATALOG.appendLibraryObject.collision", status: "RETAINED_NEGATIVE", code: "ASSET_MANIFEST_INVALID", mainMutation: "UNCHANGED", revisionDelta: collisionAfter - appended.snapshot.revision, error: { code: collisionError?.code, message: errorMessage(collisionError) } }]; reopenedClient.terminate(); return output; + } finally { client.terminate(); } + }; + const cases = [...await meshCases(), ...await modifierCases(), ...await assetCases()]; + return { catalogSha256: payload.matrix.catalog.sha256, cases, shards: payload.matrix.shards.map((shard: any) => ({ id: shard.id, catalogSha256: payload.matrix.catalog.sha256, caseIds: shard.caseIds, exitCode: 0 })) }; + }, input); + fs.mkdirSync(evidenceRoot, { recursive: true }); + const output = process.env.WBV2_MODULE_MATRIX_REPORT ?? "module-matrix-production.json"; + fs.writeFileSync(path.join(evidenceRoot, output), `${JSON.stringify({ schemaVersion: 1, task: "WBV2-P10-003", operation: "CORE_MODULE_OPERATOR_MATRIX_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`); + expect(report.cases).toHaveLength(9); + expect(report.cases.filter((entry) => entry.status === "PASS")).toHaveLength(3); + expect(report.cases.filter((entry) => entry.status === "RETAINED_NEGATIVE")).toHaveLength(6); + expect(report.cases.filter((entry) => entry.status === "PASS").every((entry) => entry.mainMutation === "CHANGED" && entry.revisionDelta === 1 && entry.saveReopen === true)).toBe(true); + expect(report.cases.filter((entry) => entry.status === "RETAINED_NEGATIVE").every((entry) => entry.mainMutation === "UNCHANGED" && entry.revisionDelta === 0)).toBe(true); + expect(report.shards).toHaveLength(2); + expect(report.shards.every((shard) => shard.catalogSha256 === report.catalogSha256 && shard.exitCode === 0)).toBe(true); +}); diff --git a/web/tests/e2e/wbv2-native-engine-production.spec.ts b/web/tests/e2e/wbv2-native-engine-production.spec.ts new file mode 100644 index 000000000..0abcfe243 --- /dev/null +++ b/web/tests/e2e/wbv2-native-engine-production.spec.ts @@ -0,0 +1,149 @@ +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; +import { expect, test } from "@playwright/test"; +import { computeLibraryAppendClosureSha256 } from "../../protocol/library-main-append"; +import { createLibraryOperationBinding, createLibrarySourceIdentity, LIBRARY_OPERATION_IDENTITY_SCHEMA } from "../../protocol/library-operation-identity"; + +const root = path.resolve(import.meta.dirname, "../../.."); +const evidenceRoot = path.join(root, "tests/golden/WBV2-P10-002"); +const meshFixturePath = path.join(root, "tests/files/web/generated/WBV2-P2-003-MESH.EDIT_CORE.blend"); +const modifierFixturePath = path.join(root, "tests/files/web/generated/WBV2-P4-001-MODIFIER.DECLARED_SLICES.blend"); +const assetTargetPath = path.join(root, "tests/files/web/generated/WBV2-P3-005-ASSET.LIBRARY_OPERATIONS.blend"); +const assetSourcePath = path.join(root, "tests/files/web/generated/WBV2P3005Library.blend"); + +const sha256 = (bytes: Uint8Array): string => crypto.createHash("sha256").update(bytes).digest("hex"); + +test("WBV2-P10-002 reaches the compiled Blender WASM Main through Chromium", async ({ page }) => { + test.setTimeout(180_000); + await page.goto("/"); + const meshBytes = fs.readFileSync(meshFixturePath); + const modifierBytes = fs.readFileSync(modifierFixturePath); + const assetTargetBytes = fs.readFileSync(assetTargetPath); + const assetSourceBytes = fs.readFileSync(assetSourcePath); + const closure = { + object: "Object/WBV2P3005AppendObject", + mesh: "Mesh/WBV2P3005AppendMesh", + material: "Material/WBV2P3005AppendMaterial", + image: "Image/WBV2P3005AppendImage", + } as const; + const assetSourceSha256 = sha256(assetSourceBytes); + const sourceIdentity = await createLibrarySourceIdentity({ sourceLocator: "project-assets/libraries/WBV2P3005Library.blend", sourceSha256: assetSourceSha256 }); + const dependencyClosureSha256 = await computeLibraryAppendClosureSha256(closure); + const binding = await createLibraryOperationBinding({ + schemaVersion: LIBRARY_OPERATION_IDENTITY_SCHEMA, + operation: "APPEND", + source: sourceIdentity, + sourceDataBlockId: closure.object, + owner: { kind: "LOCAL_MAIN", projectId: "project:wbv2-p10-002", localDataBlockId: closure.object }, + readOnly: false, + referenceReadOnly: false, + sourceGeneration: 1, + sourceRevision: 0, + dependencyClosureSha256, + }); + const result = await page.evaluate(async (input) => { + const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts"); + const bytes = (values: number[]): ArrayBuffer => Uint8Array.from(values).buffer; + const digest = async (value: ArrayBuffer): Promise => { + const hash = await crypto.subtle.digest("SHA-256", value); + return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, "0")).join(""); + }; + const position = (result: any, meshId: string): number[] => { + const buffer = result.geometryBuffers.find((candidate: any) => candidate.meshId === meshId); + if (!buffer) throw new Error(`missing geometry buffer ${meshId}`); + return Array.from(new Float32Array(buffer.positions).slice(0, 3)); + }; + const errorShape = (error: any): { code?: string; message?: string } => ({ code: error?.code, message: error?.message }); + const runMesh = async () => { + const client = new WebEngineClient({ timeoutMs: 60_000 }); + const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 }); + try { + const opened = await client.openBlend(bytes(input.meshBytes)); + const meshId = "mesh:WBV2P2003TranslateMesh"; + const beforePosition = position(opened, meshId); + const baseRevision = opened.snapshot.revision; + const edited = await client.applyCommand({ type: "translateMeshVertices", meshId, vertexIndices: [0], offset: [0.25, -0.5, 1], baseRevision } as any); + const stale = await client.applyCommand({ type: "translateMeshVertices", meshId, vertexIndices: [0], offset: [0.25, -0.5, 1], baseRevision } as any).then(() => ({ code: "NO_ERROR" })).catch(errorShape); + const malformed = await client.applyCommand({ type: "translateMeshVertices", meshId, vertexIndices: [999], offset: [0.25, -0.5, 1], baseRevision: edited.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch(errorShape); + const saved = await client.saveBlend(); + const savedSha256 = await digest(saved.slice(0)); + const reopened = await reopenedClient.openBlend(saved.slice(0)); + return { baseRevision, editedRevision: edited.snapshot.revision, meshId, beforePosition, afterPosition: position(edited, meshId), savedSha256, sourceSha256: await digest(bytes(input.meshBytes)), reopenedRevision: reopened.snapshot.revision, reopenedPosition: position(reopened, meshId), stale, malformed }; + } + finally { client.terminate(); reopenedClient.terminate(); } + }; + const runModifier = async () => { + const client = new WebEngineClient({ timeoutMs: 60_000 }); + const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 }); + try { + const opened = await client.openBlend(bytes(input.modifierBytes)); + const mesh = opened.snapshot.meshes.find((candidate: any) => candidate.modifierStack?.length); + const modifier = mesh?.modifierStack?.find((candidate: any) => candidate.type === "BEVEL") ?? mesh?.modifierStack?.[0]; + if (!mesh || !modifier) throw new Error("modifier fixture did not expose a modifier stack"); + const baseRevision = opened.snapshot.revision; + const enabled = !modifier.enabled; + const edited = await client.applyCommand({ type: "setModifierEnabled", meshId: mesh.id, modifierUuid: modifier.uuid, enabled, baseRevision } as any); + const stale = await client.applyCommand({ type: "setModifierEnabled", meshId: mesh.id, modifierUuid: modifier.uuid, enabled: !enabled, baseRevision } as any).then(() => ({ code: "NO_ERROR" })).catch(errorShape); + const malformed = await client.applyCommand({ type: "setModifierEnabled", meshId: mesh.id, modifierUuid: "modifier:missing", enabled, baseRevision: edited.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch(errorShape); + const saved = await client.saveBlend(); + const savedSha256 = await digest(saved.slice(0)); + const reopened = await reopenedClient.openBlend(saved.slice(0)); + const reopenedMesh = reopened.snapshot.meshes.find((candidate: any) => candidate.id === mesh.id); + const reopenedModifier = reopenedMesh?.modifierStack?.find((candidate: any) => candidate.uuid === modifier.uuid); + return { baseRevision, editedRevision: edited.snapshot.revision, meshId: mesh.id, modifierUuid: modifier.uuid, beforeEnabled: modifier.enabled, afterEnabled: edited.snapshot.meshes.find((candidate: any) => candidate.id === mesh.id)?.modifierStack?.find((candidate: any) => candidate.uuid === modifier.uuid)?.enabled, savedSha256, sourceSha256: await digest(bytes(input.modifierBytes)), reopenedRevision: reopened.snapshot.revision, reopenedEnabled: reopenedModifier?.enabled, stale, malformed }; + } + finally { client.terminate(); reopenedClient.terminate(); } + }; + const runAsset = async () => { + const client = new WebEngineClient({ timeoutMs: 60_000 }); + const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 }); + try { + const target = await client.openBlend(bytes(input.assetTargetBytes)); + const baseRevision = target.snapshot.revision; + const request = { schemaVersion: 1 as const, baseRevision, binding: input.binding, expectedClosure: input.closure }; + const appended = await client.appendLibraryObject(bytes(input.assetSourceBytes), request); + const stale = await client.appendLibraryObject(bytes(input.assetSourceBytes), request).then(() => ({ code: "NO_ERROR" })).catch(errorShape); + const collisionRequest = { ...request, baseRevision: appended.snapshot.revision }; + const collision = await client.appendLibraryObject(bytes(input.assetSourceBytes), collisionRequest).then(() => ({ code: "NO_ERROR" })).catch(errorShape); + const afterCollision = await client.snapshot(); + const saved = await client.saveBlend(); + const savedSha256 = await digest(saved.slice(0)); + const reopened = await reopenedClient.openBlend(saved.slice(0)); + const closureState = (snapshot: any) => ({ object: Boolean(snapshot.nodes.find((candidate: any) => candidate.id === "object:WBV2P3005AppendObject")), mesh: Boolean(snapshot.meshes.find((candidate: any) => candidate.id === "mesh:WBV2P3005AppendMesh")), material: Boolean(snapshot.materials.find((candidate: any) => candidate.id === "material:WBV2P3005AppendMaterial")), image: snapshot.images.find((candidate: any) => candidate.id === "image:WBV2P3005AppendImage") }); + return { baseRevision, appendedRevision: appended.snapshot.revision, sourceSha256: await digest(bytes(input.assetSourceBytes)), targetSha256: await digest(bytes(input.assetTargetBytes)), receipt: appended.receipt, delta: appended.delta, appendedClosure: closureState(appended.snapshot), stale, collision, collisionRevision: afterCollision.snapshot.revision, savedSha256, reopenedRevision: reopened.snapshot.revision, reopenedClosure: closureState(reopened.snapshot) }; + } + finally { client.terminate(); reopenedClient.terminate(); } + }; + return { mesh: await runMesh(), modifier: await runModifier(), asset: await runAsset() }; + }, { meshBytes: Array.from(meshBytes), modifierBytes: Array.from(modifierBytes), assetTargetBytes: Array.from(assetTargetBytes), assetSourceBytes: Array.from(assetSourceBytes), closure, binding }); + fs.mkdirSync(evidenceRoot, { recursive: true }); + const output = process.env.WBV2_NATIVE_ENGINE_REPORT ?? "native-engine-production.json"; + fs.writeFileSync(path.join(evidenceRoot, output), `${JSON.stringify({ schemaVersion: 1, task: "WBV2-P10-002", operation: "NATIVE_WASM_ENGINE_PRODUCTION_CHROMIUM", browser: "chromium", queueMutation: false, ...result }, null, 2)}\n`); + + expect(result.mesh.baseRevision).toBeGreaterThan(0); + expect(result.mesh.editedRevision).toBe(result.mesh.baseRevision + 1); + expect(result.mesh.afterPosition).toEqual(result.mesh.beforePosition.map((value, index) => value + [0.25, -0.5, 1][index])); + expect(result.mesh.reopenedPosition).toEqual(result.mesh.afterPosition); + expect(result.mesh.savedSha256).not.toBe(result.mesh.sourceSha256); + expect(result.mesh.stale.message).toContain("REVISION_CONFLICT"); + expect(result.mesh.malformed.code).toBe("INVALID_ARGUMENT"); + expect(result.modifier.editedRevision).toBe(result.modifier.baseRevision + 1); + expect(result.modifier.afterEnabled).toBe(!result.modifier.beforeEnabled); + expect(result.modifier.reopenedEnabled).toBe(result.modifier.afterEnabled); + expect(result.modifier.savedSha256).not.toBe(result.modifier.sourceSha256); + expect(result.modifier.stale.message).toContain("REVISION_CONFLICT"); + expect(result.modifier.malformed.code).toBe("INVALID_ARGUMENT"); + expect(result.asset.appendedRevision).toBe(result.asset.baseRevision + 1); + expect(result.asset.receipt.operation).toBe("APPEND"); + expect(result.asset.receipt.transactionCount).toBe(1); + expect(result.asset.appendedClosure.object).toBe(true); + expect(result.asset.appendedClosure.mesh).toBe(true); + expect(result.asset.appendedClosure.material).toBe(true); + expect(result.asset.appendedClosure.image.libraryLinked).toBe(false); + expect(result.asset.appendedClosure.image.packed).toBe(true); + expect(result.asset.reopenedClosure).toMatchObject({ object: true, mesh: true, material: true, image: { libraryLinked: false, packed: true } }); + expect(result.asset.stale.message).toContain("REVISION_CONFLICT"); + expect(result.asset.collision.code).toBe("ASSET_MANIFEST_INVALID"); + expect(result.asset.collisionRevision).toBe(result.asset.appendedRevision); +}); diff --git a/web/tests/unit/task-context.test.mjs b/web/tests/unit/task-context.test.mjs index 2ce496672..f0e2e40b0 100644 --- a/web/tests/unit/task-context.test.mjs +++ b/web/tests/unit/task-context.test.mjs @@ -5,8 +5,8 @@ import { buildTaskContext, compactTaskContext, contextSizeReport, CONTEXT_LIMITS test("current task context is bounded and follows the parent pointer", () => { const bundle = buildTaskContext(); const report = contextSizeReport(bundle); - assert.match(bundle.context.task, /^(?:M\d+-GAP-\d{5}|WBV2-P\d-\d{3})$/); - assert.match(bundle.context.parentTask, /^(?:M\d+-GAP-\d{5}|WBV2-(?:BASELINE|P\d-\d{3}))$/); + assert.match(bundle.context.task, /^(?:M\d+-GAP-\d{5}|WBV2-P\d+-\d{3})$/); + assert.match(bundle.context.parentTask, /^(?:M\d+-GAP-\d{5}|WBV2-(?:BASELINE|P\d+-\d{3}))$/); assert.equal(bundle.context.parent.manifest.nextTask, bundle.context.task); assert.ok(bundle.context.commands.length >= 1); assert.equal(bundle.context.sourceDocuments.taskCard, `docs/tasks/${bundle.context.task}.md`);