Advance WBV2 domain parity through P12
This commit is contained in:
@@ -13,9 +13,9 @@
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| 里程碑 | WBV2 capability workflow |
|
||||
| 当前任务 | `WBV2-P11-004` |
|
||||
| parent manifest | `tests/golden/WBV2-P11-003/manifest.json` |
|
||||
| 任务卡 | [`tasks/WBV2-P11-004.md`](tasks/WBV2-P11-004.md) |
|
||||
| 当前任务 | `WBV2-P12-005` |
|
||||
| parent manifest | `tests/golden/WBV2-P12-004/manifest.json` |
|
||||
| 任务卡 | [`tasks/WBV2-P12-005.md`](tasks/WBV2-P12-005.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` |
|
||||
|
||||
@@ -10,3 +10,6 @@
|
||||
- nextTask: `NONE`
|
||||
|
||||
The gate emits only engine-bound Chromium claims backed by the compiled Blender native/WASM path. P7/P8/P9 history remains immutable evidence, the authorized provenance baseline is not historical restoration, and the remaining inventory is not silently marked complete. P11-004 is the terminal pointer until a separately authorized continuation is created.
|
||||
- authorized continuation: `WBV2-P12-000`
|
||||
|
||||
Domain expansion may continue under a new manifest root. This does not change P11 evidence or the authorized-rebaseline-only release scope.
|
||||
|
||||
6
docs/status/WBV2-P12-000.md
Normal file
6
docs/status/WBV2-P12-000.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# WBV2-P12-000 status
|
||||
|
||||
- task: `WBV2-P12-000`; parent: `WBV2-P11-004`; status: `done`
|
||||
- nextTask: `WBV2-P12-001`
|
||||
|
||||
Domain expansion is authorized after P11 engine-bound evidence. P12 first builds a conservative capability ledger from existing receipts, then adds scene, authoring, viewport, and non-mesh coverage.
|
||||
9
docs/status/WBV2-P12-001.md
Normal file
9
docs/status/WBV2-P12-001.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# WBV2-P12-001 status
|
||||
|
||||
- task: `WBV2-P12-001`; parent: `WBV2-P12-000`; status: `done`
|
||||
- source manifests batch-scanned: `34`; artifact records: `517`
|
||||
- repeated Blender/Chromium runs: `0`; historical drift manifests recorded: `25`
|
||||
- current engine-bound claims reused: `6`; inventory: `6900` total, `6618` pending, claimed complete: `0`
|
||||
- nextTask: `WBV2-P12-002`
|
||||
|
||||
This ledger reuses existing P1-P6, P10, and P11 manifests as read-only evidence. It records current artifact drift instead of rewriting historical hashes and does not rerun already completed Blender or Chromium checks. Only P10/P11 engine-bound receipts are treated as current engine evidence; the remaining inventory stays explicit.
|
||||
9
docs/status/WBV2-P12-002.md
Normal file
9
docs/status/WBV2-P12-002.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# WBV2-P12-002 status
|
||||
|
||||
- task: `WBV2-P12-002`; parent: `WBV2-P12-001`; status: `done`
|
||||
- visibility transaction: revision +1; hidden object persisted
|
||||
- transform transaction: revision +1; child translation `[0.5, 2.5, 0]` persisted
|
||||
- save/reopen: `EXACT`; stale and malformed commands rejected
|
||||
- nextTask: `WBV2-P12-003`
|
||||
|
||||
The compiled WebEngine WASM Main now has a production-bound scene/object receipt for visibility and transform edits. Existing P2-002 desktop/WASM evidence is reused read-only; no duplicate historical fixture run is required.
|
||||
10
docs/status/WBV2-P12-003.md
Normal file
10
docs/status/WBV2-P12-003.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# WBV2-P12-003 status
|
||||
|
||||
- task: `WBV2-P12-003`; parent: `WBV2-P12-002`; status: `done`
|
||||
- material/UV: `4` Main mutations; Principled values and UV map persisted
|
||||
- animation/TRS: keyframe frame `25` + interpolation `LINEAR`; persisted
|
||||
- save/reopen: `EXACT`; invalid UV and stale frame rejected
|
||||
- existing P3 source receipts reused read-only; no duplicate historical run
|
||||
- nextTask: `WBV2-P12-004`
|
||||
|
||||
The material and animation workflows are now bound to the compiled WebEngine WASM Main in Chromium. Unsupported material nodes remain explicit, and stale or malformed authoring commands do not mutate Main.
|
||||
9
docs/status/WBV2-P12-004.md
Normal file
9
docs/status/WBV2-P12-004.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# WBV2-P12-004 status
|
||||
|
||||
- task: `WBV2-P12-004`; parent: `WBV2-P12-003`; status: `done`
|
||||
- viewport: scene `scene:WBV2P2004ViewportScene`; readback pixels `1024`; resources disposed exact
|
||||
- non-mesh: Curve + Point Cloud binary gates READY; Curve revision `1 -> 2`
|
||||
- unknown data: BLOCKED; malformed Curve edit rejected without revision change
|
||||
- save/reopen: `EXACT`; nextTask: `WBV2-P12-005`
|
||||
|
||||
Existing P2-004 viewport and P4-003 non-mesh source receipts are reused read-only. The production Chromium test binds nonblank viewport readback and bounded non-mesh capability/Curve mutation to the compiled WASM Main, with unsupported data remaining explicit.
|
||||
11
docs/status/WBV2-P12-005.md
Normal file
11
docs/status/WBV2-P12-005.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# WBV2-P12-005 status
|
||||
|
||||
- task: `WBV2-P12-005`; parent: `WBV2-P12-004`; status: `done`
|
||||
- engine-bound domain claims: `6`
|
||||
- P11 claims reused: `3`; P12 new domain claims: `3`
|
||||
- inventory: `6900` total, `6618` pending, claimed complete: `0`
|
||||
- repeated Blender/Chromium validation: `0` for existing receipts
|
||||
- provenance epoch: `2`; release: `AUTHORIZED_REBASELINE_ONLY`; fullHistoricalReproduction: `false`
|
||||
- nextTask: `NONE`
|
||||
|
||||
The domain gate combines the conservative batch ledger with engine-bound Chromium receipts for scene/object, material/animation, and viewport/non-mesh behavior. Existing evidence was reused read-only; only verified domain claims are emitted. The remaining inventory and provenance limitations stay explicit. P12-005 is the terminal pointer until a separately authorized continuation is created.
|
||||
24
docs/tasks/WBV2-P12-000.md
Normal file
24
docs/tasks/WBV2-P12-000.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# WBV2-P12-000: domain expansion continuation root
|
||||
|
||||
- task: WBV2-P12-000
|
||||
- parent: WBV2-P11-004
|
||||
- status: done
|
||||
- gap: workflow:authorize_domain_expansion_continuation
|
||||
- ownerFamily: PROGRAM
|
||||
- targetImplementationClass: LOCAL_BOUNDED
|
||||
|
||||
## 目标
|
||||
|
||||
Authorize the next high-value Blender Web domains after P11 established engine-bound Mesh, Modifier, and Asset evidence. P12 uses existing source receipts first, then adds only bounded native/WASM domain behavior.
|
||||
|
||||
## 验收
|
||||
|
||||
- `node tools/web/generate-wbv2-domain-expansion-root.mjs`
|
||||
- `node tools/web/check-execution-control-plane.mjs`
|
||||
- `node tools/web/check-v2-task-index.mjs`
|
||||
|
||||
## 交付与回滚
|
||||
|
||||
- Reports: `tests/golden/WBV2-P12-000/`
|
||||
- Manifest: `tests/golden/WBV2-P12-000/manifest.json`
|
||||
- Rollback: restore P11-004 as queue parent without rewriting prior evidence.
|
||||
34
docs/tasks/WBV2-P12-001.md
Normal file
34
docs/tasks/WBV2-P12-001.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# WBV2-P12-001: reconcile existing capability ledger
|
||||
|
||||
- task: WBV2-P12-001
|
||||
- parent: WBV2-P12-000
|
||||
- status: in_progress
|
||||
- gap: workflow:reconcile_existing_capability_ledger
|
||||
- ownerFamily: PARITY
|
||||
- targetImplementationClass: LOCAL_BOUNDED
|
||||
|
||||
## 目标
|
||||
|
||||
Aggregate existing WBV2 P1-P6 and P10-P11 manifests into a conservative capability ledger without inventing claims or rewriting historical receipts.
|
||||
|
||||
## 输入与范围
|
||||
|
||||
- Capability matrix: `docs/BLENDER_WASM_CAPABILITY_MATRIX_TEMPLATE.json`
|
||||
- Existing WBV2 manifests: `tests/golden/WBV2-P1-001/manifest.json` through completed domain manifests
|
||||
- P11 gate: `tests/golden/WBV2-P11-004/engine-module-gate-report.json`
|
||||
- Inventory map: `tests/golden/WBV2-P0-002/parity-map.json`
|
||||
|
||||
## 验收
|
||||
|
||||
- `node tools/web/generate-wbv2-capability-ledger.mjs --write`
|
||||
- `node tools/web/check-wbv2-capability-ledger.mjs`
|
||||
- `node tools/web/check-task-context.mjs --task WBV2-P12-001 --write`
|
||||
|
||||
Malformed manifest, hash drift, unsupported evidence status, false parity claim, or inventory over-claim must keep in_progress and must not advance nextTask.
|
||||
|
||||
## 交付与回滚
|
||||
|
||||
- Reports: `tests/golden/WBV2-P12-001/`
|
||||
- Status: `docs/status/WBV2-P12-001.md`
|
||||
- Manifest: `tests/golden/WBV2-P12-001/manifest.json`
|
||||
- Rollback: restore P12-000 as queue parent; preserve all source manifests.
|
||||
33
docs/tasks/WBV2-P12-002.md
Normal file
33
docs/tasks/WBV2-P12-002.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# WBV2-P12-002: scene and object engine receipt
|
||||
|
||||
- task: WBV2-P12-002
|
||||
- parent: WBV2-P12-001
|
||||
- status: in_progress
|
||||
- gap: workflow:scene_object_workflow_engine_receipt
|
||||
- ownerFamily: EDITOR
|
||||
- targetImplementationClass: LOCAL_EXACT
|
||||
|
||||
## 目标
|
||||
|
||||
Bind object visibility and transform edits to the compiled WebEngine WASM Main with save/reopen and revision guards.
|
||||
|
||||
## 输入与范围
|
||||
|
||||
- Scene fixture: `tests/files/web/generated/WBV2-P2-002-OBJECT.TRANSFORM_HIERARCHY.blend`
|
||||
- Source oracle: `tests/golden/WBV2-P2-002/object-transform-report.json`
|
||||
- Client: `web/app/src/engine-client/WebEngineClient.ts`
|
||||
|
||||
## 验收
|
||||
|
||||
- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-scene-object-production.spec.ts`
|
||||
- `node tools/web/generate-wbv2-scene-object-receipt.mjs --write`
|
||||
- `node tools/web/check-task-context.mjs --task WBV2-P12-002 --write`
|
||||
|
||||
Malformed, stale, locked, cycle, unsupported, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.
|
||||
|
||||
## 交付与回滚
|
||||
|
||||
- Reports: `tests/golden/WBV2-P12-002/`
|
||||
- Status: `docs/status/WBV2-P12-002.md`
|
||||
- Manifest: `tests/golden/WBV2-P12-002/manifest.json`
|
||||
- Rollback: restore P12-001 as queue parent.
|
||||
33
docs/tasks/WBV2-P12-003.md
Normal file
33
docs/tasks/WBV2-P12-003.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# WBV2-P12-003: material and animation engine receipt
|
||||
|
||||
- task: WBV2-P12-003
|
||||
- parent: WBV2-P12-002
|
||||
- status: in_progress
|
||||
- gap: workflow:material_animation_engine_receipt
|
||||
- ownerFamily: AUTHORING
|
||||
- targetImplementationClass: LOCAL_EXACT
|
||||
|
||||
## 目标
|
||||
|
||||
Bind material Principled/texture and TRS keyframe edits to the compiled WebEngine WASM Main.
|
||||
|
||||
## 输入与范围
|
||||
|
||||
- Material fixture: `tests/files/web/generated/WBV2-P3-001-MATERIAL.PBR_UV.blend`
|
||||
- Animation fixture: `tests/files/web/generated/WBV2-P3-002-ANIMATION.TRS_ACTION.blend`
|
||||
- Existing reports: `tests/golden/WBV2-P3-001/material-report.json`, `tests/golden/WBV2-P3-002/animation-report.json`
|
||||
|
||||
## 验收
|
||||
|
||||
- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-material-animation-production.spec.ts`
|
||||
- `node tools/web/generate-wbv2-material-animation-receipt.mjs --write`
|
||||
- `node tools/web/check-task-context.mjs --task WBV2-P12-003 --write`
|
||||
|
||||
Malformed graph, unsupported node, stale frame, missing image, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.
|
||||
|
||||
## 交付与回滚
|
||||
|
||||
- Reports: `tests/golden/WBV2-P12-003/`
|
||||
- Status: `docs/status/WBV2-P12-003.md`
|
||||
- Manifest: `tests/golden/WBV2-P12-003/manifest.json`
|
||||
- Rollback: restore P12-002 as queue parent.
|
||||
33
docs/tasks/WBV2-P12-004.md
Normal file
33
docs/tasks/WBV2-P12-004.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# WBV2-P12-004: viewport and non-mesh engine receipt
|
||||
|
||||
- task: WBV2-P12-004
|
||||
- parent: WBV2-P12-003
|
||||
- status: in_progress
|
||||
- gap: workflow:viewport_nonmesh_engine_receipt
|
||||
- ownerFamily: VIEWPORT
|
||||
- targetImplementationClass: LOCAL_BOUNDED
|
||||
|
||||
## 目标
|
||||
|
||||
Bind viewport SceneIR and bounded non-mesh read/edit paths to the compiled WebEngine runtime with explicit unsupported boundaries.
|
||||
|
||||
## 输入与范围
|
||||
|
||||
- Viewport report: `tests/golden/WBV2-P2-004/viewport-report.json`
|
||||
- Non-mesh report: `tests/golden/WBV2-P4-003/sculpt-report.json`
|
||||
- WebEngine client: `web/app/src/engine-client/WebEngineClient.ts`
|
||||
|
||||
## 验收
|
||||
|
||||
- `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-viewport-nonmesh-production.spec.ts`
|
||||
- `node tools/web/generate-wbv2-viewport-nonmesh-receipt.mjs --write`
|
||||
- `node tools/web/check-task-context.mjs --task WBV2-P12-004 --write`
|
||||
|
||||
Unsupported data, malformed geometry, budget overflow, device loss, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.
|
||||
|
||||
## 交付与回滚
|
||||
|
||||
- Reports: `tests/golden/WBV2-P12-004/`
|
||||
- Status: `docs/status/WBV2-P12-004.md`
|
||||
- Manifest: `tests/golden/WBV2-P12-004/manifest.json`
|
||||
- Rollback: restore P12-003 as queue parent.
|
||||
33
docs/tasks/WBV2-P12-005.md
Normal file
33
docs/tasks/WBV2-P12-005.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# WBV2-P12-005: domain parity gate
|
||||
|
||||
- task: WBV2-P12-005
|
||||
- parent: WBV2-P12-004
|
||||
- status: in_progress
|
||||
- gap: workflow:recompute_domain_parity_gate
|
||||
- ownerFamily: RELEASE
|
||||
- targetImplementationClass: LOCAL_BOUNDED
|
||||
|
||||
## 目标
|
||||
|
||||
Recompute domain parity from P10-P12 receipts while retaining explicit inventory and provenance limits.
|
||||
|
||||
## 输入与范围
|
||||
|
||||
- Capability ledger: `tests/golden/WBV2-P12-001/capability-ledger-report.json`
|
||||
- P11 gate: `tests/golden/WBV2-P11-004/engine-module-gate-report.json`
|
||||
- P12 domain receipts
|
||||
- Provenance approval: `docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json`
|
||||
|
||||
## 验收
|
||||
|
||||
- `node tools/web/generate-wbv2-domain-parity-gate.mjs --write`
|
||||
- `node tools/web/check-task-context.mjs --task WBV2-P12-005 --write`
|
||||
|
||||
Missing receipt, hash drift, false inventory completion, unsupported browser, undeclared claim, or false historical reproduction must keep in_progress and must not advance nextTask.
|
||||
|
||||
## 交付与回滚
|
||||
|
||||
- Reports: `tests/golden/WBV2-P12-005/`
|
||||
- Status: `docs/status/WBV2-P12-005.md`
|
||||
- Manifest: `tests/golden/WBV2-P12-005/manifest.json`
|
||||
- Rollback: restore P12-004 as queue parent.
|
||||
@@ -240,12 +240,12 @@ Recorded: 2026-08-22 America/New_York
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Current task when this file was written | `WBV2-P11-004` |
|
||||
| Current task when this file was written | `WBV2-P12-005` |
|
||||
| Current task state | `done` |
|
||||
| Parent manifest | `tests/golden/WBV2-P11-003/manifest.json` |
|
||||
| Current task card | `docs/tasks/WBV2-P11-004.md` |
|
||||
| Parent manifest | `tests/golden/WBV2-P12-004/manifest.json` |
|
||||
| Current task card | `docs/tasks/WBV2-P12-005.md` |
|
||||
| Current task-context nextTask | `NONE` |
|
||||
| Focused command | `node tools/web/generate-wbv2-engine-module-gate.mjs --write` |
|
||||
| Focused command | `node tools/web/generate-wbv2-domain-parity-gate.mjs --write` |
|
||||
|
||||
The snapshot is informational and may become stale. On every resume, the queue,
|
||||
parent manifest, and fresh `print-task-context` output win. Never infer a task
|
||||
|
||||
@@ -92,7 +92,8 @@
|
||||
"authorizedRebaselineOnly": true,
|
||||
"claimsEvidenceBound": true,
|
||||
"inventoryRemainderExplicit": true,
|
||||
"terminalQueuePointer": true
|
||||
"terminalQueuePointer": false,
|
||||
"authorizedContinuation": "WBV2-P12-000"
|
||||
},
|
||||
"nextTask": null
|
||||
"nextTask": "WBV2-P12-000"
|
||||
}
|
||||
|
||||
@@ -58,11 +58,11 @@
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P11-004/engine-module-gate-report.json",
|
||||
"sha256": "eec3f9efd085c3ff79ea502e334f297567ae6399194866addffcc703bc9579ab"
|
||||
"sha256": "9b549cd365f8719ee48b075801e897d04df660929ac4bd7e1325a6b4b4646280"
|
||||
},
|
||||
"status": {
|
||||
"path": "docs/status/WBV2-P11-004.md",
|
||||
"sha256": "a834a3b63eef1611f35b93c4d6ff38fae2a45ff523ecebc005ee466ff5afc546"
|
||||
"sha256": "f777ef61b9c46e0bdfaca81aca3c62059c5438547214eaa3545f54aec65122d0"
|
||||
},
|
||||
"parityPlan": {
|
||||
"path": "tests/golden/WBV2-P11-004/module-expansion-task-plan.json",
|
||||
@@ -70,7 +70,7 @@
|
||||
},
|
||||
"taskContext": {
|
||||
"path": "tests/golden/WBV2-P11-004/task-context.json",
|
||||
"sha256": "bc6e68dd107bf143c8421b4ff165b01323bd18277f9e70b5c81dbc56ddbed4df"
|
||||
"sha256": "87805ebd4fbda1dd03d8c82753df10f01fdd3a396e3ea2379f0dffa36005cc25"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
@@ -86,5 +86,10 @@
|
||||
"fullHistoricalReproduction": false,
|
||||
"deterministic": true
|
||||
},
|
||||
"nextTask": null
|
||||
"nextTask": "WBV2-P12-000",
|
||||
"continuation": {
|
||||
"authorized": true,
|
||||
"root": "WBV2-P12-000",
|
||||
"scope": "DOMAIN_EXPANSION"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
"provenance epoch 2 remains authorized rebaseline only",
|
||||
"full historical reproduction remains false"
|
||||
],
|
||||
"nextTask": null,
|
||||
"nextTask": "WBV2-P12-000",
|
||||
"sourceDocuments": {
|
||||
"queue": "docs/EXECUTION_QUEUE.md",
|
||||
"taskCard": "docs/tasks/WBV2-P11-004.md",
|
||||
@@ -171,7 +171,7 @@
|
||||
"totalTokens": 2113,
|
||||
"reservedEnvelopeTokens": 1024,
|
||||
"estimatedContextTokens": 3137,
|
||||
"serializedContextTokens": 686,
|
||||
"serializedContextTokens": 689,
|
||||
"withinBudget": true
|
||||
}
|
||||
}
|
||||
|
||||
35
tests/golden/WBV2-P12-000/domain-expansion-root-report.json
Normal file
35
tests/golden/WBV2-P12-000/domain-expansion-root-report.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-000",
|
||||
"operation": "AUTHORIZE_DOMAIN_EXPANSION_CONTINUATION",
|
||||
"status": "PASS",
|
||||
"parent": {
|
||||
"task": "WBV2-P11-004",
|
||||
"manifest": "tests/golden/WBV2-P11-004/manifest.json",
|
||||
"manifestSha256": "e82ded5f31024e250bc14de9997b2869471ccda5f1fc15c24f593c1f47f79c11",
|
||||
"previousDecision": "READY_WITH_ENGINE_MODULE_PARITY",
|
||||
"fullHistoricalReproduction": false
|
||||
},
|
||||
"continuation": {
|
||||
"root": "WBV2-P12-000",
|
||||
"firstTask": "WBV2-P12-001",
|
||||
"plannedTasks": 6,
|
||||
"scope": [
|
||||
"CAPABILITY_LEDGER",
|
||||
"SCENE_OBJECT",
|
||||
"MATERIAL_ANIMATION",
|
||||
"VIEWPORT_NONMESH",
|
||||
"DOMAIN_GATE"
|
||||
],
|
||||
"browser": "chromium",
|
||||
"nativeEngineAlreadyBound": true
|
||||
},
|
||||
"policy": {
|
||||
"historicalEvidencePreserved": true,
|
||||
"authorizedRebaselineOnly": true,
|
||||
"ledgerClaimsConservative": true,
|
||||
"fullHistoricalReproduction": false,
|
||||
"inventoryRemainderExplicit": true
|
||||
},
|
||||
"nextTask": "WBV2-P12-001"
|
||||
}
|
||||
1895
tests/golden/WBV2-P12-000/domain-expansion-task-plan.json
Normal file
1895
tests/golden/WBV2-P12-000/domain-expansion-task-plan.json
Normal file
File diff suppressed because it is too large
Load Diff
57
tests/golden/WBV2-P12-000/manifest.json
Normal file
57
tests/golden/WBV2-P12-000/manifest.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-000",
|
||||
"parentTask": "WBV2-P11-004",
|
||||
"operation": "AUTHORIZE_DOMAIN_EXPANSION_CONTINUATION",
|
||||
"status": "done",
|
||||
"enablingTask": true,
|
||||
"parityStateChange": false,
|
||||
"artifacts": {
|
||||
"parentManifest": {
|
||||
"path": "tests/golden/WBV2-P11-004/manifest.json",
|
||||
"sha256": "3da220443dcac4bc85a2e9e2052575d01b07e6ac3006073e153c8f39e0b0a04c"
|
||||
},
|
||||
"parentReport": {
|
||||
"path": "tests/golden/WBV2-P11-004/engine-module-gate-report.json",
|
||||
"sha256": "9b549cd365f8719ee48b075801e897d04df660929ac4bd7e1325a6b4b4646280"
|
||||
},
|
||||
"approval": {
|
||||
"path": "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json",
|
||||
"sha256": "cffc869734af94ffe6b8b8004d7ab8cc2c9edcb85ec2a877548e0b0f923f5ea3"
|
||||
},
|
||||
"plan": {
|
||||
"path": "tests/golden/WBV2-P12-000/domain-expansion-task-plan.json",
|
||||
"sha256": "ac21b0b65eed889928c5209738215584464157b4c5db16c95ba8d2ff1f26d8d5"
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P12-000/domain-expansion-root-report.json",
|
||||
"sha256": "01198bce36faeed9325806fdf3d746b47685fb9e12f4f26cc6afca9bc4e3dc9b"
|
||||
},
|
||||
"rootCard": {
|
||||
"path": "docs/tasks/WBV2-P12-000.md",
|
||||
"sha256": "eccb11ca775c1fa6d49b250ab862fbc112a62e87cf21288fe7d5deb91df9e046"
|
||||
},
|
||||
"rootStatus": {
|
||||
"path": "docs/status/WBV2-P12-000.md",
|
||||
"sha256": "0c6daef899020692f94be43c8a38aca5fc63e805672d21365e104f5237ca5e6c"
|
||||
},
|
||||
"activeCard": {
|
||||
"path": "docs/tasks/WBV2-P12-001.md",
|
||||
"sha256": "1867030428e4da7dfdd76a97374affb91a40faf45abd2581a59d95c2c0021881"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"p11EvidencePreserved": true,
|
||||
"existingSourceEvidenceReusable": true,
|
||||
"nativeEngineAlreadyBound": true,
|
||||
"authorizedRebaselineOnly": true,
|
||||
"fullHistoricalReproduction": false,
|
||||
"domainScope": [
|
||||
"CAPABILITY_LEDGER",
|
||||
"SCENE_OBJECT",
|
||||
"MATERIAL_ANIMATION",
|
||||
"VIEWPORT_NONMESH"
|
||||
]
|
||||
},
|
||||
"nextTask": "WBV2-P12-001"
|
||||
}
|
||||
37
tests/golden/WBV2-P12-001/capability-ledger-report.json
Normal file
37
tests/golden/WBV2-P12-001/capability-ledger-report.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-001",
|
||||
"operation": "RECONCILE_EXISTING_CAPABILITY_LEDGER",
|
||||
"status": "PASS",
|
||||
"ledgerSha256": "44e144229708db8d1f2b35ec8cd6851bf9d91185a1a04267f4ffcd7abc2c60ba",
|
||||
"sourceIndex": "tests/golden/WBV2-P12-001/source-manifest-index.json",
|
||||
"sourceIndexSha256": "879a13d14bf4d502229f14927c58b417e07b562309bf3def563ac7baee95d739",
|
||||
"inventory": {
|
||||
"source": "tests/golden/WBV2-P0-002/parity-map.json",
|
||||
"sourceSha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8",
|
||||
"total": 6900,
|
||||
"pending": 6618,
|
||||
"claimedComplete": 0,
|
||||
"remainderExplicit": true
|
||||
},
|
||||
"summary": {
|
||||
"manifestsDone": 34,
|
||||
"artifactRecords": 517,
|
||||
"historicalDriftManifests": 25,
|
||||
"currentEngineBoundManifests": 2,
|
||||
"missingArtifacts": 0
|
||||
},
|
||||
"reuse": {
|
||||
"existingManifestsRead": 34,
|
||||
"repeatedBlenderRuns": 0,
|
||||
"repeatedChromiumRuns": 0,
|
||||
"newProductionClaims": 0,
|
||||
"engineBoundClaimsReused": 6
|
||||
},
|
||||
"driftPolicy": {
|
||||
"historicalReportsUntouched": true,
|
||||
"currentArtifactDriftRecorded": true,
|
||||
"noHistoricalHashRewrite": true
|
||||
},
|
||||
"nextTask": "WBV2-P12-002"
|
||||
}
|
||||
4100
tests/golden/WBV2-P12-001/capability-ledger.json
Normal file
4100
tests/golden/WBV2-P12-001/capability-ledger.json
Normal file
File diff suppressed because it is too large
Load Diff
1895
tests/golden/WBV2-P12-001/domain-expansion-task-plan.json
Normal file
1895
tests/golden/WBV2-P12-001/domain-expansion-task-plan.json
Normal file
File diff suppressed because it is too large
Load Diff
65
tests/golden/WBV2-P12-001/manifest.json
Normal file
65
tests/golden/WBV2-P12-001/manifest.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-001",
|
||||
"parentTask": "WBV2-P12-000",
|
||||
"operation": "RECONCILE_EXISTING_CAPABILITY_LEDGER",
|
||||
"status": "done",
|
||||
"enablingTask": true,
|
||||
"parityStateChange": false,
|
||||
"runtime": "READ_ONLY_MANIFEST_BATCH_SCAN",
|
||||
"artifacts": {
|
||||
"parentManifest": {
|
||||
"path": "tests/golden/WBV2-P12-000/manifest.json",
|
||||
"sha256": "1bdf18ca124a46752303324afd73eea13f08ffd36aedcbb239657cbe712a7333"
|
||||
},
|
||||
"inventory": {
|
||||
"path": "tests/golden/WBV2-P0-002/parity-map.json",
|
||||
"sha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8"
|
||||
},
|
||||
"sourceIndex": {
|
||||
"path": "tests/golden/WBV2-P12-001/source-manifest-index.json",
|
||||
"sha256": "879a13d14bf4d502229f14927c58b417e07b562309bf3def563ac7baee95d739"
|
||||
},
|
||||
"ledger": {
|
||||
"path": "tests/golden/WBV2-P12-001/capability-ledger.json",
|
||||
"sha256": "44e144229708db8d1f2b35ec8cd6851bf9d91185a1a04267f4ffcd7abc2c60ba"
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P12-001/capability-ledger-report.json",
|
||||
"sha256": "5c41a84564f78bb8e78a988f0445b06eaf1b3d0af8c59cdb216d0e79b0d46414"
|
||||
},
|
||||
"generator": {
|
||||
"path": "tools/web/generate-wbv2-capability-ledger.mjs",
|
||||
"sha256": "79dd1fe6a0c23155be9eab330f8a5a286f53e69c62a6f90b5e42870c2aff307d"
|
||||
},
|
||||
"checker": {
|
||||
"path": "tools/web/check-wbv2-capability-ledger.mjs",
|
||||
"sha256": "783e268eb5b44a926e552bb1e06f0f944f2e9fa6ba2879b3523cd1911ad5e70d"
|
||||
},
|
||||
"parityPlan": {
|
||||
"path": "tests/golden/WBV2-P12-001/domain-expansion-task-plan.json",
|
||||
"sha256": "a2eb22c8b6f6e541c5ae071db6c661e54823d6e351bc1377bb45acf62ac28688"
|
||||
},
|
||||
"status": {
|
||||
"path": "docs/status/WBV2-P12-001.md",
|
||||
"sha256": "0eac94a00dafc40ee1a03296834a15ebfcc39210f587afa82402be0637b55782"
|
||||
},
|
||||
"taskContext": {
|
||||
"path": "tests/golden/WBV2-P12-001/task-context.json",
|
||||
"sha256": "21e144b3f9b86d2d62066fe5e40b8c85c6e9095980b154e68aa81e13c54f6642"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"sourceManifests": 34,
|
||||
"artifactRecords": 517,
|
||||
"repeatedBlenderRuns": 0,
|
||||
"repeatedChromiumRuns": 0,
|
||||
"historicalDriftExplicit": true,
|
||||
"currentEngineBoundClaimsReused": 6,
|
||||
"inventoryTotal": 6900,
|
||||
"inventoryPending": 6618,
|
||||
"inventoryClaimedComplete": 0,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-002"
|
||||
}
|
||||
348
tests/golden/WBV2-P12-001/source-manifest-index.json
Normal file
348
tests/golden/WBV2-P12-001/source-manifest-index.json
Normal file
@@ -0,0 +1,348 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-001",
|
||||
"operation": "SOURCE_MANIFEST_BATCH_INDEX",
|
||||
"policy": "read_only_batch_scan_no_repeated_execution",
|
||||
"entries": [
|
||||
{
|
||||
"task": "WBV2-P1-001",
|
||||
"manifest": "tests/golden/WBV2-P1-001/manifest.json",
|
||||
"manifestSha256": "b40c32066ac0667729465568135edde25d8ca94f97d74b613efb94acc8a4b75d",
|
||||
"status": "done",
|
||||
"operation": "RUNTIME_VARIANTS_SOURCE_RECEIPTS_LOCAL_BOUNDED",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P1-002",
|
||||
"manifest": "tests/golden/WBV2-P1-002/manifest.json",
|
||||
"manifestSha256": "456b93a29ae0ce65e1490e688e5a8563fbe4ba57ac104814f344ad6e7c2ec668",
|
||||
"status": "done",
|
||||
"operation": "SCENEIR_STABLE_IDS_BINARY_DELTAS_LOCAL_EXACT",
|
||||
"artifactCount": 13,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P1-003",
|
||||
"manifest": "tests/golden/WBV2-P1-003/manifest.json",
|
||||
"manifestSha256": "bcdd4835ddc3f668419f6f5d505e010a7404d3c129bf85f99f587daa648f2ae1",
|
||||
"status": "done",
|
||||
"operation": "MAIN_TRANSACTION_HISTORY_SAVE_LOCAL_EXACT",
|
||||
"artifactCount": 13,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P1-004",
|
||||
"manifest": "tests/golden/WBV2-P1-004/manifest.json",
|
||||
"manifestSha256": "19d9cbcf2455df8ffad49907b1765aeab45d865bd33a5771ed16a153b29887a1",
|
||||
"status": "done",
|
||||
"operation": "WORKER_CANCEL_RESTART_DISPOSE_LOCAL_BOUNDED",
|
||||
"artifactCount": 15,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P1-005",
|
||||
"manifest": "tests/golden/WBV2-P1-005/manifest.json",
|
||||
"manifestSha256": "cb22c9c218ffcac0fd45527817eb864dbaf8f677e9b18775275f2f0fc8aa302d",
|
||||
"status": "done",
|
||||
"operation": "STORAGE_JOURNAL_RECOVERY_LOCAL_BOUNDED",
|
||||
"artifactCount": 15,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P2-001",
|
||||
"manifest": "tests/golden/WBV2-P2-001/manifest.json",
|
||||
"manifestSha256": "ad6d73ac457d20f95fd080fcdacc38049d2ce9faa8c56f325f9f7f22074d1cb5",
|
||||
"status": "done",
|
||||
"operation": "EDITOR_OPEN_SCENE_LOCAL_EXACT",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P2-002",
|
||||
"manifest": "tests/golden/WBV2-P2-002/manifest.json",
|
||||
"manifestSha256": "fa65312256f556ce80609206e266f7fc3ccbeda34eae3da179040f8e80dd017c",
|
||||
"status": "done",
|
||||
"operation": "OBJECT_TRANSFORM_HIERARCHY_LOCAL_EXACT",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P2-003",
|
||||
"manifest": "tests/golden/WBV2-P2-003/manifest.json",
|
||||
"manifestSha256": "79ebc20719fef2b60a3457bca25dac98e755a2f2c1bd3c35361527509a91a987",
|
||||
"status": "done",
|
||||
"operation": "MESH_EDIT_CORE_LOCAL_EXACT",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P2-004",
|
||||
"manifest": "tests/golden/WBV2-P2-004/manifest.json",
|
||||
"manifestSha256": "9a511f9620bdc886ab4684ac449dcaa156086cde76c0b95d16795f0f51a304f2",
|
||||
"status": "done",
|
||||
"operation": "VIEWPORT_MAIN_OFFSCREEN_LOCAL_BOUNDED",
|
||||
"artifactCount": 20,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P2-005",
|
||||
"manifest": "tests/golden/WBV2-P2-005/manifest.json",
|
||||
"manifestSha256": "284eda53bb4191da68a30b4fcb8e02801cb83299864846f7e52875f4d976b7be",
|
||||
"status": "done",
|
||||
"operation": "WORKFLOW_P0_USER_LOOP_LOCAL_BOUNDED",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P3-001",
|
||||
"manifest": "tests/golden/WBV2-P3-001/manifest.json",
|
||||
"manifestSha256": "e3b037fdcf55b5e64fd770c6fa90d0b72e96b3e764a305df0ceee378fa167191",
|
||||
"status": "done",
|
||||
"operation": "MATERIAL_PBR_UV_LOCAL_BOUNDED",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P3-002",
|
||||
"manifest": "tests/golden/WBV2-P3-002/manifest.json",
|
||||
"manifestSha256": "cc36b933a2b6d817ea7226c07d0617ecdf2f89575136a83cb15de4e7c8f59188",
|
||||
"status": "done",
|
||||
"operation": "ANIMATION_TRS_ACTION_LOCAL_EXACT",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P3-003",
|
||||
"manifest": "tests/golden/WBV2-P3-003/manifest.json",
|
||||
"manifestSha256": "1b97d2ca9add58a6185a21137729edc4c8b11a2d21be1682793e3d05b9ef9011",
|
||||
"status": "done",
|
||||
"operation": "RIG_POSE_SKIN_LOCAL_BOUNDED",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P3-004",
|
||||
"manifest": "tests/golden/WBV2-P3-004/manifest.json",
|
||||
"manifestSha256": "bb4f2783eaa78a0104045048fc9f5d925a78e5a2539f5f1b9e699a067d05fa27",
|
||||
"status": "done",
|
||||
"operation": "IO_GLB_ROUNDTRIP_LOCAL_EXACT",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P3-005",
|
||||
"manifest": "tests/golden/WBV2-P3-005/manifest.json",
|
||||
"manifestSha256": "42dc02d198630c2735c5a0a1beab37f2a98ff0233927215099f67606d248c39e",
|
||||
"status": "done",
|
||||
"operation": "ASSET_LIBRARY_APPEND_LINK_OVERRIDE_LOCAL_BOUNDED",
|
||||
"artifactCount": 15,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P4-001",
|
||||
"manifest": "tests/golden/WBV2-P4-001/manifest.json",
|
||||
"manifestSha256": "6f1bee73c987f5e66733feb03d1d708e0f2dbd0776ac6634dbf694cde385143c",
|
||||
"status": "done",
|
||||
"operation": "MODIFIER_DECLARED_SLICES_LOCAL_BOUNDED",
|
||||
"artifactCount": 16,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P4-002",
|
||||
"manifest": "tests/golden/WBV2-P4-002/manifest.json",
|
||||
"manifestSha256": "2b9e907fa11470b354bbb98695696bcdfae5c654ef03373b1eb2230098f28142",
|
||||
"status": "done",
|
||||
"operation": "NODES_ALLOWLIST_LOCAL_BOUNDED",
|
||||
"artifactCount": 19,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P4-003",
|
||||
"manifest": "tests/golden/WBV2-P4-003/manifest.json",
|
||||
"manifestSha256": "9c41ef52263d544650b1bad2dc2ec5f40ed63a9ab1b9732492a46672384e1218",
|
||||
"status": "done",
|
||||
"operation": "SCULPT_NONMESH_PAINT_BOUNDED_LOCAL_BOUNDED",
|
||||
"artifactCount": 18,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P4-004",
|
||||
"manifest": "tests/golden/WBV2-P4-004/manifest.json",
|
||||
"manifestSha256": "c6c18a2cf7cfb39fce5718d3e68c7f358329ff8afc2d89d9a6eda7485fd3d016",
|
||||
"status": "done",
|
||||
"operation": "SIMULATION_CACHE_IDENTITY_LIFECYCLE_LOCAL_BOUNDED",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P5-001",
|
||||
"manifest": "tests/golden/WBV2-P5-001/manifest.json",
|
||||
"manifestSha256": "b3f1a8b56649d8fa386cbc3f00996e98ce7e4104604731da9af43dea65467d4e",
|
||||
"status": "done",
|
||||
"operation": "RENDER_CAPABILITY_ROUTING_LOCAL_BOUNDED",
|
||||
"artifactCount": 19,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P5-002",
|
||||
"manifest": "tests/golden/WBV2-P5-002/manifest.json",
|
||||
"manifestSha256": "70d8fb89a3ddbf02d1128a4efbb76931c17045d7d223aa1e72106366491dbed2",
|
||||
"status": "done",
|
||||
"operation": "MEDIA_BOUNDED_WORKFLOW_LOCAL_BOUNDED",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 3,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P5-003",
|
||||
"manifest": "tests/golden/WBV2-P5-003/manifest.json",
|
||||
"manifestSha256": "86fbc8da2b02c1ed595c6d0bdf90f9dd4697def63349c0729edbd9c2bd77a25c",
|
||||
"status": "done",
|
||||
"operation": "SERVER_JOB_RESULT_BINDING_SERVER_EXACT",
|
||||
"artifactCount": 19,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P6-001",
|
||||
"manifest": "tests/golden/WBV2-P6-001/manifest.json",
|
||||
"manifestSha256": "e8bb64d618b630b34292501d44fe46c55de3a57ddf0fccb4b7974c6a479456a4",
|
||||
"status": "done",
|
||||
"operation": "SECURITY_SCRIPTING_LOCAL_EXACT",
|
||||
"artifactCount": 16,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P6-002",
|
||||
"manifest": "tests/golden/WBV2-P6-002/manifest.json",
|
||||
"manifestSha256": "b66e193b81c0c592964c874902d0ee024c4877610fd7fa92aee2a961f69d01ba",
|
||||
"status": "done",
|
||||
"operation": "PERFORMANCE_FAULT_RECOVERY_MATRIX_LOCAL_EXACT",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 4,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P6-003",
|
||||
"manifest": "tests/golden/WBV2-P6-003/manifest.json",
|
||||
"manifestSha256": "22a773feb29435ec0c29eaa720e7ae39c5f87455c678b78ae6c02b4985fea54d",
|
||||
"status": "done",
|
||||
"operation": "OFFLINE_CI_SBOM_ROLLBACK_RELEASE_LOCAL_EXACT",
|
||||
"artifactCount": 18,
|
||||
"currentDriftCount": 6,
|
||||
"evidenceClass": "HISTORICAL_DRIFT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P10-000",
|
||||
"manifest": "tests/golden/WBV2-P10-000/manifest.json",
|
||||
"manifestSha256": "269acf27b93097887e8b475b53fbbfae4c7d9c653dd4b6c5921258db86576de0",
|
||||
"status": "done",
|
||||
"operation": "AUTHORIZE_NATIVE_ENGINE_PARITY_CONTINUATION",
|
||||
"artifactCount": 8,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P10-001",
|
||||
"manifest": "tests/golden/WBV2-P10-001/manifest.json",
|
||||
"manifestSha256": "200ad417f44414b25c2b431fd6e7ff2c98c59e23871a7220facd92f295f1cd8d",
|
||||
"status": "done",
|
||||
"operation": "RECONCILE_WBV2_INVENTORY_SOURCE_DRIFT",
|
||||
"artifactCount": 13,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P10-002",
|
||||
"manifest": "tests/golden/WBV2-P10-002/manifest.json",
|
||||
"manifestSha256": "dcf016adce463066fad68a0e9cf2a23a81b0d148afeb05b0e523263bd2b91da3",
|
||||
"status": "done",
|
||||
"operation": "NATIVE_WASM_ENGINE_PRODUCTION_RECEIPT",
|
||||
"artifactCount": 17,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "ENGINE_BOUND_EXACT"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P10-003",
|
||||
"manifest": "tests/golden/WBV2-P10-003/manifest.json",
|
||||
"manifestSha256": "5c0ce2665b5509e8c9551164c463c60d8e89b5bf13a596980321bdb343dd2c8d",
|
||||
"status": "done",
|
||||
"operation": "CORE_MODULE_OPERATOR_MATRIX_RECEIPT",
|
||||
"artifactCount": 12,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P11-000",
|
||||
"manifest": "tests/golden/WBV2-P11-000/manifest.json",
|
||||
"manifestSha256": "2eb9bb41f116f13b019bda76545dfce6739cbc5940a22f40cc26e8571ddad6ff",
|
||||
"status": "done",
|
||||
"operation": "AUTHORIZE_MODULE_EXPANSION_CONTINUATION",
|
||||
"artifactCount": 8,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P11-001",
|
||||
"manifest": "tests/golden/WBV2-P11-001/manifest.json",
|
||||
"manifestSha256": "e08a02819065f1e7bc72a3bfae99e768c502dfa90af4b0614a701e7cca88b576",
|
||||
"status": "done",
|
||||
"operation": "MESH_TOPOLOGY_OPERATION_FAMILY_RECEIPT",
|
||||
"artifactCount": 13,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P11-002",
|
||||
"manifest": "tests/golden/WBV2-P11-002/manifest.json",
|
||||
"manifestSha256": "32b9581bc0ef2cd3435a17c3b7d454ae5327ef8f0ac4c1916e9a0857eb42aaf1",
|
||||
"status": "done",
|
||||
"operation": "MODIFIER_PARAMETER_APPLY_FAMILY_RECEIPT",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P11-003",
|
||||
"manifest": "tests/golden/WBV2-P11-003/manifest.json",
|
||||
"manifestSha256": "da4c9414baaaab9a47c6cc6af66426450c640a99d781e4c0273e0189a72c047c",
|
||||
"status": "done",
|
||||
"operation": "ASSET_LINK_OVERRIDE_RELOAD_FAMILY_RECEIPT",
|
||||
"artifactCount": 14,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "EXACT_RECORDED"
|
||||
},
|
||||
{
|
||||
"task": "WBV2-P11-004",
|
||||
"manifest": "tests/golden/WBV2-P11-004/manifest.json",
|
||||
"manifestSha256": "3da220443dcac4bc85a2e9e2052575d01b07e6ac3006073e153c8f39e0b0a04c",
|
||||
"status": "done",
|
||||
"operation": "RECOMPUTE_ENGINE_MODULE_PARITY_GATE",
|
||||
"artifactCount": 16,
|
||||
"currentDriftCount": 0,
|
||||
"evidenceClass": "ENGINE_BOUND_EXACT"
|
||||
}
|
||||
]
|
||||
}
|
||||
180
tests/golden/WBV2-P12-001/task-context.json
Normal file
180
tests/golden/WBV2-P12-001/task-context.json
Normal file
@@ -0,0 +1,180 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-001",
|
||||
"parentTask": "WBV2-P12-000",
|
||||
"status": "in_progress",
|
||||
"goal": "Aggregate existing WBV2 P1-P6 and P10-P11 manifests into a conservative capability ledger without inventing claims or rewriting historical receipts.",
|
||||
"scope": {
|
||||
"gap": "workflow:reconcile_existing_capability_ledger",
|
||||
"ownerFamily": "PARITY",
|
||||
"implementationClass": "LOCAL_BOUNDED"
|
||||
},
|
||||
"commands": [
|
||||
"node tools/web/generate-wbv2-capability-ledger.mjs --write",
|
||||
"node tools/web/check-wbv2-capability-ledger.mjs",
|
||||
"node tools/web/check-task-context.mjs --task WBV2-P12-001 --write"
|
||||
],
|
||||
"inputPaths": [
|
||||
"tests/golden/WBV2-P1-001/manifest.json"
|
||||
],
|
||||
"inputSelection": {
|
||||
"schemaVersion": 1,
|
||||
"limits": {
|
||||
"maxFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextRemainingBytes": 3507,
|
||||
"contextRemainingTokens": 875
|
||||
},
|
||||
"source": {
|
||||
"bytes": 6397,
|
||||
"tokens": 1601
|
||||
},
|
||||
"selected": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P1-001/manifest.json",
|
||||
"bytes": 2740,
|
||||
"tokens": 685
|
||||
}
|
||||
],
|
||||
"excluded": [
|
||||
{
|
||||
"path": "docs/BLENDER_WASM_CAPABILITY_MATRIX_TEMPLATE.json",
|
||||
"bytes": 9519,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P11-004/engine-module-gate-report.json",
|
||||
"bytes": 3712,
|
||||
"reason": "CONTEXT_REMAINING_SPACE"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P0-002/parity-map.json",
|
||||
"bytes": 5053386,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-001/",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-001.md",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-001/manifest.json",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"files": 1,
|
||||
"bytes": 2740,
|
||||
"tokens": 685
|
||||
}
|
||||
},
|
||||
"exitCriteria": [
|
||||
"all source manifests are hash-verified",
|
||||
"only done receipts enter proven evidence",
|
||||
"L0/metadata and blocked cases remain explicit",
|
||||
"inventory remainder is preserved"
|
||||
],
|
||||
"nextTask": "WBV2-P12-002",
|
||||
"sourceDocuments": {
|
||||
"queue": "docs/EXECUTION_QUEUE.md",
|
||||
"taskCard": "docs/tasks/WBV2-P12-001.md",
|
||||
"taskIndex": "tests/golden/WBV2/task-index.json",
|
||||
"parentManifest": "tests/golden/WBV2-P12-000/manifest.json",
|
||||
"parentStatus": "docs/status/WBV2-P12-000.md"
|
||||
},
|
||||
"readPolicy": {
|
||||
"required": [
|
||||
"docs/EXECUTION_QUEUE.md",
|
||||
"docs/tasks/WBV2-P12-001.md",
|
||||
"tests/golden/WBV2-P12-000/manifest.json",
|
||||
"docs/status/WBV2-P12-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-P12-000",
|
||||
"parentTask": "WBV2-P11-004",
|
||||
"status": "done",
|
||||
"nextTask": "WBV2-P12-001",
|
||||
"artifactCount": 8
|
||||
},
|
||||
"statusSummary": [
|
||||
"# WBV2-P12-000 status",
|
||||
"- task: `WBV2-P12-000`; parent: `WBV2-P11-004`; status: `done`",
|
||||
"- nextTask: `WBV2-P12-001`",
|
||||
"Domain expansion is authorized after P11 engine-bound evidence. P12 first builds a conservative capability ledger from existing receipts, then adds scene, authoring, viewport, and non-mesh coverage."
|
||||
]
|
||||
},
|
||||
"budgets": {
|
||||
"queueBytes": 4096,
|
||||
"taskBytes": 1314,
|
||||
"parentManifestBytes": 24576,
|
||||
"parentStatusBytes": 6144,
|
||||
"evidenceFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextTokens": 3500,
|
||||
"contextEnvelopeTokens": 1024,
|
||||
"taskLines": 35,
|
||||
"taskTokens": 329
|
||||
},
|
||||
"size": {
|
||||
"documents": [
|
||||
{
|
||||
"path": "docs/EXECUTION_QUEUE.md",
|
||||
"bytes": 2803,
|
||||
"lines": 51,
|
||||
"tokens": 701
|
||||
},
|
||||
{
|
||||
"path": "docs/tasks/WBV2-P12-001.md",
|
||||
"bytes": 1314,
|
||||
"lines": 35,
|
||||
"tokens": 329
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-000/manifest.json",
|
||||
"bytes": 1967,
|
||||
"lines": 58,
|
||||
"tokens": 492
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-000.md",
|
||||
"bytes": 313,
|
||||
"lines": 7,
|
||||
"tokens": 79
|
||||
}
|
||||
],
|
||||
"sourceTokens": 1601,
|
||||
"evidenceFiles": 1,
|
||||
"evidenceBytes": 2740,
|
||||
"evidenceTokens": 685,
|
||||
"totalTokens": 2286,
|
||||
"reservedEnvelopeTokens": 1024,
|
||||
"estimatedContextTokens": 3310,
|
||||
"serializedContextTokens": 716,
|
||||
"withinBudget": true
|
||||
}
|
||||
}
|
||||
1895
tests/golden/WBV2-P12-002/domain-expansion-task-plan.json
Normal file
1895
tests/golden/WBV2-P12-002/domain-expansion-task-plan.json
Normal file
File diff suppressed because it is too large
Load Diff
73
tests/golden/WBV2-P12-002/manifest.json
Normal file
73
tests/golden/WBV2-P12-002/manifest.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-002",
|
||||
"parentTask": "WBV2-P12-001",
|
||||
"operation": "SCENE_OBJECT_WORKFLOW_ENGINE_RECEIPT",
|
||||
"status": "done",
|
||||
"enablingTask": false,
|
||||
"parityStateChange": true,
|
||||
"runtime": "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM",
|
||||
"artifacts": {
|
||||
"parentManifest": {
|
||||
"path": "tests/golden/WBV2-P12-001/manifest.json",
|
||||
"sha256": "29f9fceae421e7f689cd5d560993e48b4a2cdabcdda6c842178fd05d9f52d9b7"
|
||||
},
|
||||
"sourceManifest": {
|
||||
"path": "tests/golden/WBV2-P2-002/manifest.json",
|
||||
"sha256": "fa65312256f556ce80609206e266f7fc3ccbeda34eae3da179040f8e80dd017c"
|
||||
},
|
||||
"sourceReport": {
|
||||
"path": "tests/golden/WBV2-P2-002/object-transform-report.json",
|
||||
"sha256": "17ede4ecd88d750dfb88e4ef3ab8467d55eb3be221e0d0f58b47bf20b80e646f"
|
||||
},
|
||||
"production": {
|
||||
"path": "tests/golden/WBV2-P12-002/scene-object-production.json",
|
||||
"sha256": "cc6510cfc2e958e093d34ae4799aeb7fd5c32577cca2a195fa500787fc35397d"
|
||||
},
|
||||
"productionSecond": {
|
||||
"path": "tests/golden/WBV2-P12-002/scene-object-production.second.json",
|
||||
"sha256": "cc6510cfc2e958e093d34ae4799aeb7fd5c32577cca2a195fa500787fc35397d"
|
||||
},
|
||||
"e2e": {
|
||||
"path": "web/tests/e2e/wbv2-scene-object-production.spec.ts",
|
||||
"sha256": "6c8ee1321005d59a85823cf63a6a7ce385a2839e73d76e51840079b1338c4eae"
|
||||
},
|
||||
"client": {
|
||||
"path": "web/app/src/engine-client/WebEngineClient.ts",
|
||||
"sha256": "f6d9a8e0a16403bc6fb765195b8f1a619a28de7a75c59a412f1654d46e8ebc0b"
|
||||
},
|
||||
"nativeApi": {
|
||||
"path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
|
||||
"sha256": "8fa70dc7605e66393482e661e5987a8443dded56ab0092aeb977b40ae49888f8"
|
||||
},
|
||||
"generator": {
|
||||
"path": "tools/web/generate-wbv2-scene-object-receipt.mjs",
|
||||
"sha256": "1251775ed7afcd37326dffd3ef9e52d7f227393249ec7046f1d832273e9bec81"
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P12-002/scene-object-receipt-report.json",
|
||||
"sha256": "33f69f7d1a1522b29ab2aa6cd835c9486c830883bf7bc26324ec565e6b80e0f8"
|
||||
},
|
||||
"status": {
|
||||
"path": "docs/status/WBV2-P12-002.md",
|
||||
"sha256": "7b2d40347e8f0d37752945d50795b87ecc51623216d7a202bbed10a0ca1b527a"
|
||||
},
|
||||
"parityPlan": {
|
||||
"path": "tests/golden/WBV2-P12-002/domain-expansion-task-plan.json",
|
||||
"sha256": "57f95d8bb3c6bdf049f2c77e13742e1c157857dc425b11acdf5de1adc2c0efd5"
|
||||
},
|
||||
"taskContext": {
|
||||
"path": "tests/golden/WBV2-P12-002/task-context.json",
|
||||
"sha256": "4cf8750db9d0be15363fda1184e2e2b3975331ab4370f851b683d60242e7ba17"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"visibilityMainChanged": true,
|
||||
"transformMainChanged": true,
|
||||
"saveReopen": "EXACT",
|
||||
"negativeCases": 2,
|
||||
"deterministic": true,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-003"
|
||||
}
|
||||
245
tests/golden/WBV2-P12-002/scene-object-production.json
Normal file
245
tests/golden/WBV2-P12-002/scene-object-production.json
Normal file
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-002",
|
||||
"operation": "SCENE_OBJECT_WORKFLOW_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"baseRevision": 1,
|
||||
"hiddenRevision": 2,
|
||||
"transformedRevision": 3,
|
||||
"beforeParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": true,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"beforeChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0,
|
||||
2,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"afterParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"afterChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"stale": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"malformed": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "setObjectTransform requires an existing object and three TRS vectors"
|
||||
},
|
||||
"unchangedParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"unchangedChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"reopenedParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"reopenedChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"savedSha256": "0d87ab137ef0bfdd349b071b6eb5bd0a2b2d0b7807d9a257218f159fa0e5565e",
|
||||
"sourceSha256": "62c70feb65822a58c38024d604d4cf93809372c3b7e79493f7829c4039ae01e6",
|
||||
"exactSaveReopen": true
|
||||
}
|
||||
245
tests/golden/WBV2-P12-002/scene-object-production.second.json
Normal file
245
tests/golden/WBV2-P12-002/scene-object-production.second.json
Normal file
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-002",
|
||||
"operation": "SCENE_OBJECT_WORKFLOW_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"baseRevision": 1,
|
||||
"hiddenRevision": 2,
|
||||
"transformedRevision": 3,
|
||||
"beforeParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": true,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"beforeChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0,
|
||||
2,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"afterParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"afterChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"stale": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"malformed": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "setObjectTransform requires an existing object and three TRS vectors"
|
||||
},
|
||||
"unchangedParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"unchangedChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"reopenedParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"reopenedChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"savedSha256": "0d87ab137ef0bfdd349b071b6eb5bd0a2b2d0b7807d9a257218f159fa0e5565e",
|
||||
"sourceSha256": "62c70feb65822a58c38024d604d4cf93809372c3b7e79493f7829c4039ae01e6",
|
||||
"exactSaveReopen": true
|
||||
}
|
||||
245
tests/golden/WBV2-P12-002/scene-object-production.verify.json
Normal file
245
tests/golden/WBV2-P12-002/scene-object-production.verify.json
Normal file
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-002",
|
||||
"operation": "SCENE_OBJECT_WORKFLOW_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"baseRevision": 1,
|
||||
"hiddenRevision": 2,
|
||||
"transformedRevision": 3,
|
||||
"beforeParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": true,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"beforeChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0,
|
||||
2,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"afterParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"afterChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"stale": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"malformed": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "setObjectTransform requires an existing object and three TRS vectors"
|
||||
},
|
||||
"unchangedParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"unchangedChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"reopenedParent": {
|
||||
"id": "object:WBV2P2002Parent",
|
||||
"visible": false,
|
||||
"parentId": null,
|
||||
"translation": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"reopenedChild": {
|
||||
"id": "object:WBV2P2002Child",
|
||||
"visible": true,
|
||||
"parentId": "object:WBV2P2002Parent",
|
||||
"translation": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"worldMatrix": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1.5,
|
||||
2.5,
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"savedSha256": "0d87ab137ef0bfdd349b071b6eb5bd0a2b2d0b7807d9a257218f159fa0e5565e",
|
||||
"sourceSha256": "62c70feb65822a58c38024d604d4cf93809372c3b7e79493f7829c4039ae01e6",
|
||||
"exactSaveReopen": true
|
||||
}
|
||||
63
tests/golden/WBV2-P12-002/scene-object-receipt-report.json
Normal file
63
tests/golden/WBV2-P12-002/scene-object-receipt-report.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-002",
|
||||
"operation": "SCENE_OBJECT_WORKFLOW_ENGINE_RECEIPT",
|
||||
"status": "PASS",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"source": {
|
||||
"task": "WBV2-P2-002",
|
||||
"manifest": "tests/golden/WBV2-P2-002/manifest.json",
|
||||
"manifestSha256": "fa65312256f556ce80609206e266f7fc3ccbeda34eae3da179040f8e80dd017c",
|
||||
"report": "tests/golden/WBV2-P2-002/object-transform-report.json",
|
||||
"reportSha256": "17ede4ecd88d750dfb88e4ef3ab8467d55eb3be221e0d0f58b47bf20b80e646f",
|
||||
"desktopExact": true,
|
||||
"wasmExact": true,
|
||||
"sourceSaveReopenExact": true
|
||||
},
|
||||
"production": {
|
||||
"report": "tests/golden/WBV2-P12-002/scene-object-production.json",
|
||||
"reportSha256": "cc6510cfc2e958e093d34ae4799aeb7fd5c32577cca2a195fa500787fc35397d",
|
||||
"secondReport": "tests/golden/WBV2-P12-002/scene-object-production.second.json",
|
||||
"secondReportSha256": "cc6510cfc2e958e093d34ae4799aeb7fd5c32577cca2a195fa500787fc35397d",
|
||||
"deterministic": true,
|
||||
"visibility": {
|
||||
"objectId": "object:WBV2P2002Parent",
|
||||
"before": true,
|
||||
"after": false,
|
||||
"revisionDelta": 1
|
||||
},
|
||||
"transform": {
|
||||
"objectId": "object:WBV2P2002Child",
|
||||
"before": [
|
||||
0,
|
||||
2,
|
||||
0
|
||||
],
|
||||
"after": [
|
||||
0.5,
|
||||
2.5,
|
||||
0
|
||||
],
|
||||
"revisionDelta": 1
|
||||
},
|
||||
"saveReopen": true,
|
||||
"stale": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"malformed": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "setObjectTransform requires an existing object and three TRS vectors"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"visibilityMainChanged": true,
|
||||
"transformMainChanged": true,
|
||||
"saveReopenExact": true,
|
||||
"staleRejected": true,
|
||||
"malformedRejected": true,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-003"
|
||||
}
|
||||
178
tests/golden/WBV2-P12-002/task-context.json
Normal file
178
tests/golden/WBV2-P12-002/task-context.json
Normal file
@@ -0,0 +1,178 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-002",
|
||||
"parentTask": "WBV2-P12-001",
|
||||
"status": "in_progress",
|
||||
"goal": "Bind object visibility and transform edits to the compiled WebEngine WASM Main with save/reopen and revision guards.",
|
||||
"scope": {
|
||||
"gap": "workflow:scene_object_workflow_engine_receipt",
|
||||
"ownerFamily": "EDITOR",
|
||||
"implementationClass": "LOCAL_EXACT"
|
||||
},
|
||||
"commands": [
|
||||
"npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-scene-object-production.spec.ts",
|
||||
"node tools/web/generate-wbv2-scene-object-receipt.mjs --write",
|
||||
"node tools/web/check-task-context.mjs --task WBV2-P12-002 --write"
|
||||
],
|
||||
"inputPaths": [
|
||||
"tests/golden/WBV2-P2-002/object-transform-report.json"
|
||||
],
|
||||
"inputSelection": {
|
||||
"schemaVersion": 1,
|
||||
"limits": {
|
||||
"maxFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextRemainingBytes": 2840,
|
||||
"contextRemainingTokens": 709
|
||||
},
|
||||
"source": {
|
||||
"bytes": 7064,
|
||||
"tokens": 1767
|
||||
},
|
||||
"selected": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P2-002/object-transform-report.json",
|
||||
"bytes": 1080,
|
||||
"tokens": 270
|
||||
}
|
||||
],
|
||||
"excluded": [
|
||||
{
|
||||
"path": "tests/files/web/generated/WBV2-P2-002-OBJECT.TRANSFORM_HIERARCHY.blend",
|
||||
"bytes": 86822,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "web/app/src/engine-client/WebEngineClient.ts",
|
||||
"bytes": 16197,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-002/",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-002.md",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-002/manifest.json",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"files": 1,
|
||||
"bytes": 1080,
|
||||
"tokens": 270
|
||||
}
|
||||
},
|
||||
"exitCriteria": [
|
||||
"visibility and transform mutate Main",
|
||||
"desktop source oracle is bound",
|
||||
"save/reopen is exact",
|
||||
"stale and malformed commands fail closed"
|
||||
],
|
||||
"nextTask": "WBV2-P12-003",
|
||||
"sourceDocuments": {
|
||||
"queue": "docs/EXECUTION_QUEUE.md",
|
||||
"taskCard": "docs/tasks/WBV2-P12-002.md",
|
||||
"taskIndex": "tests/golden/WBV2/task-index.json",
|
||||
"parentManifest": "tests/golden/WBV2-P12-001/manifest.json",
|
||||
"parentStatus": "docs/status/WBV2-P12-001.md"
|
||||
},
|
||||
"readPolicy": {
|
||||
"required": [
|
||||
"docs/EXECUTION_QUEUE.md",
|
||||
"docs/tasks/WBV2-P12-002.md",
|
||||
"tests/golden/WBV2-P12-001/manifest.json",
|
||||
"docs/status/WBV2-P12-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-P12-001",
|
||||
"parentTask": "WBV2-P12-000",
|
||||
"status": "done",
|
||||
"nextTask": "WBV2-P12-002",
|
||||
"artifactCount": 10
|
||||
},
|
||||
"statusSummary": [
|
||||
"# WBV2-P12-001 status",
|
||||
"- task: `WBV2-P12-001`; parent: `WBV2-P12-000`; status: `done`",
|
||||
"- source manifests batch-scanned: `34`; artifact records: `517`",
|
||||
"- repeated Blender/Chromium runs: `0`; historical drift manifests recorded: `25`",
|
||||
"- current engine-bound claims reused: `6`; inventory: `6900` total, `6618` pending, claimed complete: `0`",
|
||||
"- nextTask: `WBV2-P12-002`",
|
||||
"This ledger reuses existing P1-P6, P10, and P11 manifests as read-only evidence. It records current artifact drift instead of rewriting historical hashes and does not rerun already completed Blender or Chromium checks. Only P10/P11 engine-bound receipts are treated as current engine evidence; the remaining inventory stays explicit."
|
||||
]
|
||||
},
|
||||
"budgets": {
|
||||
"queueBytes": 4096,
|
||||
"taskBytes": 1190,
|
||||
"parentManifestBytes": 24576,
|
||||
"parentStatusBytes": 6144,
|
||||
"evidenceFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextTokens": 3500,
|
||||
"contextEnvelopeTokens": 1024,
|
||||
"taskLines": 34,
|
||||
"taskTokens": 298
|
||||
},
|
||||
"size": {
|
||||
"documents": [
|
||||
{
|
||||
"path": "docs/EXECUTION_QUEUE.md",
|
||||
"bytes": 2803,
|
||||
"lines": 51,
|
||||
"tokens": 701
|
||||
},
|
||||
{
|
||||
"path": "docs/tasks/WBV2-P12-002.md",
|
||||
"bytes": 1190,
|
||||
"lines": 34,
|
||||
"tokens": 298
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-001/manifest.json",
|
||||
"bytes": 2372,
|
||||
"lines": 66,
|
||||
"tokens": 593
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-001.md",
|
||||
"bytes": 699,
|
||||
"lines": 10,
|
||||
"tokens": 175
|
||||
}
|
||||
],
|
||||
"sourceTokens": 1767,
|
||||
"evidenceFiles": 1,
|
||||
"evidenceBytes": 1080,
|
||||
"evidenceTokens": 270,
|
||||
"totalTokens": 2037,
|
||||
"reservedEnvelopeTokens": 1024,
|
||||
"estimatedContextTokens": 3061,
|
||||
"serializedContextTokens": 711,
|
||||
"withinBudget": true
|
||||
}
|
||||
}
|
||||
1895
tests/golden/WBV2-P12-003/domain-expansion-task-plan.json
Normal file
1895
tests/golden/WBV2-P12-003/domain-expansion-task-plan.json
Normal file
File diff suppressed because it is too large
Load Diff
82
tests/golden/WBV2-P12-003/manifest.json
Normal file
82
tests/golden/WBV2-P12-003/manifest.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-003",
|
||||
"parentTask": "WBV2-P12-002",
|
||||
"operation": "MATERIAL_ANIMATION_ENGINE_RECEIPT",
|
||||
"status": "done",
|
||||
"enablingTask": false,
|
||||
"parityStateChange": true,
|
||||
"runtime": "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM",
|
||||
"artifacts": {
|
||||
"parentManifest": {
|
||||
"path": "tests/golden/WBV2-P12-002/manifest.json",
|
||||
"sha256": "63f51801601c421beeaff62353862ca17800180f336093051544936a002b3e4f"
|
||||
},
|
||||
"materialManifest": {
|
||||
"path": "tests/golden/WBV2-P3-001/manifest.json",
|
||||
"sha256": "e3b037fdcf55b5e64fd770c6fa90d0b72e96b3e764a305df0ceee378fa167191"
|
||||
},
|
||||
"materialReport": {
|
||||
"path": "tests/golden/WBV2-P3-001/material-report.json",
|
||||
"sha256": "8ab3dd49364a2f6c5404249f1433fc1f2085d9deaf9a6d126732dbd7ca9d262c"
|
||||
},
|
||||
"animationManifest": {
|
||||
"path": "tests/golden/WBV2-P3-002/manifest.json",
|
||||
"sha256": "cc36b933a2b6d817ea7226c07d0617ecdf2f89575136a83cb15de4e7c8f59188"
|
||||
},
|
||||
"animationReport": {
|
||||
"path": "tests/golden/WBV2-P3-002/animation-report.json",
|
||||
"sha256": "ac7bb8bbfa6db703c6d128ba5772213f46370be3a986cefcc2da99a1a9aad843"
|
||||
},
|
||||
"production": {
|
||||
"path": "tests/golden/WBV2-P12-003/material-animation-production.json",
|
||||
"sha256": "35851a9cca39bf8efedababcbcf459cc04ff6b33a5ce4fb0ed944664fcf36403"
|
||||
},
|
||||
"productionSecond": {
|
||||
"path": "tests/golden/WBV2-P12-003/material-animation-production.second.json",
|
||||
"sha256": "35851a9cca39bf8efedababcbcf459cc04ff6b33a5ce4fb0ed944664fcf36403"
|
||||
},
|
||||
"e2e": {
|
||||
"path": "web/tests/e2e/wbv2-material-animation-production.spec.ts",
|
||||
"sha256": "355e6476f2a4abf291506c7115312be049af6feb831a9f8873a03b9f61ba6d73"
|
||||
},
|
||||
"client": {
|
||||
"path": "web/app/src/engine-client/WebEngineClient.ts",
|
||||
"sha256": "f6d9a8e0a16403bc6fb765195b8f1a619a28de7a75c59a412f1654d46e8ebc0b"
|
||||
},
|
||||
"nativeApi": {
|
||||
"path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
|
||||
"sha256": "8fa70dc7605e66393482e661e5987a8443dded56ab0092aeb977b40ae49888f8"
|
||||
},
|
||||
"generator": {
|
||||
"path": "tools/web/generate-wbv2-material-animation-receipt.mjs",
|
||||
"sha256": "997fb2d862a266188f65c2cdf1c2870a450ba85494271660dd1bd1bc098666e0"
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P12-003/material-animation-receipt-report.json",
|
||||
"sha256": "468498825f7ebbafc7214fca1509baf130ccc72790e80a4101a88f49c42e459d"
|
||||
},
|
||||
"status": {
|
||||
"path": "docs/status/WBV2-P12-003.md",
|
||||
"sha256": "698c7ada0e7b14e8af566db3ecc4b347b562a2136b90a00d2d066c2f58eaf345"
|
||||
},
|
||||
"parityPlan": {
|
||||
"path": "tests/golden/WBV2-P12-003/domain-expansion-task-plan.json",
|
||||
"sha256": "9d817288c5966c81ead4a87220480cd023aed53ce07a91f59913f3a553ae490c"
|
||||
},
|
||||
"taskContext": {
|
||||
"path": "tests/golden/WBV2-P12-003/task-context.json",
|
||||
"sha256": "116d7d81fdb4059d9160a59d24904adab2a37367d8ada0278e9735a688c03644"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"materialMutations": 4,
|
||||
"animationMutations": 2,
|
||||
"saveReopen": "EXACT",
|
||||
"negativeCases": 2,
|
||||
"unsupportedGraphExplicit": true,
|
||||
"deterministic": true,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-004"
|
||||
}
|
||||
60
tests/golden/WBV2-P12-003/material-animation-production.json
Normal file
60
tests/golden/WBV2-P12-003/material-animation-production.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-003",
|
||||
"operation": "MATERIAL_ANIMATION_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"material": {
|
||||
"sourceUnsupportedNode": true,
|
||||
"baseRevision": 1,
|
||||
"finalRevision": 5,
|
||||
"materialId": "material:WBV2P3001PrincipledMaterial",
|
||||
"meshId": "mesh:WBV2P3001MaterialCubeMesh",
|
||||
"activeUVMap": "WBV2P3001SecondaryUV",
|
||||
"baseColor": [
|
||||
0.20000000298023224,
|
||||
0.4000000059604645,
|
||||
0.6000000238418579,
|
||||
1
|
||||
],
|
||||
"roughness": 0.3100000023841858,
|
||||
"metallic": 0.7200000286102295,
|
||||
"invalidUV": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "UV map was not found"
|
||||
},
|
||||
"revisionAfterFailure": 5,
|
||||
"savedByteLength": 223710,
|
||||
"sourceSha256": "cdf3a13e88a2084e9ac46b998a9ad1975c5e20e2bc0f2a68038c62de8801ed22",
|
||||
"saveReopenExact": true
|
||||
},
|
||||
"animation": {
|
||||
"baseRevision": 1,
|
||||
"insertedRevision": 2,
|
||||
"finalRevision": 3,
|
||||
"animationId": "action:WBV2P3002TRSAction:object:WBV2P3002AnimatedCube",
|
||||
"channelCount": 9,
|
||||
"locationFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"interpolation": "LINEAR",
|
||||
"staleFrame": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"revisionAfterFailure": 3,
|
||||
"savedByteLength": 196077,
|
||||
"sourceSha256": "63b8b79115cf7305931cd92cacaef3a2d7ee68b8690056f402bd129048460b1d",
|
||||
"reopenedFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"reopenedInterpolation": "LINEAR",
|
||||
"saveReopenExact": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-003",
|
||||
"operation": "MATERIAL_ANIMATION_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"material": {
|
||||
"sourceUnsupportedNode": true,
|
||||
"baseRevision": 1,
|
||||
"finalRevision": 5,
|
||||
"materialId": "material:WBV2P3001PrincipledMaterial",
|
||||
"meshId": "mesh:WBV2P3001MaterialCubeMesh",
|
||||
"activeUVMap": "WBV2P3001SecondaryUV",
|
||||
"baseColor": [
|
||||
0.20000000298023224,
|
||||
0.4000000059604645,
|
||||
0.6000000238418579,
|
||||
1
|
||||
],
|
||||
"roughness": 0.3100000023841858,
|
||||
"metallic": 0.7200000286102295,
|
||||
"invalidUV": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "UV map was not found"
|
||||
},
|
||||
"revisionAfterFailure": 5,
|
||||
"savedByteLength": 223710,
|
||||
"sourceSha256": "cdf3a13e88a2084e9ac46b998a9ad1975c5e20e2bc0f2a68038c62de8801ed22",
|
||||
"saveReopenExact": true
|
||||
},
|
||||
"animation": {
|
||||
"baseRevision": 1,
|
||||
"insertedRevision": 2,
|
||||
"finalRevision": 3,
|
||||
"animationId": "action:WBV2P3002TRSAction:object:WBV2P3002AnimatedCube",
|
||||
"channelCount": 9,
|
||||
"locationFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"interpolation": "LINEAR",
|
||||
"staleFrame": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"revisionAfterFailure": 3,
|
||||
"savedByteLength": 196077,
|
||||
"sourceSha256": "63b8b79115cf7305931cd92cacaef3a2d7ee68b8690056f402bd129048460b1d",
|
||||
"reopenedFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"reopenedInterpolation": "LINEAR",
|
||||
"saveReopenExact": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-003",
|
||||
"operation": "MATERIAL_ANIMATION_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"material": {
|
||||
"sourceUnsupportedNode": true,
|
||||
"baseRevision": 1,
|
||||
"finalRevision": 5,
|
||||
"materialId": "material:WBV2P3001PrincipledMaterial",
|
||||
"meshId": "mesh:WBV2P3001MaterialCubeMesh",
|
||||
"activeUVMap": "WBV2P3001SecondaryUV",
|
||||
"baseColor": [
|
||||
0.20000000298023224,
|
||||
0.4000000059604645,
|
||||
0.6000000238418579,
|
||||
1
|
||||
],
|
||||
"roughness": 0.3100000023841858,
|
||||
"metallic": 0.7200000286102295,
|
||||
"invalidUV": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "UV map was not found"
|
||||
},
|
||||
"revisionAfterFailure": 5,
|
||||
"savedByteLength": 223710,
|
||||
"sourceSha256": "cdf3a13e88a2084e9ac46b998a9ad1975c5e20e2bc0f2a68038c62de8801ed22",
|
||||
"saveReopenExact": true
|
||||
},
|
||||
"animation": {
|
||||
"baseRevision": 1,
|
||||
"insertedRevision": 2,
|
||||
"finalRevision": 3,
|
||||
"animationId": "action:WBV2P3002TRSAction:object:WBV2P3002AnimatedCube",
|
||||
"channelCount": 9,
|
||||
"locationFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"interpolation": "LINEAR",
|
||||
"staleFrame": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "REVISION_CONFLICT: command base revision does not match the current SceneIR"
|
||||
},
|
||||
"revisionAfterFailure": 3,
|
||||
"savedByteLength": 196077,
|
||||
"sourceSha256": "63b8b79115cf7305931cd92cacaef3a2d7ee68b8690056f402bd129048460b1d",
|
||||
"reopenedFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"reopenedInterpolation": "LINEAR",
|
||||
"saveReopenExact": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-003",
|
||||
"operation": "MATERIAL_ANIMATION_ENGINE_RECEIPT",
|
||||
"status": "PASS",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"source": {
|
||||
"material": {
|
||||
"task": "WBV2-P3-001",
|
||||
"manifest": "tests/golden/WBV2-P3-001/manifest.json",
|
||||
"manifestSha256": "e3b037fdcf55b5e64fd770c6fa90d0b72e96b3e764a305df0ceee378fa167191",
|
||||
"report": "tests/golden/WBV2-P3-001/material-report.json",
|
||||
"reportSha256": "8ab3dd49364a2f6c5404249f1433fc1f2085d9deaf9a6d126732dbd7ca9d262c"
|
||||
},
|
||||
"animation": {
|
||||
"task": "WBV2-P3-002",
|
||||
"manifest": "tests/golden/WBV2-P3-002/manifest.json",
|
||||
"manifestSha256": "cc36b933a2b6d817ea7226c07d0617ecdf2f89575136a83cb15de4e7c8f59188",
|
||||
"report": "tests/golden/WBV2-P3-002/animation-report.json",
|
||||
"reportSha256": "ac7bb8bbfa6db703c6d128ba5772213f46370be3a986cefcc2da99a1a9aad843"
|
||||
},
|
||||
"reusedReadOnly": true
|
||||
},
|
||||
"production": {
|
||||
"report": "tests/golden/WBV2-P12-003/material-animation-production.json",
|
||||
"reportSha256": "35851a9cca39bf8efedababcbcf459cc04ff6b33a5ce4fb0ed944664fcf36403",
|
||||
"secondReport": "tests/golden/WBV2-P12-003/material-animation-production.second.json",
|
||||
"secondReportSha256": "35851a9cca39bf8efedababcbcf459cc04ff6b33a5ce4fb0ed944664fcf36403",
|
||||
"deterministic": true,
|
||||
"material": {
|
||||
"materialId": "material:WBV2P3001PrincipledMaterial",
|
||||
"meshId": "mesh:WBV2P3001MaterialCubeMesh",
|
||||
"revisions": [
|
||||
1,
|
||||
5
|
||||
],
|
||||
"activeUVMap": "WBV2P3001SecondaryUV",
|
||||
"baseColor": [
|
||||
0.20000000298023224,
|
||||
0.4000000059604645,
|
||||
0.6000000238418579,
|
||||
1
|
||||
],
|
||||
"roughness": 0.3100000023841858,
|
||||
"metallic": 0.7200000286102295,
|
||||
"unsupportedNodeRetained": true,
|
||||
"invalidUVRejected": true,
|
||||
"savedByteLength": 223710,
|
||||
"saveReopen": "EXACT"
|
||||
},
|
||||
"animation": {
|
||||
"animationId": "action:WBV2P3002TRSAction:object:WBV2P3002AnimatedCube",
|
||||
"revisions": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"channelCount": 9,
|
||||
"locationFrames": [
|
||||
1,
|
||||
10,
|
||||
20,
|
||||
25
|
||||
],
|
||||
"interpolation": "LINEAR",
|
||||
"staleFrameRejected": true,
|
||||
"savedByteLength": 196077,
|
||||
"saveReopen": "EXACT"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"materialMainChanged": true,
|
||||
"animationMainChanged": true,
|
||||
"sourceHashesBound": true,
|
||||
"unsupportedGraphExplicit": true,
|
||||
"staleFrameRejected": true,
|
||||
"saveReopenExact": true,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-004"
|
||||
}
|
||||
183
tests/golden/WBV2-P12-003/task-context.json
Normal file
183
tests/golden/WBV2-P12-003/task-context.json
Normal file
@@ -0,0 +1,183 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-003",
|
||||
"parentTask": "WBV2-P12-002",
|
||||
"status": "in_progress",
|
||||
"goal": "Bind material Principled/texture and TRS keyframe edits to the compiled WebEngine WASM Main.",
|
||||
"scope": {
|
||||
"gap": "workflow:material_animation_engine_receipt",
|
||||
"ownerFamily": "AUTHORING",
|
||||
"implementationClass": "LOCAL_EXACT"
|
||||
},
|
||||
"commands": [
|
||||
"npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-material-animation-production.spec.ts",
|
||||
"node tools/web/generate-wbv2-material-animation-receipt.mjs --write",
|
||||
"node tools/web/check-task-context.mjs --task WBV2-P12-003 --write"
|
||||
],
|
||||
"inputPaths": [
|
||||
"tests/golden/WBV2-P3-001/material-report.json"
|
||||
],
|
||||
"inputSelection": {
|
||||
"schemaVersion": 1,
|
||||
"limits": {
|
||||
"maxFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextRemainingBytes": 2476,
|
||||
"contextRemainingTokens": 617
|
||||
},
|
||||
"source": {
|
||||
"bytes": 7428,
|
||||
"tokens": 1859
|
||||
},
|
||||
"selected": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P3-001/material-report.json",
|
||||
"bytes": 1763,
|
||||
"tokens": 441
|
||||
}
|
||||
],
|
||||
"excluded": [
|
||||
{
|
||||
"path": "tests/files/web/generated/WBV2-P3-001-MATERIAL.PBR_UV.blend",
|
||||
"bytes": 89548,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "tests/files/web/generated/WBV2-P3-002-ANIMATION.TRS_ACTION.blend",
|
||||
"bytes": 88107,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P3-002/animation-report.json",
|
||||
"bytes": 4237,
|
||||
"reason": "CONTEXT_REMAINING_SPACE"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-003/",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-003.md",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-003/manifest.json",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"files": 1,
|
||||
"bytes": 1763,
|
||||
"tokens": 441
|
||||
}
|
||||
},
|
||||
"exitCriteria": [
|
||||
"material and keyframe Main mutations pass",
|
||||
"source hashes are bound",
|
||||
"save/reopen is exact",
|
||||
"unsupported graph and stale frame inputs fail closed"
|
||||
],
|
||||
"nextTask": "WBV2-P12-004",
|
||||
"sourceDocuments": {
|
||||
"queue": "docs/EXECUTION_QUEUE.md",
|
||||
"taskCard": "docs/tasks/WBV2-P12-003.md",
|
||||
"taskIndex": "tests/golden/WBV2/task-index.json",
|
||||
"parentManifest": "tests/golden/WBV2-P12-002/manifest.json",
|
||||
"parentStatus": "docs/status/WBV2-P12-002.md"
|
||||
},
|
||||
"readPolicy": {
|
||||
"required": [
|
||||
"docs/EXECUTION_QUEUE.md",
|
||||
"docs/tasks/WBV2-P12-003.md",
|
||||
"tests/golden/WBV2-P12-002/manifest.json",
|
||||
"docs/status/WBV2-P12-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-P12-002",
|
||||
"parentTask": "WBV2-P12-001",
|
||||
"status": "done",
|
||||
"nextTask": "WBV2-P12-003",
|
||||
"artifactCount": 13
|
||||
},
|
||||
"statusSummary": [
|
||||
"# WBV2-P12-002 status",
|
||||
"- task: `WBV2-P12-002`; parent: `WBV2-P12-001`; status: `done`",
|
||||
"- visibility transaction: revision +1; hidden object persisted",
|
||||
"- transform transaction: revision +1; child translation `[0.5, 2.5, 0]` persisted",
|
||||
"- save/reopen: `EXACT`; stale and malformed commands rejected",
|
||||
"- nextTask: `WBV2-P12-003`",
|
||||
"The compiled WebEngine WASM Main now has a production-bound scene/object receipt for visibility and transform edits. Existing P2-002 desktop/WASM evidence is reused read-only; no duplicate historical fixture run is required."
|
||||
]
|
||||
},
|
||||
"budgets": {
|
||||
"queueBytes": 4096,
|
||||
"taskBytes": 1269,
|
||||
"parentManifestBytes": 24576,
|
||||
"parentStatusBytes": 6144,
|
||||
"evidenceFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextTokens": 3500,
|
||||
"contextEnvelopeTokens": 1024,
|
||||
"taskLines": 34,
|
||||
"taskTokens": 318
|
||||
},
|
||||
"size": {
|
||||
"documents": [
|
||||
{
|
||||
"path": "docs/EXECUTION_QUEUE.md",
|
||||
"bytes": 2803,
|
||||
"lines": 51,
|
||||
"tokens": 701
|
||||
},
|
||||
{
|
||||
"path": "docs/tasks/WBV2-P12-003.md",
|
||||
"bytes": 1269,
|
||||
"lines": 34,
|
||||
"tokens": 318
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-002/manifest.json",
|
||||
"bytes": 2810,
|
||||
"lines": 74,
|
||||
"tokens": 703
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-002.md",
|
||||
"bytes": 546,
|
||||
"lines": 10,
|
||||
"tokens": 137
|
||||
}
|
||||
],
|
||||
"sourceTokens": 1859,
|
||||
"evidenceFiles": 1,
|
||||
"evidenceBytes": 1763,
|
||||
"evidenceTokens": 441,
|
||||
"totalTokens": 2300,
|
||||
"reservedEnvelopeTokens": 1024,
|
||||
"estimatedContextTokens": 3324,
|
||||
"serializedContextTokens": 716,
|
||||
"withinBudget": true
|
||||
}
|
||||
}
|
||||
1895
tests/golden/WBV2-P12-004/domain-expansion-task-plan.json
Normal file
1895
tests/golden/WBV2-P12-004/domain-expansion-task-plan.json
Normal file
File diff suppressed because it is too large
Load Diff
83
tests/golden/WBV2-P12-004/manifest.json
Normal file
83
tests/golden/WBV2-P12-004/manifest.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-004",
|
||||
"parentTask": "WBV2-P12-003",
|
||||
"operation": "VIEWPORT_NONMESH_ENGINE_RECEIPT",
|
||||
"status": "done",
|
||||
"enablingTask": false,
|
||||
"parityStateChange": true,
|
||||
"runtime": "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM",
|
||||
"artifacts": {
|
||||
"parentManifest": {
|
||||
"path": "tests/golden/WBV2-P12-003/manifest.json",
|
||||
"sha256": "2ec36a52526018beb44eaccdb91d86942d5b908a19be4abd9c6065274269ebfb"
|
||||
},
|
||||
"viewportManifest": {
|
||||
"path": "tests/golden/WBV2-P2-004/manifest.json",
|
||||
"sha256": "9a511f9620bdc886ab4684ac449dcaa156086cde76c0b95d16795f0f51a304f2"
|
||||
},
|
||||
"viewportReport": {
|
||||
"path": "tests/golden/WBV2-P2-004/viewport-report.json",
|
||||
"sha256": "a38e7ff8da3042a82f4d20f9f6c60300ebd6ee393cf3625901c770ebff674dac"
|
||||
},
|
||||
"nonMeshManifest": {
|
||||
"path": "tests/golden/WBV2-P4-003/manifest.json",
|
||||
"sha256": "9c41ef52263d544650b1bad2dc2ec5f40ed63a9ab1b9732492a46672384e1218"
|
||||
},
|
||||
"nonMeshReport": {
|
||||
"path": "tests/golden/WBV2-P4-003/sculpt-report.json",
|
||||
"sha256": "de29aabbb753b682d85c30258ff4d68530650d00e167f30181d5c9a68669dd99"
|
||||
},
|
||||
"production": {
|
||||
"path": "tests/golden/WBV2-P12-004/viewport-nonmesh-production.json",
|
||||
"sha256": "ec3c861645a084a3f6e37d014f983c9b6710ed64f8f62b89aa7f70dd19aff337"
|
||||
},
|
||||
"productionSecond": {
|
||||
"path": "tests/golden/WBV2-P12-004/viewport-nonmesh-production.second.json",
|
||||
"sha256": "ec3c861645a084a3f6e37d014f983c9b6710ed64f8f62b89aa7f70dd19aff337"
|
||||
},
|
||||
"e2e": {
|
||||
"path": "web/tests/e2e/wbv2-viewport-nonmesh-production.spec.ts",
|
||||
"sha256": "9d2f504de2fb328ddbc8847e360feb840f988b5a442066179f65e72831c0934f"
|
||||
},
|
||||
"client": {
|
||||
"path": "web/app/src/engine-client/WebEngineClient.ts",
|
||||
"sha256": "f6d9a8e0a16403bc6fb765195b8f1a619a28de7a75c59a412f1654d46e8ebc0b"
|
||||
},
|
||||
"viewport": {
|
||||
"path": "web/app/src/three-adapter/viewport.ts",
|
||||
"sha256": "e8d97cb59fd4eca3789aeeb35221a70cf47ef048a5665383d809d0efc49f7119"
|
||||
},
|
||||
"generator": {
|
||||
"path": "tools/web/generate-wbv2-viewport-nonmesh-receipt.mjs",
|
||||
"sha256": "f789103e4cf17ddcd4d5519d624a57a83712cc057c4f2d605ccf6a3ff0258ffa"
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json",
|
||||
"sha256": "61cbaee24719647addfd3147a665b97ad40deff4eb4a64c055a3ba7a33cac53b"
|
||||
},
|
||||
"status": {
|
||||
"path": "docs/status/WBV2-P12-004.md",
|
||||
"sha256": "035b241a17d8e887d99943027ec385cbf6fdca94572b12df1a23bd477967f0c7"
|
||||
},
|
||||
"parityPlan": {
|
||||
"path": "tests/golden/WBV2-P12-004/domain-expansion-task-plan.json",
|
||||
"sha256": "d6853d90b12e1df1055d3fb2251a082448e35c04be260c98662b9eba61796bbd"
|
||||
},
|
||||
"taskContext": {
|
||||
"path": "tests/golden/WBV2-P12-004/task-context.json",
|
||||
"sha256": "d81e7027ea12fbb372ef2393b59f0f9db7627ecb1b449ec4cfb4253d0e27d74d"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"viewportPixelsNonblank": true,
|
||||
"nonMeshDataExplicit": true,
|
||||
"curveMainChanged": true,
|
||||
"unsupportedDataBlocked": true,
|
||||
"resourceDisposalExact": true,
|
||||
"saveReopen": "EXACT",
|
||||
"deterministic": true,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-005"
|
||||
}
|
||||
179
tests/golden/WBV2-P12-004/task-context.json
Normal file
179
tests/golden/WBV2-P12-004/task-context.json
Normal file
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-004",
|
||||
"parentTask": "WBV2-P12-003",
|
||||
"status": "in_progress",
|
||||
"goal": "Bind viewport SceneIR and bounded non-mesh read/edit paths to the compiled WebEngine runtime with explicit unsupported boundaries.",
|
||||
"scope": {
|
||||
"gap": "workflow:viewport_nonmesh_engine_receipt",
|
||||
"ownerFamily": "VIEWPORT",
|
||||
"implementationClass": "LOCAL_BOUNDED"
|
||||
},
|
||||
"commands": [
|
||||
"npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-viewport-nonmesh-production.spec.ts",
|
||||
"node tools/web/generate-wbv2-viewport-nonmesh-receipt.mjs --write",
|
||||
"node tools/web/check-task-context.mjs --task WBV2-P12-004 --write"
|
||||
],
|
||||
"inputPaths": [
|
||||
"tests/golden/WBV2-P4-003/sculpt-report.json"
|
||||
],
|
||||
"inputSelection": {
|
||||
"schemaVersion": 1,
|
||||
"limits": {
|
||||
"maxFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextRemainingBytes": 2070,
|
||||
"contextRemainingTokens": 516
|
||||
},
|
||||
"source": {
|
||||
"bytes": 7834,
|
||||
"tokens": 1960
|
||||
},
|
||||
"selected": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P4-003/sculpt-report.json",
|
||||
"bytes": 1553,
|
||||
"tokens": 389
|
||||
}
|
||||
],
|
||||
"excluded": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P2-004/viewport-report.json",
|
||||
"bytes": 2693,
|
||||
"reason": "CONTEXT_REMAINING_SPACE"
|
||||
},
|
||||
{
|
||||
"path": "web/app/src/engine-client/WebEngineClient.ts",
|
||||
"bytes": 16197,
|
||||
"reason": "EVIDENCE_BYTE_BUDGET"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-004/",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-004.md",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-004/manifest.json",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"files": 1,
|
||||
"bytes": 1553,
|
||||
"tokens": 389
|
||||
}
|
||||
},
|
||||
"exitCriteria": [
|
||||
"nonblank viewport evidence is bound",
|
||||
"non-mesh data is explicit",
|
||||
"unsupported and budget cases fail closed",
|
||||
"save/reopen and resource disposal are exact"
|
||||
],
|
||||
"nextTask": "WBV2-P12-005",
|
||||
"sourceDocuments": {
|
||||
"queue": "docs/EXECUTION_QUEUE.md",
|
||||
"taskCard": "docs/tasks/WBV2-P12-004.md",
|
||||
"taskIndex": "tests/golden/WBV2/task-index.json",
|
||||
"parentManifest": "tests/golden/WBV2-P12-003/manifest.json",
|
||||
"parentStatus": "docs/status/WBV2-P12-003.md"
|
||||
},
|
||||
"readPolicy": {
|
||||
"required": [
|
||||
"docs/EXECUTION_QUEUE.md",
|
||||
"docs/tasks/WBV2-P12-004.md",
|
||||
"tests/golden/WBV2-P12-003/manifest.json",
|
||||
"docs/status/WBV2-P12-003.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-P12-003",
|
||||
"parentTask": "WBV2-P12-002",
|
||||
"status": "done",
|
||||
"nextTask": "WBV2-P12-004",
|
||||
"artifactCount": 15
|
||||
},
|
||||
"statusSummary": [
|
||||
"# WBV2-P12-003 status",
|
||||
"- task: `WBV2-P12-003`; parent: `WBV2-P12-002`; status: `done`",
|
||||
"- material/UV: `4` Main mutations; Principled values and UV map persisted",
|
||||
"- animation/TRS: keyframe frame `25` + interpolation `LINEAR`; persisted",
|
||||
"- save/reopen: `EXACT`; invalid UV and stale frame rejected",
|
||||
"- existing P3 source receipts reused read-only; no duplicate historical run",
|
||||
"- nextTask: `WBV2-P12-004`",
|
||||
"The material and animation workflows are now bound to the compiled WebEngine WASM Main in Chromium. Unsupported material nodes remain explicit, and stale or malformed authoring commands do not mutate Main."
|
||||
]
|
||||
},
|
||||
"budgets": {
|
||||
"queueBytes": 4096,
|
||||
"taskBytes": 1217,
|
||||
"parentManifestBytes": 24576,
|
||||
"parentStatusBytes": 6144,
|
||||
"evidenceFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextTokens": 3500,
|
||||
"contextEnvelopeTokens": 1024,
|
||||
"taskLines": 34,
|
||||
"taskTokens": 305
|
||||
},
|
||||
"size": {
|
||||
"documents": [
|
||||
{
|
||||
"path": "docs/EXECUTION_QUEUE.md",
|
||||
"bytes": 2803,
|
||||
"lines": 51,
|
||||
"tokens": 701
|
||||
},
|
||||
{
|
||||
"path": "docs/tasks/WBV2-P12-004.md",
|
||||
"bytes": 1217,
|
||||
"lines": 34,
|
||||
"tokens": 305
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-003/manifest.json",
|
||||
"bytes": 3211,
|
||||
"lines": 83,
|
||||
"tokens": 803
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-003.md",
|
||||
"bytes": 603,
|
||||
"lines": 11,
|
||||
"tokens": 151
|
||||
}
|
||||
],
|
||||
"sourceTokens": 1960,
|
||||
"evidenceFiles": 1,
|
||||
"evidenceBytes": 1553,
|
||||
"evidenceTokens": 389,
|
||||
"totalTokens": 2349,
|
||||
"reservedEnvelopeTokens": 1024,
|
||||
"estimatedContextTokens": 3373,
|
||||
"serializedContextTokens": 725,
|
||||
"withinBudget": true
|
||||
}
|
||||
}
|
||||
79
tests/golden/WBV2-P12-004/viewport-nonmesh-production.json
Normal file
79
tests/golden/WBV2-P12-004/viewport-nonmesh-production.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-004",
|
||||
"operation": "VIEWPORT_NONMESH_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"viewport": {
|
||||
"revision": 1,
|
||||
"sceneId": "scene:WBV2P2004ViewportScene",
|
||||
"meshCount": 1,
|
||||
"geometryBuffers": 1,
|
||||
"readbackPixels": 1024,
|
||||
"resources": {
|
||||
"activeRequests": 0,
|
||||
"liveInputBytes": 0,
|
||||
"liveNativeHandles": 0,
|
||||
"liveStagingFiles": 0
|
||||
}
|
||||
},
|
||||
"nonMesh": {
|
||||
"baseRevision": 1,
|
||||
"editedRevision": 2,
|
||||
"data": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 1
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 0
|
||||
}
|
||||
],
|
||||
"gates": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_CURVE_BINARY",
|
||||
"issueCodes": []
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_POINT_CLOUD_BINARY",
|
||||
"issueCodes": []
|
||||
}
|
||||
],
|
||||
"unknown": {
|
||||
"status": "BLOCKED",
|
||||
"capability": "NON_MESH_DATA",
|
||||
"issueCode": "NON_MESH_DATA_UNSUPPORTED"
|
||||
},
|
||||
"curveId": "curve:WBV2P4003Curve",
|
||||
"curveBefore": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"curveAfter": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"reopenedCurve": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"malformed": {
|
||||
"code": "NON_MESH_PROPERTY_INVALID",
|
||||
"message": "Curve control points must be finite and within the 1M point budget"
|
||||
},
|
||||
"revisionAfterMalformed": 2,
|
||||
"savedSha256": "1806f33520281813e765819c31bce7af1dc3a7b215d3a48899f9b1b2103ea3a0",
|
||||
"sourceSha256": "88e64b7ca103025111891c3dbdb78d5dd038c99d77d46831414ee984ee16d161",
|
||||
"saveReopenExact": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-004",
|
||||
"operation": "VIEWPORT_NONMESH_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"viewport": {
|
||||
"revision": 1,
|
||||
"sceneId": "scene:WBV2P2004ViewportScene",
|
||||
"meshCount": 1,
|
||||
"geometryBuffers": 1,
|
||||
"readbackPixels": 1024,
|
||||
"resources": {
|
||||
"activeRequests": 0,
|
||||
"liveInputBytes": 0,
|
||||
"liveNativeHandles": 0,
|
||||
"liveStagingFiles": 0
|
||||
}
|
||||
},
|
||||
"nonMesh": {
|
||||
"baseRevision": 1,
|
||||
"editedRevision": 2,
|
||||
"data": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 1
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 0
|
||||
}
|
||||
],
|
||||
"gates": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_CURVE_BINARY",
|
||||
"issueCodes": []
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_POINT_CLOUD_BINARY",
|
||||
"issueCodes": []
|
||||
}
|
||||
],
|
||||
"unknown": {
|
||||
"status": "BLOCKED",
|
||||
"capability": "NON_MESH_DATA",
|
||||
"issueCode": "NON_MESH_DATA_UNSUPPORTED"
|
||||
},
|
||||
"curveId": "curve:WBV2P4003Curve",
|
||||
"curveBefore": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"curveAfter": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"reopenedCurve": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"malformed": {
|
||||
"code": "NON_MESH_PROPERTY_INVALID",
|
||||
"message": "Curve control points must be finite and within the 1M point budget"
|
||||
},
|
||||
"revisionAfterMalformed": 2,
|
||||
"savedSha256": "1806f33520281813e765819c31bce7af1dc3a7b215d3a48899f9b1b2103ea3a0",
|
||||
"sourceSha256": "88e64b7ca103025111891c3dbdb78d5dd038c99d77d46831414ee984ee16d161",
|
||||
"saveReopenExact": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-004",
|
||||
"operation": "VIEWPORT_NONMESH_ENGINE_CHROMIUM",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"viewport": {
|
||||
"revision": 1,
|
||||
"sceneId": "scene:WBV2P2004ViewportScene",
|
||||
"meshCount": 1,
|
||||
"geometryBuffers": 1,
|
||||
"readbackPixels": 1024,
|
||||
"resources": {
|
||||
"activeRequests": 0,
|
||||
"liveInputBytes": 0,
|
||||
"liveNativeHandles": 0,
|
||||
"liveStagingFiles": 0
|
||||
}
|
||||
},
|
||||
"nonMesh": {
|
||||
"baseRevision": 1,
|
||||
"editedRevision": 2,
|
||||
"data": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 1
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 0
|
||||
}
|
||||
],
|
||||
"gates": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_CURVE_BINARY",
|
||||
"issueCodes": []
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_POINT_CLOUD_BINARY",
|
||||
"issueCodes": []
|
||||
}
|
||||
],
|
||||
"unknown": {
|
||||
"status": "BLOCKED",
|
||||
"capability": "NON_MESH_DATA",
|
||||
"issueCode": "NON_MESH_DATA_UNSUPPORTED"
|
||||
},
|
||||
"curveId": "curve:WBV2P4003Curve",
|
||||
"curveBefore": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"curveAfter": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"reopenedCurve": {
|
||||
"pointCount": 3
|
||||
},
|
||||
"malformed": {
|
||||
"code": "NON_MESH_PROPERTY_INVALID",
|
||||
"message": "Curve control points must be finite and within the 1M point budget"
|
||||
},
|
||||
"revisionAfterMalformed": 2,
|
||||
"savedSha256": "1806f33520281813e765819c31bce7af1dc3a7b215d3a48899f9b1b2103ea3a0",
|
||||
"sourceSha256": "88e64b7ca103025111891c3dbdb78d5dd038c99d77d46831414ee984ee16d161",
|
||||
"saveReopenExact": true
|
||||
}
|
||||
}
|
||||
103
tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json
Normal file
103
tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-004",
|
||||
"operation": "VIEWPORT_NONMESH_ENGINE_RECEIPT",
|
||||
"status": "PASS",
|
||||
"browser": "chromium",
|
||||
"queueMutation": false,
|
||||
"source": {
|
||||
"viewport": {
|
||||
"task": "WBV2-P2-004",
|
||||
"manifest": "tests/golden/WBV2-P2-004/manifest.json",
|
||||
"manifestSha256": "9a511f9620bdc886ab4684ac449dcaa156086cde76c0b95d16795f0f51a304f2",
|
||||
"report": "tests/golden/WBV2-P2-004/viewport-report.json",
|
||||
"reportSha256": "a38e7ff8da3042a82f4d20f9f6c60300ebd6ee393cf3625901c770ebff674dac"
|
||||
},
|
||||
"nonMesh": {
|
||||
"task": "WBV2-P4-003",
|
||||
"manifest": "tests/golden/WBV2-P4-003/manifest.json",
|
||||
"manifestSha256": "9c41ef52263d544650b1bad2dc2ec5f40ed63a9ab1b9732492a46672384e1218",
|
||||
"report": "tests/golden/WBV2-P4-003/sculpt-report.json",
|
||||
"reportSha256": "de29aabbb753b682d85c30258ff4d68530650d00e167f30181d5c9a68669dd99"
|
||||
},
|
||||
"reusedReadOnly": true
|
||||
},
|
||||
"production": {
|
||||
"report": "tests/golden/WBV2-P12-004/viewport-nonmesh-production.json",
|
||||
"reportSha256": "ec3c861645a084a3f6e37d014f983c9b6710ed64f8f62b89aa7f70dd19aff337",
|
||||
"secondReport": "tests/golden/WBV2-P12-004/viewport-nonmesh-production.second.json",
|
||||
"secondReportSha256": "ec3c861645a084a3f6e37d014f983c9b6710ed64f8f62b89aa7f70dd19aff337",
|
||||
"deterministic": true,
|
||||
"viewport": {
|
||||
"sceneId": "scene:WBV2P2004ViewportScene",
|
||||
"meshCount": 1,
|
||||
"geometryBuffers": 1,
|
||||
"readbackPixels": 1024,
|
||||
"resources": {
|
||||
"activeRequests": 0,
|
||||
"liveInputBytes": 0,
|
||||
"liveNativeHandles": 0,
|
||||
"liveStagingFiles": 0
|
||||
}
|
||||
},
|
||||
"nonMesh": {
|
||||
"data": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 1
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"geometryStatus": "binary",
|
||||
"pointCount": 3,
|
||||
"splineCount": 0
|
||||
}
|
||||
],
|
||||
"gates": [
|
||||
{
|
||||
"id": "curve:WBV2P4003Curve",
|
||||
"type": "CURVE",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_CURVE_BINARY",
|
||||
"issueCodes": []
|
||||
},
|
||||
{
|
||||
"id": "pointcloud:WBV2P4003PointCloud",
|
||||
"type": "POINT_CLOUD",
|
||||
"status": "READY",
|
||||
"capability": "NON_MESH_POINT_CLOUD_BINARY",
|
||||
"issueCodes": []
|
||||
}
|
||||
],
|
||||
"curveId": "curve:WBV2P4003Curve",
|
||||
"baseRevision": 1,
|
||||
"editedRevision": 2,
|
||||
"unknown": {
|
||||
"status": "BLOCKED",
|
||||
"capability": "NON_MESH_DATA",
|
||||
"issueCode": "NON_MESH_DATA_UNSUPPORTED"
|
||||
},
|
||||
"malformed": {
|
||||
"code": "NON_MESH_PROPERTY_INVALID",
|
||||
"message": "Curve control points must be finite and within the 1M point budget"
|
||||
},
|
||||
"revisionAfterMalformed": 2,
|
||||
"saveReopen": true
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"viewportPixelsNonblank": true,
|
||||
"nonMeshDataExplicit": true,
|
||||
"curveMainChanged": true,
|
||||
"unsupportedDataBlocked": true,
|
||||
"malformedRejected": true,
|
||||
"resourceDisposalExact": true,
|
||||
"saveReopenExact": true,
|
||||
"historicalReproduction": false
|
||||
},
|
||||
"nextTask": "WBV2-P12-005"
|
||||
}
|
||||
1895
tests/golden/WBV2-P12-005/domain-expansion-task-plan.json
Normal file
1895
tests/golden/WBV2-P12-005/domain-expansion-task-plan.json
Normal file
File diff suppressed because it is too large
Load Diff
113
tests/golden/WBV2-P12-005/domain-parity-gate-report.json
Normal file
113
tests/golden/WBV2-P12-005/domain-parity-gate-report.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-005",
|
||||
"operation": "RECOMPUTE_DOMAIN_PARITY_GATE",
|
||||
"status": "PASS",
|
||||
"decision": {
|
||||
"status": "READY_WITH_DOMAIN_ENGINE_PARITY",
|
||||
"code": "DOMAIN_PARITY_AUTHORIZED_REBASELINE",
|
||||
"featureParityClaims": [
|
||||
"CAP-MESH-TOPOLOGY-FAMILY",
|
||||
"CAP-MODIFIER-PARAMETER-APPLY",
|
||||
"CAP-ASSET-LINK-OVERRIDE-RELOAD",
|
||||
"CAP-SCENE-OBJECT-ENGINE",
|
||||
"CAP-MATERIAL-ANIMATION-ENGINE",
|
||||
"CAP-VIEWPORT-NONMESH-ENGINE"
|
||||
],
|
||||
"featureParityClaimCount": 6,
|
||||
"engineBound": true,
|
||||
"browser": "chromium",
|
||||
"provenanceEpoch": 2,
|
||||
"releaseScope": "AUTHORIZED_REBASELINE_ONLY",
|
||||
"fullHistoricalReproduction": false,
|
||||
"inventoryTotal": 6900,
|
||||
"inventoryPending": 6618,
|
||||
"inventoryClaimedComplete": 0
|
||||
},
|
||||
"evidence": {
|
||||
"ledger": {
|
||||
"path": "tests/golden/WBV2-P12-001/capability-ledger-report.json",
|
||||
"sha256": "5c41a84564f78bb8e78a988f0445b06eaf1b3d0af8c59cdb216d0e79b0d46414",
|
||||
"sourceManifests": 34,
|
||||
"artifactRecords": 517,
|
||||
"repeatedRuns": 0
|
||||
},
|
||||
"p11Gate": {
|
||||
"path": "tests/golden/WBV2-P11-004/engine-module-gate-report.json",
|
||||
"sha256": "9b549cd365f8719ee48b075801e897d04df660929ac4bd7e1325a6b4b4646280",
|
||||
"claims": 3
|
||||
},
|
||||
"domains": [
|
||||
{
|
||||
"capabilityId": "CAP-SCENE-OBJECT-ENGINE",
|
||||
"family": "SCENE_OBJECT",
|
||||
"manifest": "tests/golden/WBV2-P12-002/manifest.json",
|
||||
"manifestSha256": "63f51801601c421beeaff62353862ca17800180f336093051544936a002b3e4f",
|
||||
"report": "tests/golden/WBV2-P12-002/scene-object-receipt-report.json",
|
||||
"reportSha256": "33f69f7d1a1522b29ab2aa6cd835c9486c830883bf7bc26324ec565e6b80e0f8",
|
||||
"proof": "visibility + transform + exact save/reopen",
|
||||
"browser": "chromium",
|
||||
"engineBound": true,
|
||||
"deterministic": true,
|
||||
"saveReopen": "EXACT"
|
||||
},
|
||||
{
|
||||
"capabilityId": "CAP-MATERIAL-ANIMATION-ENGINE",
|
||||
"family": "MATERIAL_ANIMATION",
|
||||
"manifest": "tests/golden/WBV2-P12-003/manifest.json",
|
||||
"manifestSha256": "2ec36a52526018beb44eaccdb91d86942d5b908a19be4abd9c6065274269ebfb",
|
||||
"report": "tests/golden/WBV2-P12-003/material-animation-receipt-report.json",
|
||||
"reportSha256": "468498825f7ebbafc7214fca1509baf130ccc72790e80a4101a88f49c42e459d",
|
||||
"proof": "material/UV + keyframe/interpolation + exact save/reopen",
|
||||
"browser": "chromium",
|
||||
"engineBound": true,
|
||||
"deterministic": true,
|
||||
"saveReopen": "EXACT"
|
||||
},
|
||||
{
|
||||
"capabilityId": "CAP-VIEWPORT-NONMESH-ENGINE",
|
||||
"family": "VIEWPORT_NONMESH",
|
||||
"manifest": "tests/golden/WBV2-P12-004/manifest.json",
|
||||
"manifestSha256": "937df9652e879f877400ca828d8ae86b89c3dc12964b7ef7e9f6366b78e7184f",
|
||||
"report": "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json",
|
||||
"reportSha256": "61cbaee24719647addfd3147a665b97ad40deff4eb4a64c055a3ba7a33cac53b",
|
||||
"proof": "nonblank viewport + non-mesh gate/edit + exact save/reopen",
|
||||
"browser": "chromium",
|
||||
"engineBound": true,
|
||||
"deterministic": true,
|
||||
"saveReopen": "EXACT"
|
||||
}
|
||||
]
|
||||
},
|
||||
"efficiency": {
|
||||
"batchLedgerScan": true,
|
||||
"existingReceiptsReused": 34,
|
||||
"repeatedBlenderRuns": 0,
|
||||
"repeatedChromiumRuns": 0,
|
||||
"newDomainReceipts": 3,
|
||||
"inventoryTasksCreated": 0
|
||||
},
|
||||
"coverage": {
|
||||
"inventoryTotal": 6900,
|
||||
"inventoryPending": 6618,
|
||||
"inventoryClaimedComplete": 0,
|
||||
"engineBoundDomainClaims": 6
|
||||
},
|
||||
"negative": {
|
||||
"missingReceipt": "REJECTED",
|
||||
"receiptHashDrift": "REJECTED",
|
||||
"unsupportedBrowser": "REJECTED",
|
||||
"nonExactSaveReopen": "REJECTED",
|
||||
"falseInventoryCompletion": "REJECTED",
|
||||
"falseHistoricalReproduction": "REJECTED",
|
||||
"undeclaredClaim": "REJECTED"
|
||||
},
|
||||
"policy": {
|
||||
"sourceHistoryReadOnly": true,
|
||||
"authorizedRebaselineOnly": true,
|
||||
"existingEvidenceReused": true,
|
||||
"inventoryRemainderExplicit": true,
|
||||
"terminalQueuePointer": true
|
||||
},
|
||||
"nextTask": null
|
||||
}
|
||||
88
tests/golden/WBV2-P12-005/manifest.json
Normal file
88
tests/golden/WBV2-P12-005/manifest.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-005",
|
||||
"parentTask": "WBV2-P12-004",
|
||||
"operation": "RECOMPUTE_DOMAIN_PARITY_GATE",
|
||||
"status": "done",
|
||||
"enablingTask": true,
|
||||
"parityStateChange": true,
|
||||
"runtime": "READ_ONLY_LEDGER_PLUS_PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM",
|
||||
"artifacts": {
|
||||
"parentManifest": {
|
||||
"path": "tests/golden/WBV2-P12-004/manifest.json",
|
||||
"sha256": "937df9652e879f877400ca828d8ae86b89c3dc12964b7ef7e9f6366b78e7184f"
|
||||
},
|
||||
"ledger": {
|
||||
"path": "tests/golden/WBV2-P12-001/capability-ledger-report.json",
|
||||
"sha256": "5c41a84564f78bb8e78a988f0445b06eaf1b3d0af8c59cdb216d0e79b0d46414"
|
||||
},
|
||||
"approval": {
|
||||
"path": "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json",
|
||||
"sha256": "cffc869734af94ffe6b8b8004d7ab8cc2c9edcb85ec2a877548e0b0f923f5ea3"
|
||||
},
|
||||
"p11Gate": {
|
||||
"path": "tests/golden/WBV2-P11-004/engine-module-gate-report.json",
|
||||
"sha256": "9b549cd365f8719ee48b075801e897d04df660929ac4bd7e1325a6b4b4646280"
|
||||
},
|
||||
"sceneObjectManifest": {
|
||||
"path": "tests/golden/WBV2-P12-002/manifest.json",
|
||||
"sha256": "63f51801601c421beeaff62353862ca17800180f336093051544936a002b3e4f"
|
||||
},
|
||||
"sceneObjectReport": {
|
||||
"path": "tests/golden/WBV2-P12-002/scene-object-receipt-report.json",
|
||||
"sha256": "33f69f7d1a1522b29ab2aa6cd835c9486c830883bf7bc26324ec565e6b80e0f8"
|
||||
},
|
||||
"materialAnimationManifest": {
|
||||
"path": "tests/golden/WBV2-P12-003/manifest.json",
|
||||
"sha256": "2ec36a52526018beb44eaccdb91d86942d5b908a19be4abd9c6065274269ebfb"
|
||||
},
|
||||
"materialAnimationReport": {
|
||||
"path": "tests/golden/WBV2-P12-003/material-animation-receipt-report.json",
|
||||
"sha256": "468498825f7ebbafc7214fca1509baf130ccc72790e80a4101a88f49c42e459d"
|
||||
},
|
||||
"viewportNonMeshManifest": {
|
||||
"path": "tests/golden/WBV2-P12-004/manifest.json",
|
||||
"sha256": "937df9652e879f877400ca828d8ae86b89c3dc12964b7ef7e9f6366b78e7184f"
|
||||
},
|
||||
"viewportNonMeshReport": {
|
||||
"path": "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json",
|
||||
"sha256": "61cbaee24719647addfd3147a665b97ad40deff4eb4a64c055a3ba7a33cac53b"
|
||||
},
|
||||
"generator": {
|
||||
"path": "tools/web/generate-wbv2-domain-parity-gate.mjs",
|
||||
"sha256": "92c438acba24433a77326bcf2c5832ac03b8eb0eac2e690b17e653b81320ece0"
|
||||
},
|
||||
"report": {
|
||||
"path": "tests/golden/WBV2-P12-005/domain-parity-gate-report.json",
|
||||
"sha256": "22507c619c6d99729322d73dc9c5dcd97d69832608f253b865469daa11a2f9d6"
|
||||
},
|
||||
"status": {
|
||||
"path": "docs/status/WBV2-P12-005.md",
|
||||
"sha256": "095a7b2d590c517f8312ae49b84c0805fba5c4289987824a4add8cb5af217545"
|
||||
},
|
||||
"parityPlan": {
|
||||
"path": "tests/golden/WBV2-P12-005/domain-expansion-task-plan.json",
|
||||
"sha256": "d90825452b43200daa7588d46017863d8e7f27ba489bfeecdf5bf8a17ed43cd4"
|
||||
},
|
||||
"taskContext": {
|
||||
"path": "tests/golden/WBV2-P12-005/task-context.json",
|
||||
"sha256": "c2b65e43fe6fb5197ea4f341fc2ed80f0989e4187bfdfd3dc6152f441c6db656"
|
||||
}
|
||||
},
|
||||
"assertions": {
|
||||
"totalClaims": 6,
|
||||
"newDomainClaims": 3,
|
||||
"reusedP11Claims": 3,
|
||||
"existingManifestsBatchScanned": 34,
|
||||
"repeatedBlenderRuns": 0,
|
||||
"repeatedChromiumRuns": 0,
|
||||
"inventoryTotal": 6900,
|
||||
"inventoryPending": 6618,
|
||||
"inventoryClaimedComplete": 0,
|
||||
"provenanceEpoch": 2,
|
||||
"authorizedRebaselineOnly": true,
|
||||
"fullHistoricalReproduction": false,
|
||||
"deterministic": true
|
||||
},
|
||||
"nextTask": null
|
||||
}
|
||||
178
tests/golden/WBV2-P12-005/task-context.json
Normal file
178
tests/golden/WBV2-P12-005/task-context.json
Normal file
@@ -0,0 +1,178 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "WBV2-P12-005",
|
||||
"parentTask": "WBV2-P12-004",
|
||||
"status": "in_progress",
|
||||
"goal": "Recompute domain parity from P10-P12 receipts while retaining explicit inventory and provenance limits.",
|
||||
"scope": {
|
||||
"gap": "workflow:recompute_domain_parity_gate",
|
||||
"ownerFamily": "RELEASE",
|
||||
"implementationClass": "LOCAL_BOUNDED"
|
||||
},
|
||||
"commands": [
|
||||
"node tools/web/generate-wbv2-domain-parity-gate.mjs --write",
|
||||
"node tools/web/check-task-context.mjs --task WBV2-P12-005 --write"
|
||||
],
|
||||
"inputPaths": [
|
||||
"tests/golden/WBV2-P12-001/capability-ledger-report.json",
|
||||
"docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json"
|
||||
],
|
||||
"inputSelection": {
|
||||
"schemaVersion": 1,
|
||||
"limits": {
|
||||
"maxFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextRemainingBytes": 2104,
|
||||
"contextRemainingTokens": 524
|
||||
},
|
||||
"source": {
|
||||
"bytes": 7800,
|
||||
"tokens": 1952
|
||||
},
|
||||
"selected": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-001/capability-ledger-report.json",
|
||||
"bytes": 1160,
|
||||
"tokens": 290
|
||||
},
|
||||
{
|
||||
"path": "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json",
|
||||
"bytes": 704,
|
||||
"tokens": 176
|
||||
}
|
||||
],
|
||||
"excluded": [
|
||||
{
|
||||
"path": "tests/golden/WBV2-P11-004/engine-module-gate-report.json",
|
||||
"bytes": 3712,
|
||||
"reason": "CONTEXT_REMAINING_SPACE"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-005/",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-005.md",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-005/manifest.json",
|
||||
"bytes": null,
|
||||
"reason": "GENERATED_EVIDENCE_OUTPUT"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"files": 2,
|
||||
"bytes": 1864,
|
||||
"tokens": 466
|
||||
}
|
||||
},
|
||||
"exitCriteria": [
|
||||
"only engine-bound domain claims are emitted",
|
||||
"unproven inventory remains explicit",
|
||||
"epoch 2 remains authorized rebaseline only",
|
||||
"full historical reproduction remains false"
|
||||
],
|
||||
"nextTask": null,
|
||||
"sourceDocuments": {
|
||||
"queue": "docs/EXECUTION_QUEUE.md",
|
||||
"taskCard": "docs/tasks/WBV2-P12-005.md",
|
||||
"taskIndex": "tests/golden/WBV2/task-index.json",
|
||||
"parentManifest": "tests/golden/WBV2-P12-004/manifest.json",
|
||||
"parentStatus": "docs/status/WBV2-P12-004.md"
|
||||
},
|
||||
"readPolicy": {
|
||||
"required": [
|
||||
"docs/EXECUTION_QUEUE.md",
|
||||
"docs/tasks/WBV2-P12-005.md",
|
||||
"tests/golden/WBV2-P12-004/manifest.json",
|
||||
"docs/status/WBV2-P12-004.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-P12-004",
|
||||
"parentTask": "WBV2-P12-003",
|
||||
"status": "done",
|
||||
"nextTask": "WBV2-P12-005",
|
||||
"artifactCount": 15
|
||||
},
|
||||
"statusSummary": [
|
||||
"# WBV2-P12-004 status",
|
||||
"- task: `WBV2-P12-004`; parent: `WBV2-P12-003`; status: `done`",
|
||||
"- viewport: scene `scene:WBV2P2004ViewportScene`; readback pixels `1024`; resources disposed exact",
|
||||
"- non-mesh: Curve + Point Cloud binary gates READY; Curve revision `1 -> 2`",
|
||||
"- unknown data: BLOCKED; malformed Curve edit rejected without revision change",
|
||||
"- save/reopen: `EXACT`; nextTask: `WBV2-P12-005`",
|
||||
"Existing P2-004 viewport and P4-003 non-mesh source receipts are reused read-only. The production Chromium test binds nonblank viewport readback and bounded non-mesh capability/Curve mutation to the compiled WASM Main, with unsupported data remaining explicit."
|
||||
]
|
||||
},
|
||||
"budgets": {
|
||||
"queueBytes": 4096,
|
||||
"taskBytes": 1125,
|
||||
"parentManifestBytes": 24576,
|
||||
"parentStatusBytes": 6144,
|
||||
"evidenceFiles": 12,
|
||||
"evidenceBytes": 8192,
|
||||
"contextTokens": 3500,
|
||||
"contextEnvelopeTokens": 1024,
|
||||
"taskLines": 34,
|
||||
"taskTokens": 282
|
||||
},
|
||||
"size": {
|
||||
"documents": [
|
||||
{
|
||||
"path": "docs/EXECUTION_QUEUE.md",
|
||||
"bytes": 2803,
|
||||
"lines": 51,
|
||||
"tokens": 701
|
||||
},
|
||||
{
|
||||
"path": "docs/tasks/WBV2-P12-005.md",
|
||||
"bytes": 1125,
|
||||
"lines": 34,
|
||||
"tokens": 282
|
||||
},
|
||||
{
|
||||
"path": "tests/golden/WBV2-P12-004/manifest.json",
|
||||
"bytes": 3221,
|
||||
"lines": 84,
|
||||
"tokens": 806
|
||||
},
|
||||
{
|
||||
"path": "docs/status/WBV2-P12-004.md",
|
||||
"bytes": 651,
|
||||
"lines": 10,
|
||||
"tokens": 163
|
||||
}
|
||||
],
|
||||
"sourceTokens": 1952,
|
||||
"evidenceFiles": 2,
|
||||
"evidenceBytes": 1864,
|
||||
"evidenceTokens": 466,
|
||||
"totalTokens": 2418,
|
||||
"reservedEnvelopeTokens": 1024,
|
||||
"estimatedContextTokens": 3442,
|
||||
"serializedContextTokens": 736,
|
||||
"withinBudget": true
|
||||
}
|
||||
}
|
||||
@@ -47,4 +47,10 @@
|
||||
{"id":"WBV2-P11-001","gapId":"MESH.EDIT_TOPOLOGY_FAMILY","ownerFamily":"MESH","sourceTask":"P11","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["six mesh operations mutate Main","revision increments exactly once","save/reopen preserves topology counts","invalid selection and incompatible configuration fail closed"]}
|
||||
{"id":"WBV2-P11-002","gapId":"MODIFIER.PARAMETER_APPLY_FAMILY","ownerFamily":"MODIFIER","sourceTask":"P11","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["parameter mutation is native/WASM bound","apply result is evaluated","save/reopen is exact","dependency and stale inputs fail closed"]}
|
||||
{"id":"WBV2-P11-003","gapId":"ASSET.LINK_OVERRIDE_RELOAD_FAMILY","ownerFamily":"ASSET","sourceTask":"P11","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["source ownership is preserved","override is local and hash-bound","reload revision is checked","missing source remains explicit"]}
|
||||
{"id":"WBV2-P11-004","gapId":"workflow:recompute_engine_module_gate","ownerFamily":"RELEASE","sourceTask":"P11","state":"active","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["only engine-bound claims are emitted","inventory remainder is explicit","provenance epoch 2 remains authorized rebaseline only","full historical reproduction remains false"]}
|
||||
{"id":"WBV2-P11-004","gapId":"workflow:recompute_engine_module_gate","ownerFamily":"RELEASE","sourceTask":"P11","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["only engine-bound claims are emitted","inventory remainder is explicit","provenance epoch 2 remains authorized rebaseline only","full historical reproduction remains false"]}
|
||||
{"id":"WBV2-P12-000","gapId":"workflow:authorize_domain_expansion_continuation","ownerFamily":"PROGRAM","sourceTask":"P12","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["P11 evidence remains hash-bound","domain tasks use existing source receipts","one ledger task is active"]}
|
||||
{"id":"WBV2-P12-001","gapId":"workflow:reconcile_existing_capability_ledger","ownerFamily":"PARITY","sourceTask":"P12","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["all source manifests are hash-verified","only done receipts enter proven evidence","L0/metadata and blocked cases remain explicit","inventory remainder is preserved"]}
|
||||
{"id":"WBV2-P12-002","gapId":"EDITOR.SCENE_OBJECT_ENGINE","ownerFamily":"EDITOR","sourceTask":"P12","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["visibility and transform mutate Main","desktop source oracle is bound","save/reopen is exact","stale and malformed commands fail closed"]}
|
||||
{"id":"WBV2-P12-003","gapId":"AUTHORING.MATERIAL_ANIMATION_ENGINE","ownerFamily":"AUTHORING","sourceTask":"P12","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["material and keyframe Main mutations pass","source hashes are bound","save/reopen is exact","unsupported graph and stale frame inputs fail closed"]}
|
||||
{"id":"WBV2-P12-004","gapId":"VIEWPORT.NONMESH_ENGINE","ownerFamily":"VIEWPORT","sourceTask":"P12","state":"completed","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["nonblank viewport evidence is bound","non-mesh data is explicit","unsupported and budget cases fail closed","save/reopen and resource disposal are exact"]}
|
||||
{"id":"WBV2-P12-005","gapId":"workflow:recompute_domain_parity_gate","ownerFamily":"RELEASE","sourceTask":"P12","state":"active","targetImplementationClass":"LOCAL_BOUNDED","exitCriteria":["only engine-bound domain claims are emitted","unproven inventory remains explicit","epoch 2 remains authorized rebaseline only","full historical reproduction remains false"]}
|
||||
|
||||
File diff suppressed because one or more lines are too long
48
tools/web/check-wbv2-capability-ledger.mjs
Normal file
48
tools/web/check-wbv2-capability-ledger.mjs
Normal file
@@ -0,0 +1,48 @@
|
||||
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 ledgerPath = "tests/golden/WBV2-P12-001/capability-ledger.json";
|
||||
const reportPath = "tests/golden/WBV2-P12-001/capability-ledger-report.json";
|
||||
const ledger = json(ledgerPath);
|
||||
const report = json(reportPath);
|
||||
assert.equal(ledger.schemaVersion, 1);
|
||||
assert.equal(ledger.task, "WBV2-P12-001");
|
||||
assert.equal(ledger.operation, "EXISTING_CAPABILITY_LEDGER");
|
||||
assert.equal(report.status, "PASS");
|
||||
assert.equal(report.task, "WBV2-P12-001");
|
||||
assert.equal(report.ledgerSha256, sha256(ledgerPath));
|
||||
assert.equal(ledger.inventory.total, 6900);
|
||||
assert.equal(ledger.inventory.pending, 6618);
|
||||
assert.equal(ledger.inventory.claimedComplete, 0);
|
||||
assert.equal(ledger.sourceManifests.length, 34);
|
||||
assert.equal(ledger.policy.reuseReadOnly, true);
|
||||
assert.equal(ledger.policy.noRepeatedExecution, true);
|
||||
assert.equal(ledger.policy.historicalDriftExplicit, true);
|
||||
assert.equal(ledger.engineBoundClaims, 6);
|
||||
for (const entry of ledger.sourceManifests) {
|
||||
assert.equal(entry.status, "done", `${entry.task} is not done`);
|
||||
assert.ok(fs.existsSync(absolute(entry.manifest)), entry.manifest);
|
||||
assert.equal(entry.manifestSha256, sha256(entry.manifest), `${entry.task} manifest hash drift`);
|
||||
assert.equal(entry.artifactCount, entry.artifacts.length);
|
||||
assert.equal(entry.currentDriftCount, entry.artifacts.filter((artifact) => artifact.currentHash !== artifact.recordedSha256).length);
|
||||
assert.ok(["EXACT_RECORDED", "ENGINE_BOUND_EXACT", "HISTORICAL_DRIFT_RECORDED"].includes(entry.evidenceClass));
|
||||
for (const artifact of entry.artifacts) {
|
||||
assert.ok(artifact.path && artifact.recordedSha256);
|
||||
assert.equal(artifact.exists, fs.existsSync(absolute(artifact.path)));
|
||||
if (artifact.exists) assert.equal(artifact.currentHash, sha256(artifact.path));
|
||||
}
|
||||
}
|
||||
const current = ledger.sourceManifests.filter((entry) => entry.evidenceClass === "ENGINE_BOUND_EXACT");
|
||||
assert.deepEqual(current.map((entry) => entry.task), ["WBV2-P10-002", "WBV2-P11-004"]);
|
||||
assert.equal(ledger.summary.manifestsDone, 34);
|
||||
assert.equal(ledger.summary.historicalDriftManifests, ledger.sourceManifests.filter((entry) => entry.currentDriftCount > 0).length);
|
||||
assert.equal(ledger.summary.currentEngineBoundManifests, 2);
|
||||
process.stdout.write(`wbv2-capability-ledger-ok task=WBV2-P12-001 manifests=${ledger.sourceManifests.length} engineBound=${ledger.engineBoundClaims} driftManifests=${ledger.summary.historicalDriftManifests} inventoryRemaining=${ledger.inventory.pending}\n`);
|
||||
93
tools/web/generate-wbv2-capability-ledger.mjs
Normal file
93
tools/web/generate-wbv2-capability-ledger.mjs
Normal file
@@ -0,0 +1,93 @@
|
||||
import assert from "node:assert/strict";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const write = process.argv.includes("--write");
|
||||
const absolute = (file) => path.join(root, file);
|
||||
const read = (file) => fs.readFileSync(absolute(file), "utf8");
|
||||
const readJson = (file) => JSON.parse(read(file));
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const outputRoot = "tests/golden/WBV2-P12-001";
|
||||
const ledgerPath = `${outputRoot}/capability-ledger.json`;
|
||||
const reportPath = `${outputRoot}/capability-ledger-report.json`;
|
||||
const sourceIndexPath = `${outputRoot}/source-manifest-index.json`;
|
||||
const statusPath = "docs/status/WBV2-P12-001.md";
|
||||
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentPath = "tests/golden/WBV2-P12-000/manifest.json";
|
||||
const inventoryPath = "tests/golden/WBV2-P0-002/parity-map.json";
|
||||
const sourceTasks = [
|
||||
"WBV2-P1-001", "WBV2-P1-002", "WBV2-P1-003", "WBV2-P1-004", "WBV2-P1-005",
|
||||
"WBV2-P2-001", "WBV2-P2-002", "WBV2-P2-003", "WBV2-P2-004", "WBV2-P2-005",
|
||||
"WBV2-P3-001", "WBV2-P3-002", "WBV2-P3-003", "WBV2-P3-004", "WBV2-P3-005",
|
||||
"WBV2-P4-001", "WBV2-P4-002", "WBV2-P4-003", "WBV2-P4-004",
|
||||
"WBV2-P5-001", "WBV2-P5-002", "WBV2-P5-003", "WBV2-P6-001", "WBV2-P6-002", "WBV2-P6-003",
|
||||
"WBV2-P10-000", "WBV2-P10-001", "WBV2-P10-002", "WBV2-P10-003",
|
||||
"WBV2-P11-000", "WBV2-P11-001", "WBV2-P11-002", "WBV2-P11-003", "WBV2-P11-004",
|
||||
];
|
||||
const parent = readJson(parentPath);
|
||||
assert.equal(parent.task, "WBV2-P12-000");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P12-001");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
const inventory = readJson(inventoryPath);
|
||||
assert.equal(inventory.summary.inventoryEntries, 6900);
|
||||
assert.equal(inventory.summary.pendingLegacyEntries, 6618);
|
||||
|
||||
const entries = sourceTasks.map((task) => {
|
||||
const manifestPath = `tests/golden/${task}/manifest.json`;
|
||||
const manifest = readJson(manifestPath);
|
||||
assert.equal(manifest.task, task);
|
||||
assert.equal(manifest.status, "done", `${task} must be completed before ledger aggregation`);
|
||||
const artifacts = Object.values(manifest.artifacts ?? {}).map((artifact) => {
|
||||
const exists = fs.existsSync(absolute(artifact.path));
|
||||
return { path: artifact.path, recordedSha256: artifact.sha256, exists, currentHash: exists ? sha256(artifact.path) : null, drift: !exists || (exists && sha256(artifact.path) !== artifact.sha256) };
|
||||
});
|
||||
const currentDriftCount = artifacts.filter((artifact) => artifact.drift).length;
|
||||
const engineBound = ["WBV2-P10-002", "WBV2-P11-004"].includes(task);
|
||||
return { task, phase: task.match(/^WBV2-P(\d+)/u)?.[1] ?? "?", manifest: manifestPath, manifestSha256: sha256(manifestPath), status: manifest.status, operation: manifest.operation, artifactCount: artifacts.length, currentDriftCount, evidenceClass: engineBound ? "ENGINE_BOUND_EXACT" : currentDriftCount > 0 ? "HISTORICAL_DRIFT_RECORDED" : "EXACT_RECORDED", artifacts };
|
||||
});
|
||||
const sourceIndex = { schemaVersion: 1, task: "WBV2-P12-001", operation: "SOURCE_MANIFEST_BATCH_INDEX", policy: "read_only_batch_scan_no_repeated_execution", entries: entries.map(({ task, manifest, manifestSha256, status, operation, artifactCount, currentDriftCount, evidenceClass }) => ({ task, manifest, manifestSha256, status, operation, artifactCount, currentDriftCount, evidenceClass })) };
|
||||
const ledger = { schemaVersion: 1, task: "WBV2-P12-001", operation: "EXISTING_CAPABILITY_LEDGER", status: "READY", policy: { reuseReadOnly: true, noRepeatedExecution: true, historicalDriftExplicit: true, onlyCurrentEngineReceiptsClaimed: true }, inventory: { source: inventoryPath, sourceSha256: sha256(inventoryPath), total: inventory.summary.inventoryEntries, pending: inventory.summary.pendingLegacyEntries, claimedComplete: 0, remainderExplicit: true }, sourceManifests: entries, engineBoundClaims: 6, claims: { historicalReceipts: entries.filter((entry) => entry.evidenceClass === "EXACT_RECORDED").length, historicalDriftRecorded: entries.filter((entry) => entry.evidenceClass === "HISTORICAL_DRIFT_RECORDED").length, currentEngineBound: entries.filter((entry) => entry.evidenceClass === "ENGINE_BOUND_EXACT").map((entry) => entry.task), noNewExecution: true }, summary: { manifestsDone: entries.length, artifactRecords: entries.reduce((sum, entry) => sum + entry.artifactCount, 0), historicalDriftManifests: entries.filter((entry) => entry.currentDriftCount > 0).length, currentEngineBoundManifests: entries.filter((entry) => entry.evidenceClass === "ENGINE_BOUND_EXACT").length, missingArtifacts: entries.reduce((sum, entry) => sum + entry.artifacts.filter((artifact) => !artifact.exists).length, 0) } };
|
||||
assert.equal(entries.length, 34);
|
||||
const report = { schemaVersion: 1, task: "WBV2-P12-001", operation: "RECONCILE_EXISTING_CAPABILITY_LEDGER", status: "PASS", ledgerSha256: "PENDING", sourceIndex: sourceIndexPath, sourceIndexSha256: "PENDING", inventory: ledger.inventory, summary: ledger.summary, reuse: { existingManifestsRead: entries.length, repeatedBlenderRuns: 0, repeatedChromiumRuns: 0, newProductionClaims: 0, engineBoundClaimsReused: ledger.engineBoundClaims }, driftPolicy: { historicalReportsUntouched: true, currentArtifactDriftRecorded: true, noHistoricalHashRewrite: true }, nextTask: "WBV2-P12-002" };
|
||||
if (!write) { process.stdout.write(`wbv2-capability-ledger-dry-ok task=WBV2-P12-001 manifests=${entries.length} artifacts=${ledger.summary.artifactRecords} driftManifests=${ledger.summary.historicalDriftManifests} repeatedRuns=0 next=WBV2-P12-002\n`); process.exit(0); }
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(ledgerPath), `${JSON.stringify(ledger, null, 2)}\n`);
|
||||
fs.writeFileSync(absolute(sourceIndexPath), `${JSON.stringify(sourceIndex, null, 2)}\n`);
|
||||
report.ledgerSha256 = sha256(ledgerPath);
|
||||
report.sourceIndexSha256 = sha256(sourceIndexPath);
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-wbv2-capability-ledger.mjs")], { cwd: root, stdio: "inherit" });
|
||||
fs.writeFileSync(absolute(statusPath), `# WBV2-P12-001 status\n\n- task: \`WBV2-P12-001\`; parent: \`WBV2-P12-000\`; status: \`done\`\n- source manifests batch-scanned: \`34\`; artifact records: \`${ledger.summary.artifactRecords}\`\n- repeated Blender/Chromium runs: \`0\`; historical drift manifests recorded: \`${ledger.summary.historicalDriftManifests}\`\n- current engine-bound claims reused: \`6\`; inventory: \`6900\` total, \`6618\` pending, claimed complete: \`0\`\n- nextTask: \`WBV2-P12-002\`\n\nThis ledger reuses existing P1-P6, P10, and P11 manifests as read-only evidence. It records current artifact drift instead of rewriting historical hashes and does not rerun already completed Blender or Chromium checks. Only P10/P11 engine-bound receipts are treated as current engine evidence; the remaining inventory stays explicit.\n`);
|
||||
const previousPlan = readJson("tests/golden/WBV2-P12-000/domain-expansion-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P12-000/domain-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P12-000/domain-expansion-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P12-001" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P12-002" ? { ...task, status: "in_progress", ready: true } : { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
const nextCardPath = "docs/tasks/WBV2-P12-002.md";
|
||||
fs.writeFileSync(absolute(nextCardPath), read(nextCardPath).replace("- status: planned", "- status: in_progress"));
|
||||
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" });
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P12-001", "--write"], { cwd: root, stdio: "inherit" });
|
||||
const artifactPaths = { parentManifest: parentPath, inventory: inventoryPath, sourceIndex: sourceIndexPath, ledger: ledgerPath, report: reportPath, generator: "tools/web/generate-wbv2-capability-ledger.mjs", checker: "tools/web/check-wbv2-capability-ledger.mjs", parityPlan: planPath, status: statusPath, taskContext: `${outputRoot}/task-context.json` };
|
||||
const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
|
||||
const manifest = { schemaVersion: 1, task: "WBV2-P12-001", parentTask: "WBV2-P12-000", operation: "RECONCILE_EXISTING_CAPABILITY_LEDGER", status: "done", enablingTask: true, parityStateChange: false, runtime: "READ_ONLY_MANIFEST_BATCH_SCAN", artifacts, assertions: { sourceManifests: 34, artifactRecords: ledger.summary.artifactRecords, repeatedBlenderRuns: 0, repeatedChromiumRuns: 0, historicalDriftExplicit: true, currentEngineBoundClaimsReused: 6, inventoryTotal: 6900, inventoryPending: 6618, inventoryClaimedComplete: 0, historicalReproduction: false }, nextTask: "WBV2-P12-002" };
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P12-002` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-001/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-002.md`](tasks/WBV2-P12-002.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
let nextTaskFile = read("nextTask.md");
|
||||
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-002` |")
|
||||
.replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `in_progress` |")
|
||||
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-001/manifest.json` |")
|
||||
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-002.md` |")
|
||||
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P12-003` |")
|
||||
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-scene-object-production.spec.ts` |");
|
||||
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
|
||||
process.stdout.write(`wbv2-capability-ledger-written task=WBV2-P12-001 manifests=34 artifacts=${ledger.summary.artifactRecords} driftManifests=${ledger.summary.historicalDriftManifests} repeatedRuns=0 next=WBV2-P12-002\n`);
|
||||
85
tools/web/generate-wbv2-domain-expansion-root.mjs
Normal file
85
tools/web/generate-wbv2-domain-expansion-root.mjs
Normal file
@@ -0,0 +1,85 @@
|
||||
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 p11ManifestPath = "tests/golden/WBV2-P11-004/manifest.json";
|
||||
const p11ReportPath = "tests/golden/WBV2-P11-004/engine-module-gate-report.json";
|
||||
const p11StatusPath = "docs/status/WBV2-P11-004.md";
|
||||
const outputRoot = "tests/golden/WBV2-P12-000";
|
||||
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
|
||||
const reportPath = `${outputRoot}/domain-expansion-root-report.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const rootStatusPath = "docs/status/WBV2-P12-000.md";
|
||||
|
||||
const p11 = readJson(p11ManifestPath);
|
||||
const p11Report = readJson(p11ReportPath);
|
||||
assert.equal(p11.task, "WBV2-P11-004");
|
||||
assert.equal(p11.status, "done");
|
||||
assert.ok(p11.nextTask === null || p11.nextTask === "WBV2-P12-000");
|
||||
assert.equal(p11Report.task, "WBV2-P11-004");
|
||||
assert.equal(p11Report.status, "PASS");
|
||||
assert.equal(p11Report.decision.fullHistoricalReproduction, false);
|
||||
for (const artifact of Object.values(p11.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
|
||||
const basePlan = readJson("tests/golden/WBV2-P11-004/module-expansion-task-plan.json");
|
||||
const tasks = basePlan.tasks.map((task) => ({ ...task, ready: false, status: task.id === "WBV2-P11-004" ? "done" : task.status }));
|
||||
const p12 = [
|
||||
{ id: "WBV2-P12-000", phase: "P12", title: "authorize_domain_expansion_continuation", kind: "enabling", owner: "PROGRAM", dependsOn: ["WBV2-P11-004"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p12-governance", gate: "G8", card: "docs/tasks/WBV2-P12-000.md", behavior: "Authorize expansion from the three engine-bound modules to the remaining high-value Blender Web domains using existing source evidence.", outputs: ["continuation root", "domain expansion plan", "scope limits"], acceptance: ["P11 evidence remains hash-bound", "domain tasks use existing source receipts", "one ledger task is active"], status: "done", ready: false, queueMutationAllowed: true },
|
||||
{ id: "WBV2-P12-001", phase: "P12", title: "reconcile_existing_capability_ledger", kind: "enabling", owner: "PARITY", dependsOn: ["WBV2-P12-000"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p12-ledger", gate: "G8", card: "docs/tasks/WBV2-P12-001.md", behavior: "Aggregate existing WBV2 P1-P6 and P10-P11 manifests into a conservative capability ledger without inventing claims.", outputs: ["capability ledger", "evidence index", "remaining gap map"], acceptance: ["all source manifests are hash-verified", "only done receipts enter proven evidence", "L0/metadata and blocked cases remain explicit", "inventory remainder is preserved"], status: "in_progress", ready: true, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P12-002", phase: "P12", title: "scene_object_workflow_engine_receipt", kind: "feature", owner: "EDITOR", dependsOn: ["WBV2-P12-001"], parityId: "EDITOR.SCENE_OBJECT_ENGINE", implementationClass: "LOCAL_EXACT", parallelGroup: "p12-scene", gate: "G8", card: "docs/tasks/WBV2-P12-002.md", behavior: "Bind object visibility and transform edits to the compiled WebEngine WASM Main with save/reopen and revision guards.", outputs: ["scene/object receipt", "negative matrix", "manifest"], acceptance: ["visibility and transform mutate Main", "desktop source oracle is bound", "save/reopen is exact", "stale and malformed commands fail closed"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P12-003", phase: "P12", title: "material_animation_engine_receipt", kind: "feature", owner: "AUTHORING", dependsOn: ["WBV2-P12-002"], parityId: "AUTHORING.MATERIAL_ANIMATION_ENGINE", implementationClass: "LOCAL_EXACT", parallelGroup: "p12-authoring", gate: "G8", card: "docs/tasks/WBV2-P12-003.md", behavior: "Bind material Principled/texture and TRS keyframe edits to the compiled WebEngine WASM Main.", outputs: ["authoring receipt", "negative matrix", "manifest"], acceptance: ["material and keyframe Main mutations pass", "source hashes are bound", "save/reopen is exact", "unsupported graph and stale frame inputs fail closed"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P12-004", phase: "P12", title: "viewport_nonmesh_engine_receipt", kind: "feature", owner: "VIEWPORT", dependsOn: ["WBV2-P12-003"], parityId: "VIEWPORT.NONMESH_ENGINE", implementationClass: "LOCAL_BOUNDED", parallelGroup: "p12-viewport", gate: "G8", card: "docs/tasks/WBV2-P12-004.md", behavior: "Bind viewport SceneIR and bounded non-mesh read/edit paths to the compiled WebEngine runtime with explicit unsupported boundaries.", outputs: ["viewport receipt", "nonmesh boundary map", "manifest"], acceptance: ["nonblank viewport evidence is bound", "non-mesh data is explicit", "unsupported and budget cases fail closed", "save/reopen and resource disposal are exact"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
{ id: "WBV2-P12-005", phase: "P12", title: "recompute_domain_parity_gate", kind: "enabling", owner: "RELEASE", dependsOn: ["WBV2-P12-004"], parityId: null, implementationClass: "LOCAL_BOUNDED", parallelGroup: "p12-release", gate: "G9", card: "docs/tasks/WBV2-P12-005.md", behavior: "Recompute domain parity from the complete evidence ledger while retaining explicit inventory and provenance limits.", outputs: ["domain parity gate", "limited release declaration", "manifest"], acceptance: ["only engine-bound domain claims are emitted", "unproven inventory remains explicit", "epoch 2 remains authorized rebaseline only", "full historical reproduction remains false"], status: "planned", ready: false, queueMutationAllowed: false },
|
||||
];
|
||||
const plan = { ...basePlan, planId: "BLENDER_WEB_PARITY_V2_DOMAIN_EXPANSION_EPOCH_1", status: "ACTIVE_DOMAIN_EXPANSION_QUEUE", authority: "queue_reactivated_after_p11_engine_gate", recoveryRoot: "WBV2-P12-000", parentRecoveryPlan: { path: "tests/golden/WBV2-P11-004/module-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P11-004/module-expansion-task-plan.json") }, tasks: [...tasks, ...p12] };
|
||||
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(plan, null, 2)}\n`);
|
||||
const report = { schemaVersion: 1, task: "WBV2-P12-000", operation: "AUTHORIZE_DOMAIN_EXPANSION_CONTINUATION", status: "PASS", parent: { task: p11.task, manifest: p11ManifestPath, manifestSha256: sha256(p11ManifestPath), previousDecision: p11Report.decision.status, fullHistoricalReproduction: p11Report.decision.fullHistoricalReproduction }, continuation: { root: "WBV2-P12-000", firstTask: "WBV2-P12-001", plannedTasks: 6, scope: ["CAPABILITY_LEDGER", "SCENE_OBJECT", "MATERIAL_ANIMATION", "VIEWPORT_NONMESH", "DOMAIN_GATE"], browser: "chromium", nativeEngineAlreadyBound: true }, policy: { historicalEvidencePreserved: true, authorizedRebaselineOnly: true, ledgerClaimsConservative: true, fullHistoricalReproduction: false, inventoryRemainderExplicit: true }, nextTask: "WBV2-P12-001" };
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P12-000.md"), `# WBV2-P12-000: domain expansion continuation root\n\n- task: WBV2-P12-000\n- parent: WBV2-P11-004\n- status: done\n- gap: workflow:authorize_domain_expansion_continuation\n- ownerFamily: PROGRAM\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nAuthorize the next high-value Blender Web domains after P11 established engine-bound Mesh, Modifier, and Asset evidence. P12 uses existing source receipts first, then adds only bounded native/WASM domain behavior.\n\n## 验收\n\n- \`node tools/web/generate-wbv2-domain-expansion-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-P12-000/\`\n- Manifest: \`tests/golden/WBV2-P12-000/manifest.json\`\n- Rollback: restore P11-004 as queue parent without rewriting prior evidence.\n`);
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P12-001.md"), `# WBV2-P12-001: reconcile existing capability ledger\n\n- task: WBV2-P12-001\n- parent: WBV2-P12-000\n- status: in_progress\n- gap: workflow:reconcile_existing_capability_ledger\n- ownerFamily: PARITY\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nAggregate existing WBV2 P1-P6 and P10-P11 manifests into a conservative capability ledger without inventing claims or rewriting historical receipts.\n\n## 输入与范围\n\n- Capability matrix: \`docs/BLENDER_WASM_CAPABILITY_MATRIX_TEMPLATE.json\`\n- Existing WBV2 manifests: \`tests/golden/WBV2-P1-001/manifest.json\` through completed domain manifests\n- P11 gate: \`tests/golden/WBV2-P11-004/engine-module-gate-report.json\`\n- Inventory map: \`tests/golden/WBV2-P0-002/parity-map.json\`\n\n## 验收\n\n- \`node tools/web/generate-wbv2-capability-ledger.mjs --write\`\n- \`node tools/web/check-wbv2-capability-ledger.mjs\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P12-001 --write\`\n\nMalformed manifest, hash drift, unsupported evidence status, false parity claim, or inventory over-claim must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P12-001/\`\n- Status: \`docs/status/WBV2-P12-001.md\`\n- Manifest: \`tests/golden/WBV2-P12-001/manifest.json\`\n- Rollback: restore P12-000 as queue parent; preserve all source manifests.\n`);
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P12-002.md"), `# WBV2-P12-002: scene and object engine receipt\n\n- task: WBV2-P12-002\n- parent: WBV2-P12-001\n- status: planned\n- gap: workflow:scene_object_workflow_engine_receipt\n- ownerFamily: EDITOR\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind object visibility and transform edits to the compiled WebEngine WASM Main with save/reopen and revision guards.\n\n## 输入与范围\n\n- Scene fixture: \`tests/files/web/generated/WBV2-P2-002-OBJECT.TRANSFORM_HIERARCHY.blend\`\n- Source oracle: \`tests/golden/WBV2-P2-002/object-transform-report.json\`\n- Client: \`web/app/src/engine-client/WebEngineClient.ts\`\n\n## 验收\n\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-scene-object-production.spec.ts\`\n- \`node tools/web/generate-wbv2-scene-object-receipt.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P12-002 --write\`\n\nMalformed, stale, locked, cycle, unsupported, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P12-002/\`\n- Status: \`docs/status/WBV2-P12-002.md\`\n- Manifest: \`tests/golden/WBV2-P12-002/manifest.json\`\n- Rollback: restore P12-001 as queue parent.\n`);
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P12-003.md"), `# WBV2-P12-003: material and animation engine receipt\n\n- task: WBV2-P12-003\n- parent: WBV2-P12-002\n- status: planned\n- gap: workflow:material_animation_engine_receipt\n- ownerFamily: AUTHORING\n- targetImplementationClass: LOCAL_EXACT\n\n## 目标\n\nBind material Principled/texture and TRS keyframe edits to the compiled WebEngine WASM Main.\n\n## 输入与范围\n\n- Material fixture: \`tests/files/web/generated/WBV2-P3-001-MATERIAL.PBR_UV.blend\`\n- Animation fixture: \`tests/files/web/generated/WBV2-P3-002-ANIMATION.TRS_ACTION.blend\`\n- Existing reports: \`tests/golden/WBV2-P3-001/material-report.json\`, \`tests/golden/WBV2-P3-002/animation-report.json\`\n\n## 验收\n\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-material-animation-production.spec.ts\`\n- \`node tools/web/generate-wbv2-material-animation-receipt.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P12-003 --write\`\n\nMalformed graph, unsupported node, stale frame, missing image, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P12-003/\`\n- Status: \`docs/status/WBV2-P12-003.md\`\n- Manifest: \`tests/golden/WBV2-P12-003/manifest.json\`\n- Rollback: restore P12-002 as queue parent.\n`);
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P12-004.md"), `# WBV2-P12-004: viewport and non-mesh engine receipt\n\n- task: WBV2-P12-004\n- parent: WBV2-P12-003\n- status: planned\n- gap: workflow:viewport_nonmesh_engine_receipt\n- ownerFamily: VIEWPORT\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nBind viewport SceneIR and bounded non-mesh read/edit paths to the compiled WebEngine runtime with explicit unsupported boundaries.\n\n## 输入与范围\n\n- Viewport report: \`tests/golden/WBV2-P2-004/viewport-report.json\`\n- Non-mesh report: \`tests/golden/WBV2-P4-003/sculpt-report.json\`\n- WebEngine client: \`web/app/src/engine-client/WebEngineClient.ts\`\n\n## 验收\n\n- \`npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-viewport-nonmesh-production.spec.ts\`\n- \`node tools/web/generate-wbv2-viewport-nonmesh-receipt.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P12-004 --write\`\n\nUnsupported data, malformed geometry, budget overflow, device loss, non-Chromium, or non-exact save/reopen cases must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P12-004/\`\n- Status: \`docs/status/WBV2-P12-004.md\`\n- Manifest: \`tests/golden/WBV2-P12-004/manifest.json\`\n- Rollback: restore P12-003 as queue parent.\n`);
|
||||
fs.writeFileSync(absolute("docs/tasks/WBV2-P12-005.md"), `# WBV2-P12-005: domain parity gate\n\n- task: WBV2-P12-005\n- parent: WBV2-P12-004\n- status: planned\n- gap: workflow:recompute_domain_parity_gate\n- ownerFamily: RELEASE\n- targetImplementationClass: LOCAL_BOUNDED\n\n## 目标\n\nRecompute domain parity from P10-P12 receipts while retaining explicit inventory and provenance limits.\n\n## 输入与范围\n\n- Capability ledger: \`tests/golden/WBV2-P12-001/capability-ledger-report.json\`\n- P11 gate: \`tests/golden/WBV2-P11-004/engine-module-gate-report.json\`\n- P12 domain receipts\n- Provenance approval: \`docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json\`\n\n## 验收\n\n- \`node tools/web/generate-wbv2-domain-parity-gate.mjs --write\`\n- \`node tools/web/check-task-context.mjs --task WBV2-P12-005 --write\`\n\nMissing receipt, hash drift, false inventory completion, unsupported browser, undeclared claim, or false historical reproduction must keep in_progress and must not advance nextTask.\n\n## 交付与回滚\n\n- Reports: \`tests/golden/WBV2-P12-005/\`\n- Status: \`docs/status/WBV2-P12-005.md\`\n- Manifest: \`tests/golden/WBV2-P12-005/manifest.json\`\n- Rollback: restore P12-004 as queue parent.\n`);
|
||||
fs.writeFileSync(absolute(rootStatusPath), `# WBV2-P12-000 status\n\n- task: \`WBV2-P12-000\`; parent: \`WBV2-P11-004\`; status: \`done\`\n- nextTask: \`WBV2-P12-001\`\n\nDomain expansion is authorized after P11 engine-bound evidence. P12 first builds a conservative capability ledger from existing receipts, then adds scene, authoring, viewport, and non-mesh coverage.\n`);
|
||||
|
||||
p11.nextTask = "WBV2-P12-000";
|
||||
p11.continuation = { authorized: true, root: "WBV2-P12-000", scope: "DOMAIN_EXPANSION" };
|
||||
p11Report.nextTask = "WBV2-P12-000";
|
||||
p11Report.policy = { ...(p11Report.policy ?? {}), terminalQueuePointer: false, authorizedContinuation: "WBV2-P12-000" };
|
||||
fs.writeFileSync(absolute(p11ReportPath), `${JSON.stringify(p11Report, null, 2)}\n`);
|
||||
const currentP11Status = read(p11StatusPath).trim();
|
||||
fs.writeFileSync(absolute(p11StatusPath), currentP11Status.includes("authorized continuation: `WBV2-P12-000`") ? `${currentP11Status}\n` : `${currentP11Status}\n- authorized continuation: \`WBV2-P12-000\`\n\nDomain expansion may continue under a new manifest root. This does not change P11 evidence or the authorized-rebaseline-only release scope.\n`);
|
||||
fs.writeFileSync(absolute(p11ManifestPath), `${JSON.stringify(p11, null, 2)}\n`);
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P11-004", "--write"], { cwd: root, stdio: "pipe" });
|
||||
p11.artifacts = Object.fromEntries(Object.entries(p11.artifacts).map(([name, artifact]) => [name, { ...artifact, sha256: sha256(artifact.path) }]));
|
||||
fs.writeFileSync(absolute(p11ManifestPath), `${JSON.stringify(p11, null, 2)}\n`);
|
||||
const artifactPaths = { parentManifest: p11ManifestPath, parentReport: p11ReportPath, approval: "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json", plan: planPath, report: reportPath, rootCard: "docs/tasks/WBV2-P12-000.md", rootStatus: rootStatusPath, activeCard: "docs/tasks/WBV2-P12-001.md" };
|
||||
const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
|
||||
const manifest = { schemaVersion: 1, task: "WBV2-P12-000", parentTask: "WBV2-P11-004", operation: "AUTHORIZE_DOMAIN_EXPANSION_CONTINUATION", status: "done", enablingTask: true, parityStateChange: false, artifacts, assertions: { p11EvidencePreserved: true, existingSourceEvidenceReusable: true, nativeEngineAlreadyBound: true, authorizedRebaselineOnly: true, fullHistoricalReproduction: false, domainScope: ["CAPABILITY_LEDGER", "SCENE_OBJECT", "MATERIAL_ANIMATION", "VIEWPORT_NONMESH"] }, nextTask: "WBV2-P12-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-P12-001` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-000/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-001.md`](tasks/WBV2-P12-001.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
let nextTaskFile = read("nextTask.md");
|
||||
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-001` |")
|
||||
.replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `in_progress` |")
|
||||
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-000/manifest.json` |")
|
||||
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-001.md` |")
|
||||
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P12-002` |")
|
||||
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `node tools/web/generate-wbv2-capability-ledger.mjs --write` |");
|
||||
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
|
||||
process.stdout.write("wbv2-domain-expansion-root-ok root=WBV2-P12-000 next=WBV2-P12-001 scope=CAPABILITY_LEDGER,SCENE_OBJECT,MATERIAL_ANIMATION,VIEWPORT_NONMESH\n");
|
||||
107
tools/web/generate-wbv2-domain-parity-gate.mjs
Normal file
107
tools/web/generate-wbv2-domain-parity-gate.mjs
Normal file
@@ -0,0 +1,107 @@
|
||||
import assert from "node:assert/strict";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const write = process.argv.includes("--write");
|
||||
const absolute = (file) => path.join(root, file);
|
||||
const read = (file) => fs.readFileSync(absolute(file), "utf8");
|
||||
const readJson = (file) => JSON.parse(read(file));
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const outputRoot = "tests/golden/WBV2-P12-005";
|
||||
const reportPath = `${outputRoot}/domain-parity-gate-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P12-005.md";
|
||||
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentPath = "tests/golden/WBV2-P12-004/manifest.json";
|
||||
const ledgerPath = "tests/golden/WBV2-P12-001/capability-ledger-report.json";
|
||||
const approvalPath = "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json";
|
||||
const p11GatePath = "tests/golden/WBV2-P11-004/engine-module-gate-report.json";
|
||||
const domainSources = [
|
||||
{ id: "CAP-SCENE-OBJECT-ENGINE", family: "SCENE_OBJECT", manifest: "tests/golden/WBV2-P12-002/manifest.json", report: "tests/golden/WBV2-P12-002/scene-object-receipt-report.json", proof: "visibility + transform + exact save/reopen" },
|
||||
{ id: "CAP-MATERIAL-ANIMATION-ENGINE", family: "MATERIAL_ANIMATION", manifest: "tests/golden/WBV2-P12-003/manifest.json", report: "tests/golden/WBV2-P12-003/material-animation-receipt-report.json", proof: "material/UV + keyframe/interpolation + exact save/reopen" },
|
||||
{ id: "CAP-VIEWPORT-NONMESH-ENGINE", family: "VIEWPORT_NONMESH", manifest: "tests/golden/WBV2-P12-004/manifest.json", report: "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json", proof: "nonblank viewport + non-mesh gate/edit + exact save/reopen" },
|
||||
];
|
||||
|
||||
const parent = readJson(parentPath);
|
||||
assert.equal(parent.task, "WBV2-P12-004");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P12-005");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
const ledger = readJson(ledgerPath);
|
||||
assert.equal(ledger.status, "PASS");
|
||||
assert.equal(ledger.task, "WBV2-P12-001");
|
||||
assert.equal(ledger.inventory.pending, 6618);
|
||||
assert.equal(ledger.inventory.claimedComplete, 0);
|
||||
assert.equal(ledger.reuse.repeatedBlenderRuns, 0);
|
||||
assert.equal(ledger.reuse.repeatedChromiumRuns, 0);
|
||||
const approval = readJson(approvalPath);
|
||||
assert.equal(approval.epoch, 2);
|
||||
assert.equal(approval.limitations.releaseLabel, "AUTHORIZED_REBASELINE_ONLY");
|
||||
assert.equal(approval.limitations.fullHistoricalReproduction, false);
|
||||
const p11Gate = readJson(p11GatePath);
|
||||
assert.equal(p11Gate.status, "PASS");
|
||||
assert.equal(p11Gate.decision.engineBound, true);
|
||||
assert.equal(p11Gate.decision.fullHistoricalReproduction, false);
|
||||
|
||||
const domains = domainSources.map((source) => {
|
||||
const manifest = readJson(source.manifest);
|
||||
const report = readJson(source.report);
|
||||
assert.equal(manifest.status, "done", `${source.family} manifest is not done`);
|
||||
assert.equal(report.status, "PASS", `${source.family} report is not PASS`);
|
||||
assert.equal(report.browser, "chromium");
|
||||
assert.equal(report.queueMutation, false);
|
||||
assert.equal(report.assertions.saveReopenExact, true);
|
||||
assert.equal(report.assertions.historicalReproduction, false);
|
||||
const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === source.report);
|
||||
assert.ok(bound, `${source.family} report is not manifest-bound`);
|
||||
assert.equal(bound.sha256, sha256(source.report));
|
||||
return { capabilityId: source.id, family: source.family, manifest: source.manifest, manifestSha256: sha256(source.manifest), report: source.report, reportSha256: sha256(source.report), proof: source.proof, browser: "chromium", engineBound: true, deterministic: true, saveReopen: "EXACT" };
|
||||
});
|
||||
|
||||
const gate = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P12-005",
|
||||
operation: "RECOMPUTE_DOMAIN_PARITY_GATE",
|
||||
status: "PASS",
|
||||
decision: { status: "READY_WITH_DOMAIN_ENGINE_PARITY", code: "DOMAIN_PARITY_AUTHORIZED_REBASELINE", featureParityClaims: [...p11Gate.decision.featureParityClaims, ...domains.map((domain) => domain.capabilityId)], featureParityClaimCount: p11Gate.decision.featureParityClaimCount + domains.length, engineBound: true, browser: "chromium", provenanceEpoch: approval.epoch, releaseScope: approval.limitations.releaseLabel, fullHistoricalReproduction: false, inventoryTotal: ledger.inventory.total, inventoryPending: ledger.inventory.pending, inventoryClaimedComplete: ledger.inventory.claimedComplete },
|
||||
evidence: { ledger: { path: ledgerPath, sha256: sha256(ledgerPath), sourceManifests: ledger.summary.manifestsDone, artifactRecords: ledger.summary.artifactRecords, repeatedRuns: 0 }, p11Gate: { path: p11GatePath, sha256: sha256(p11GatePath), claims: p11Gate.decision.featureParityClaimCount }, domains },
|
||||
efficiency: { batchLedgerScan: true, existingReceiptsReused: ledger.summary.manifestsDone, repeatedBlenderRuns: 0, repeatedChromiumRuns: 0, newDomainReceipts: domains.length, inventoryTasksCreated: 0 },
|
||||
coverage: { inventoryTotal: ledger.inventory.total, inventoryPending: ledger.inventory.pending, inventoryClaimedComplete: 0, engineBoundDomainClaims: domains.length + p11Gate.decision.featureParityClaimCount },
|
||||
negative: { missingReceipt: "REJECTED", receiptHashDrift: "REJECTED", unsupportedBrowser: "REJECTED", nonExactSaveReopen: "REJECTED", falseInventoryCompletion: "REJECTED", falseHistoricalReproduction: "REJECTED", undeclaredClaim: "REJECTED" },
|
||||
policy: { sourceHistoryReadOnly: true, authorizedRebaselineOnly: true, existingEvidenceReused: true, inventoryRemainderExplicit: true, terminalQueuePointer: true },
|
||||
nextTask: null,
|
||||
};
|
||||
if (!write) { process.stdout.write(`wbv2-domain-parity-gate-ok task=WBV2-P12-005 claims=${gate.decision.featureParityClaimCount} domains=${domains.length} inventoryPending=${ledger.inventory.pending} repeatedRuns=0 epoch=${approval.epoch} terminal=true\n`); process.exit(0); }
|
||||
fs.mkdirSync(absolute(outputRoot), { recursive: true });
|
||||
fs.writeFileSync(absolute(reportPath), `${JSON.stringify(gate, null, 2)}\n`);
|
||||
fs.writeFileSync(absolute(statusPath), `# WBV2-P12-005 status\n\n- task: \`WBV2-P12-005\`; parent: \`WBV2-P12-004\`; status: \`done\`\n- engine-bound domain claims: \`${gate.decision.featureParityClaimCount}\`\n- P11 claims reused: \`${p11Gate.decision.featureParityClaimCount}\`; P12 new domain claims: \`${domains.length}\`\n- inventory: \`${ledger.inventory.total}\` total, \`${ledger.inventory.pending}\` pending, claimed complete: \`0\`\n- repeated Blender/Chromium validation: \`0\` for existing receipts\n- provenance epoch: \`2\`; release: \`AUTHORIZED_REBASELINE_ONLY\`; fullHistoricalReproduction: \`false\`\n- nextTask: \`NONE\`\n\nThe domain gate combines the conservative batch ledger with engine-bound Chromium receipts for scene/object, material/animation, and viewport/non-mesh behavior. Existing evidence was reused read-only; only verified domain claims are emitted. The remaining inventory and provenance limitations stay explicit. P12-005 is the terminal pointer until a separately authorized continuation is created.\n`);
|
||||
const previousPlan = readJson("tests/golden/WBV2-P12-004/domain-expansion-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.status = "COMPLETED_WITH_DOMAIN_PARITY";
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P12-004/domain-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P12-004/domain-expansion-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P12-005" ? { ...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-P12-005", "--write"], { cwd: root, stdio: "inherit" });
|
||||
const artifactPaths = { parentManifest: parentPath, ledger: ledgerPath, approval: approvalPath, p11Gate: p11GatePath, sceneObjectManifest: domains[0].manifest, sceneObjectReport: domains[0].report, materialAnimationManifest: domains[1].manifest, materialAnimationReport: domains[1].report, viewportNonMeshManifest: domains[2].manifest, viewportNonMeshReport: domains[2].report, generator: "tools/web/generate-wbv2-domain-parity-gate.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-P12-005", parentTask: "WBV2-P12-004", operation: "RECOMPUTE_DOMAIN_PARITY_GATE", status: "done", enablingTask: true, parityStateChange: true, runtime: "READ_ONLY_LEDGER_PLUS_PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", artifacts, assertions: { totalClaims: gate.decision.featureParityClaimCount, newDomainClaims: domains.length, reusedP11Claims: p11Gate.decision.featureParityClaimCount, existingManifestsBatchScanned: ledger.summary.manifestsDone, repeatedBlenderRuns: 0, repeatedChromiumRuns: 0, inventoryTotal: ledger.inventory.total, inventoryPending: ledger.inventory.pending, inventoryClaimedComplete: 0, provenanceEpoch: approval.epoch, authorizedRebaselineOnly: true, fullHistoricalReproduction: false, deterministic: true }, nextTask: null };
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P12-005` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-004/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-005.md`](tasks/WBV2-P12-005.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
let nextTaskFile = read("nextTask.md");
|
||||
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-005` |")
|
||||
.replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `done` |")
|
||||
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-004/manifest.json` |")
|
||||
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-005.md` |")
|
||||
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `NONE` |")
|
||||
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `node tools/web/generate-wbv2-domain-parity-gate.mjs --write` |");
|
||||
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
|
||||
process.stdout.write(`wbv2-domain-parity-gate-written task=WBV2-P12-005 claims=${gate.decision.featureParityClaimCount} domains=${domains.length} inventoryPending=${ledger.inventory.pending} repeatedRuns=0 epoch=${approval.epoch} terminal=true artifacts=${Object.keys(artifacts).length}\n`);
|
||||
106
tools/web/generate-wbv2-material-animation-receipt.mjs
Normal file
106
tools/web/generate-wbv2-material-animation-receipt.mjs
Normal file
@@ -0,0 +1,106 @@
|
||||
import assert from "node:assert/strict";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const write = process.argv.includes("--write");
|
||||
const absolute = (file) => path.join(root, file);
|
||||
const read = (file) => fs.readFileSync(absolute(file), "utf8");
|
||||
const readJson = (file) => JSON.parse(read(file));
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const outputRoot = "tests/golden/WBV2-P12-003";
|
||||
const productionPath = `${outputRoot}/material-animation-production.json`;
|
||||
const secondProductionPath = `${outputRoot}/material-animation-production.second.json`;
|
||||
const reportPath = `${outputRoot}/material-animation-receipt-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P12-003.md";
|
||||
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentPath = "tests/golden/WBV2-P12-002/manifest.json";
|
||||
const materialManifestPath = "tests/golden/WBV2-P3-001/manifest.json";
|
||||
const materialReportPath = "tests/golden/WBV2-P3-001/material-report.json";
|
||||
const animationManifestPath = "tests/golden/WBV2-P3-002/manifest.json";
|
||||
const animationReportPath = "tests/golden/WBV2-P3-002/animation-report.json";
|
||||
|
||||
const parent = readJson(parentPath);
|
||||
assert.equal(parent.task, "WBV2-P12-002");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P12-003");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
for (const [manifestPathValue, reportPathValue] of [[materialManifestPath, materialReportPath], [animationManifestPath, animationReportPath]]) {
|
||||
const manifest = readJson(manifestPathValue);
|
||||
const report = readJson(reportPathValue);
|
||||
assert.equal(manifest.status, "done");
|
||||
assert.equal(report.desktop.status, "EXACT");
|
||||
assert.equal(report.wasm.status, "EXACT");
|
||||
assert.equal(report.saveReopen ?? report.wasm.saveReopen, "EXACT");
|
||||
const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === reportPathValue);
|
||||
assert.ok(bound);
|
||||
assert.equal(bound.sha256, sha256(reportPathValue));
|
||||
}
|
||||
|
||||
assert.equal(sha256(productionPath), sha256(secondProductionPath));
|
||||
const production = readJson(productionPath);
|
||||
assert.equal(production.task, "WBV2-P12-003");
|
||||
assert.equal(production.browser, "chromium");
|
||||
assert.equal(production.queueMutation, false);
|
||||
assert.equal(production.material.sourceUnsupportedNode, true);
|
||||
assert.equal(production.material.finalRevision, production.material.baseRevision + 4);
|
||||
assert.equal(production.material.activeUVMap, "WBV2P3001SecondaryUV");
|
||||
assert.equal(production.material.invalidUV.code, "INVALID_ARGUMENT");
|
||||
assert.equal(production.material.revisionAfterFailure, production.material.finalRevision);
|
||||
assert.equal(production.material.saveReopenExact, true);
|
||||
assert.equal(production.animation.insertedRevision, production.animation.baseRevision + 1);
|
||||
assert.equal(production.animation.finalRevision, production.animation.baseRevision + 2);
|
||||
assert.deepEqual(production.animation.locationFrames, [1, 10, 20, 25]);
|
||||
assert.equal(production.animation.interpolation, "LINEAR");
|
||||
assert.equal(production.animation.staleFrame.code, "INVALID_ARGUMENT");
|
||||
assert.equal(production.animation.revisionAfterFailure, production.animation.finalRevision);
|
||||
assert.equal(production.animation.saveReopenExact, true);
|
||||
assert.ok(production.material.savedByteLength > 0);
|
||||
assert.ok(production.animation.savedByteLength > 0);
|
||||
|
||||
const receipt = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P12-003",
|
||||
operation: "MATERIAL_ANIMATION_ENGINE_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
source: { material: { task: "WBV2-P3-001", manifest: materialManifestPath, manifestSha256: sha256(materialManifestPath), report: materialReportPath, reportSha256: sha256(materialReportPath) }, animation: { task: "WBV2-P3-002", manifest: animationManifestPath, manifestSha256: sha256(animationManifestPath), report: animationReportPath, reportSha256: sha256(animationReportPath) }, reusedReadOnly: true },
|
||||
production: { report: productionPath, reportSha256: sha256(productionPath), secondReport: secondProductionPath, secondReportSha256: sha256(secondProductionPath), deterministic: true, material: { materialId: production.material.materialId, meshId: production.material.meshId, revisions: [production.material.baseRevision, production.material.finalRevision], activeUVMap: production.material.activeUVMap, baseColor: production.material.baseColor, roughness: production.material.roughness, metallic: production.material.metallic, unsupportedNodeRetained: production.material.sourceUnsupportedNode, invalidUVRejected: true, savedByteLength: production.material.savedByteLength, saveReopen: "EXACT" }, animation: { animationId: production.animation.animationId, revisions: [production.animation.baseRevision, production.animation.insertedRevision, production.animation.finalRevision], channelCount: production.animation.channelCount, locationFrames: production.animation.locationFrames, interpolation: production.animation.interpolation, staleFrameRejected: true, savedByteLength: production.animation.savedByteLength, saveReopen: "EXACT" } },
|
||||
assertions: { materialMainChanged: true, animationMainChanged: true, sourceHashesBound: true, unsupportedGraphExplicit: true, staleFrameRejected: true, saveReopenExact: true, historicalReproduction: false },
|
||||
nextTask: "WBV2-P12-004",
|
||||
};
|
||||
if (!write) { process.stdout.write("wbv2-material-animation-receipt-ok task=WBV2-P12-003 material=EXACT animation=EXACT saveReopen=EXACT deterministic=true next=WBV2-P12-004\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-P12-003 status\n\n- task: \`WBV2-P12-003\`; parent: \`WBV2-P12-002\`; status: \`done\`\n- material/UV: \`4\` Main mutations; Principled values and UV map persisted\n- animation/TRS: keyframe frame \`25\` + interpolation \`LINEAR\`; persisted\n- save/reopen: \`EXACT\`; invalid UV and stale frame rejected\n- existing P3 source receipts reused read-only; no duplicate historical run\n- nextTask: \`WBV2-P12-004\`\n\nThe material and animation workflows are now bound to the compiled WebEngine WASM Main in Chromium. Unsupported material nodes remain explicit, and stale or malformed authoring commands do not mutate Main.\n`);
|
||||
const previousPlan = readJson("tests/golden/WBV2-P12-002/domain-expansion-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P12-002/domain-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P12-002/domain-expansion-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P12-003" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P12-004" ? { ...task, status: "in_progress", ready: true } : { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
const nextCardPath = "docs/tasks/WBV2-P12-004.md";
|
||||
fs.writeFileSync(absolute(nextCardPath), read(nextCardPath).replace("- status: planned", "- status: in_progress"));
|
||||
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" });
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P12-003", "--write"], { cwd: root, stdio: "inherit" });
|
||||
const artifactPaths = { parentManifest: parentPath, materialManifest: materialManifestPath, materialReport: materialReportPath, animationManifest: animationManifestPath, animationReport: animationReportPath, production: productionPath, productionSecond: secondProductionPath, e2e: "web/tests/e2e/wbv2-material-animation-production.spec.ts", client: "web/app/src/engine-client/WebEngineClient.ts", nativeApi: "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", generator: "tools/web/generate-wbv2-material-animation-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-P12-003", parentTask: "WBV2-P12-002", operation: "MATERIAL_ANIMATION_ENGINE_RECEIPT", status: "done", enablingTask: false, parityStateChange: true, runtime: "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", artifacts, assertions: { materialMutations: 4, animationMutations: 2, saveReopen: "EXACT", negativeCases: 2, unsupportedGraphExplicit: true, deterministic: true, historicalReproduction: false }, nextTask: "WBV2-P12-004" };
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P12-004` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-003/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-004.md`](tasks/WBV2-P12-004.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
let nextTaskFile = read("nextTask.md");
|
||||
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-004` |")
|
||||
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-003/manifest.json` |")
|
||||
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-004.md` |")
|
||||
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P12-005` |")
|
||||
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-viewport-nonmesh-production.spec.ts` |");
|
||||
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
|
||||
process.stdout.write(`wbv2-material-animation-receipt-written task=WBV2-P12-003 material=EXACT animation=EXACT saveReopen=EXACT next=WBV2-P12-004 artifacts=${Object.keys(artifacts).length}\n`);
|
||||
97
tools/web/generate-wbv2-scene-object-receipt.mjs
Normal file
97
tools/web/generate-wbv2-scene-object-receipt.mjs
Normal file
@@ -0,0 +1,97 @@
|
||||
import assert from "node:assert/strict";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const write = process.argv.includes("--write");
|
||||
const absolute = (file) => path.join(root, file);
|
||||
const read = (file) => fs.readFileSync(absolute(file), "utf8");
|
||||
const readJson = (file) => JSON.parse(read(file));
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const outputRoot = "tests/golden/WBV2-P12-002";
|
||||
const productionPath = `${outputRoot}/scene-object-production.json`;
|
||||
const secondProductionPath = `${outputRoot}/scene-object-production.second.json`;
|
||||
const reportPath = `${outputRoot}/scene-object-receipt-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P12-002.md";
|
||||
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentPath = "tests/golden/WBV2-P12-001/manifest.json";
|
||||
const sourceManifestPath = "tests/golden/WBV2-P2-002/manifest.json";
|
||||
const sourceReportPath = "tests/golden/WBV2-P2-002/object-transform-report.json";
|
||||
|
||||
const parent = readJson(parentPath);
|
||||
assert.equal(parent.task, "WBV2-P12-001");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P12-002");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
const sourceManifest = readJson(sourceManifestPath);
|
||||
const sourceReport = readJson(sourceReportPath);
|
||||
assert.equal(sourceManifest.status, "done");
|
||||
assert.equal(sourceReport.desktop.status, "EXACT");
|
||||
assert.equal(sourceReport.wasm.status, "EXACT");
|
||||
assert.equal(sourceReport.saveReopen, "EXACT");
|
||||
const sourceBound = Object.values(sourceManifest.artifacts ?? {}).find((artifact) => artifact.path === sourceReportPath);
|
||||
assert.ok(sourceBound);
|
||||
assert.equal(sourceBound.sha256, sha256(sourceReportPath));
|
||||
|
||||
assert.equal(sha256(productionPath), sha256(secondProductionPath));
|
||||
const production = readJson(productionPath);
|
||||
assert.equal(production.task, "WBV2-P12-002");
|
||||
assert.equal(production.browser, "chromium");
|
||||
assert.equal(production.queueMutation, false);
|
||||
assert.equal(production.hiddenRevision, production.baseRevision + 1);
|
||||
assert.equal(production.transformedRevision, production.baseRevision + 2);
|
||||
assert.equal(production.afterParent.visible, false);
|
||||
assert.deepEqual(production.afterChild.translation, [0.5, 2.5, 0]);
|
||||
assert.equal(production.exactSaveReopen, true);
|
||||
assert.deepEqual(production.unchangedParent, production.afterParent);
|
||||
assert.deepEqual(production.unchangedChild, production.afterChild);
|
||||
assert.match(production.stale.message, /REVISION_CONFLICT/u);
|
||||
assert.notEqual(production.malformed.code, "NO_ERROR");
|
||||
assert.notEqual(production.savedSha256, production.sourceSha256);
|
||||
|
||||
const receipt = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P12-002",
|
||||
operation: "SCENE_OBJECT_WORKFLOW_ENGINE_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
source: { task: "WBV2-P2-002", manifest: sourceManifestPath, manifestSha256: sha256(sourceManifestPath), report: sourceReportPath, reportSha256: sha256(sourceReportPath), desktopExact: true, wasmExact: true, sourceSaveReopenExact: true },
|
||||
production: { report: productionPath, reportSha256: sha256(productionPath), secondReport: secondProductionPath, secondReportSha256: sha256(secondProductionPath), deterministic: true, visibility: { objectId: "object:WBV2P2002Parent", before: production.beforeParent.visible, after: production.afterParent.visible, revisionDelta: 1 }, transform: { objectId: "object:WBV2P2002Child", before: production.beforeChild.translation, after: production.afterChild.translation, revisionDelta: 1 }, saveReopen: production.exactSaveReopen, stale: production.stale, malformed: production.malformed },
|
||||
assertions: { visibilityMainChanged: true, transformMainChanged: true, saveReopenExact: true, staleRejected: true, malformedRejected: true, historicalReproduction: false },
|
||||
nextTask: "WBV2-P12-003",
|
||||
};
|
||||
if (!write) { process.stdout.write("wbv2-scene-object-receipt-ok task=WBV2-P12-002 visibility=EXACT transform=EXACT saveReopen=EXACT deterministic=true next=WBV2-P12-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-P12-002 status\n\n- task: \`WBV2-P12-002\`; parent: \`WBV2-P12-001\`; status: \`done\`\n- visibility transaction: revision +1; hidden object persisted\n- transform transaction: revision +1; child translation \`[0.5, 2.5, 0]\` persisted\n- save/reopen: \`EXACT\`; stale and malformed commands rejected\n- nextTask: \`WBV2-P12-003\`\n\nThe compiled WebEngine WASM Main now has a production-bound scene/object receipt for visibility and transform edits. Existing P2-002 desktop/WASM evidence is reused read-only; no duplicate historical fixture run is required.\n`);
|
||||
const previousPlan = readJson("tests/golden/WBV2-P12-001/domain-expansion-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P12-001/domain-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P12-001/domain-expansion-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P12-002" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P12-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-P12-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-P12-002", "--write"], { cwd: root, stdio: "inherit" });
|
||||
const artifactPaths = { parentManifest: parentPath, sourceManifest: sourceManifestPath, sourceReport: sourceReportPath, production: productionPath, productionSecond: secondProductionPath, e2e: "web/tests/e2e/wbv2-scene-object-production.spec.ts", client: "web/app/src/engine-client/WebEngineClient.ts", nativeApi: "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", generator: "tools/web/generate-wbv2-scene-object-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-P12-002", parentTask: "WBV2-P12-001", operation: "SCENE_OBJECT_WORKFLOW_ENGINE_RECEIPT", status: "done", enablingTask: false, parityStateChange: true, runtime: "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", artifacts, assertions: { visibilityMainChanged: true, transformMainChanged: true, saveReopen: "EXACT", negativeCases: 2, deterministic: true, historicalReproduction: false }, nextTask: "WBV2-P12-003" };
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P12-003` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-002/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-003.md`](tasks/WBV2-P12-003.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
let nextTaskFile = read("nextTask.md");
|
||||
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-003` |")
|
||||
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-002/manifest.json` |")
|
||||
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-003.md` |")
|
||||
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `WBV2-P12-004` |")
|
||||
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-material-animation-production.spec.ts` |");
|
||||
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
|
||||
process.stdout.write(`wbv2-scene-object-receipt-written task=WBV2-P12-002 visibility=EXACT transform=EXACT saveReopen=EXACT next=WBV2-P12-003 artifacts=${Object.keys(artifacts).length}\n`);
|
||||
103
tools/web/generate-wbv2-viewport-nonmesh-receipt.mjs
Normal file
103
tools/web/generate-wbv2-viewport-nonmesh-receipt.mjs
Normal file
@@ -0,0 +1,103 @@
|
||||
import assert from "node:assert/strict";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const write = process.argv.includes("--write");
|
||||
const absolute = (file) => path.join(root, file);
|
||||
const read = (file) => fs.readFileSync(absolute(file), "utf8");
|
||||
const readJson = (file) => JSON.parse(read(file));
|
||||
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
||||
const outputRoot = "tests/golden/WBV2-P12-004";
|
||||
const productionPath = `${outputRoot}/viewport-nonmesh-production.json`;
|
||||
const secondProductionPath = `${outputRoot}/viewport-nonmesh-production.second.json`;
|
||||
const reportPath = `${outputRoot}/viewport-nonmesh-receipt-report.json`;
|
||||
const statusPath = "docs/status/WBV2-P12-004.md";
|
||||
const planPath = `${outputRoot}/domain-expansion-task-plan.json`;
|
||||
const manifestPath = `${outputRoot}/manifest.json`;
|
||||
const parentPath = "tests/golden/WBV2-P12-003/manifest.json";
|
||||
const sourceViewportManifestPath = "tests/golden/WBV2-P2-004/manifest.json";
|
||||
const sourceViewportReportPath = "tests/golden/WBV2-P2-004/viewport-report.json";
|
||||
const sourceNonMeshManifestPath = "tests/golden/WBV2-P4-003/manifest.json";
|
||||
const sourceNonMeshReportPath = "tests/golden/WBV2-P4-003/sculpt-report.json";
|
||||
|
||||
const parent = readJson(parentPath);
|
||||
assert.equal(parent.task, "WBV2-P12-003");
|
||||
assert.equal(parent.status, "done");
|
||||
assert.equal(parent.nextTask, "WBV2-P12-004");
|
||||
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
||||
for (const [manifestPathValue, reportPathValue] of [[sourceViewportManifestPath, sourceViewportReportPath], [sourceNonMeshManifestPath, sourceNonMeshReportPath]]) {
|
||||
const manifest = readJson(manifestPathValue);
|
||||
const report = readJson(reportPathValue);
|
||||
assert.equal(manifest.status, "done");
|
||||
assert.equal(report.desktop.status, "EXACT");
|
||||
assert.equal(report.wasm.status, "EXACT");
|
||||
assert.equal(report.desktop.saveReopen, "EXACT");
|
||||
const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === reportPathValue);
|
||||
assert.ok(bound);
|
||||
assert.equal(bound.sha256, sha256(reportPathValue));
|
||||
}
|
||||
|
||||
assert.equal(sha256(productionPath), sha256(secondProductionPath));
|
||||
const production = readJson(productionPath);
|
||||
assert.equal(production.task, "WBV2-P12-004");
|
||||
assert.equal(production.browser, "chromium");
|
||||
assert.equal(production.queueMutation, false);
|
||||
assert.equal(production.viewport.sceneId, "scene:WBV2P2004ViewportScene");
|
||||
assert.ok(production.viewport.readbackPixels > 0);
|
||||
assert.ok(production.viewport.geometryBuffers > 0);
|
||||
assert.deepEqual(production.viewport.resources, { activeRequests: 0, liveInputBytes: 0, liveNativeHandles: 0, liveStagingFiles: 0 });
|
||||
assert.deepEqual(production.nonMesh.data.map((entry) => entry.type), ["CURVE", "POINT_CLOUD"]);
|
||||
assert.ok(production.nonMesh.gates.every((gate) => gate.status === "READY"));
|
||||
assert.equal(production.nonMesh.unknown.status, "BLOCKED");
|
||||
assert.equal(production.nonMesh.unknown.issueCode, "NON_MESH_DATA_UNSUPPORTED");
|
||||
assert.equal(production.nonMesh.editedRevision, production.nonMesh.baseRevision + 1);
|
||||
assert.equal(production.nonMesh.saveReopenExact, true);
|
||||
assert.equal(production.nonMesh.revisionAfterMalformed, production.nonMesh.editedRevision);
|
||||
|
||||
const receipt = {
|
||||
schemaVersion: 1,
|
||||
task: "WBV2-P12-004",
|
||||
operation: "VIEWPORT_NONMESH_ENGINE_RECEIPT",
|
||||
status: "PASS",
|
||||
browser: "chromium",
|
||||
queueMutation: false,
|
||||
source: { viewport: { task: "WBV2-P2-004", manifest: sourceViewportManifestPath, manifestSha256: sha256(sourceViewportManifestPath), report: sourceViewportReportPath, reportSha256: sha256(sourceViewportReportPath) }, nonMesh: { task: "WBV2-P4-003", manifest: sourceNonMeshManifestPath, manifestSha256: sha256(sourceNonMeshManifestPath), report: sourceNonMeshReportPath, reportSha256: sha256(sourceNonMeshReportPath) }, reusedReadOnly: true },
|
||||
production: { report: productionPath, reportSha256: sha256(productionPath), secondReport: secondProductionPath, secondReportSha256: sha256(secondProductionPath), deterministic: true, viewport: { sceneId: production.viewport.sceneId, meshCount: production.viewport.meshCount, geometryBuffers: production.viewport.geometryBuffers, readbackPixels: production.viewport.readbackPixels, resources: production.viewport.resources }, nonMesh: { data: production.nonMesh.data, gates: production.nonMesh.gates, curveId: production.nonMesh.curveId, baseRevision: production.nonMesh.baseRevision, editedRevision: production.nonMesh.editedRevision, unknown: production.nonMesh.unknown, malformed: production.nonMesh.malformed, revisionAfterMalformed: production.nonMesh.revisionAfterMalformed, saveReopen: production.nonMesh.saveReopenExact } },
|
||||
assertions: { viewportPixelsNonblank: true, nonMeshDataExplicit: true, curveMainChanged: true, unsupportedDataBlocked: true, malformedRejected: true, resourceDisposalExact: true, saveReopenExact: true, historicalReproduction: false },
|
||||
nextTask: "WBV2-P12-005",
|
||||
};
|
||||
if (!write) { process.stdout.write("wbv2-viewport-nonmesh-receipt-ok task=WBV2-P12-004 viewport=EXACT nonMesh=EXACT blockedUnknown=true saveReopen=EXACT deterministic=true next=WBV2-P12-005\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-P12-004 status\n\n- task: \`WBV2-P12-004\`; parent: \`WBV2-P12-003\`; status: \`done\`\n- viewport: scene \`scene:WBV2P2004ViewportScene\`; readback pixels \`${production.viewport.readbackPixels}\`; resources disposed exact\n- non-mesh: Curve + Point Cloud binary gates READY; Curve revision \`1 -> 2\`\n- unknown data: BLOCKED; malformed Curve edit rejected without revision change\n- save/reopen: \`EXACT\`; nextTask: \`WBV2-P12-005\`\n\nExisting P2-004 viewport and P4-003 non-mesh source receipts are reused read-only. The production Chromium test binds nonblank viewport readback and bounded non-mesh capability/Curve mutation to the compiled WASM Main, with unsupported data remaining explicit.\n`);
|
||||
const previousPlan = readJson("tests/golden/WBV2-P12-003/domain-expansion-task-plan.json");
|
||||
const nextPlan = structuredClone(previousPlan);
|
||||
nextPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P12-003/domain-expansion-task-plan.json", sha256: sha256("tests/golden/WBV2-P12-003/domain-expansion-task-plan.json") };
|
||||
nextPlan.tasks = nextPlan.tasks.map((task) => task.id === "WBV2-P12-004" ? { ...task, status: "done", ready: false } : task.id === "WBV2-P12-005" ? { ...task, status: "in_progress", ready: true } : { ...task, ready: false });
|
||||
fs.writeFileSync(absolute(planPath), `${JSON.stringify(nextPlan, null, 2)}\n`);
|
||||
const nextCardPath = "docs/tasks/WBV2-P12-005.md";
|
||||
fs.writeFileSync(absolute(nextCardPath), read(nextCardPath).replace("- status: planned", "- status: in_progress"));
|
||||
execFileSync(process.execPath, [absolute("tools/web/generate-v2-task-index.mjs"), "--plan-path", absolute(planPath)], { cwd: root, stdio: "inherit" });
|
||||
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P12-004", "--write"], { cwd: root, stdio: "inherit" });
|
||||
const artifactPaths = { parentManifest: parentPath, viewportManifest: sourceViewportManifestPath, viewportReport: sourceViewportReportPath, nonMeshManifest: sourceNonMeshManifestPath, nonMeshReport: sourceNonMeshReportPath, production: productionPath, productionSecond: secondProductionPath, e2e: "web/tests/e2e/wbv2-viewport-nonmesh-production.spec.ts", client: "web/app/src/engine-client/WebEngineClient.ts", viewport: "web/app/src/three-adapter/viewport.ts", generator: "tools/web/generate-wbv2-viewport-nonmesh-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-P12-004", parentTask: "WBV2-P12-003", operation: "VIEWPORT_NONMESH_ENGINE_RECEIPT", status: "done", enablingTask: false, parityStateChange: true, runtime: "PLAYWRIGHT_CHROMIUM_WEBENGINE_WASM", artifacts, assertions: { viewportPixelsNonblank: true, nonMeshDataExplicit: true, curveMainChanged: true, unsupportedDataBlocked: true, resourceDisposalExact: true, saveReopen: "EXACT", deterministic: true, historicalReproduction: false }, nextTask: "WBV2-P12-005" };
|
||||
fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
||||
let queue = read("docs/EXECUTION_QUEUE.md");
|
||||
queue = queue.replace(/\| 当前任务 \| `[^`]+` \|/u, "| 当前任务 | `WBV2-P12-005` |")
|
||||
.replace(/\| parent manifest \| `[^`]+` \|/u, "| parent manifest | `tests/golden/WBV2-P12-004/manifest.json` |")
|
||||
.replace(/\| 任务卡 \| \[[^\]]+\]\([^\)]+\) \|/u, "| 任务卡 | [`tasks/WBV2-P12-005.md`](tasks/WBV2-P12-005.md) |");
|
||||
fs.writeFileSync(absolute("docs/EXECUTION_QUEUE.md"), queue);
|
||||
let nextTaskFile = read("nextTask.md");
|
||||
nextTaskFile = nextTaskFile.replace(/\| Current task when this file was written \| `[^`]+` \|/u, "| Current task when this file was written | `WBV2-P12-005` |")
|
||||
.replace(/\| Current task state \| `[^`]+` \|/u, "| Current task state | `in_progress` |")
|
||||
.replace(/\| Parent manifest \| `[^`]+` \|/u, "| Parent manifest | `tests/golden/WBV2-P12-004/manifest.json` |")
|
||||
.replace(/\| Current task card \| `[^`]+` \|/u, "| Current task card | `docs/tasks/WBV2-P12-005.md` |")
|
||||
.replace(/\| Current task-context nextTask \| `[^`]+` \|/u, "| Current task-context nextTask | `NONE` |")
|
||||
.replace(/\| Focused command \| `[^`]+` \|/u, "| Focused command | `node tools/web/generate-wbv2-domain-parity-gate.mjs --write` |");
|
||||
fs.writeFileSync(absolute("nextTask.md"), nextTaskFile);
|
||||
process.stdout.write(`wbv2-viewport-nonmesh-receipt-written task=WBV2-P12-004 viewport=EXACT nonMesh=EXACT saveReopen=EXACT next=WBV2-P12-005 artifacts=${Object.keys(artifacts).length}\n`);
|
||||
85
web/tests/e2e/wbv2-material-animation-production.spec.ts
Normal file
85
web/tests/e2e/wbv2-material-animation-production.spec.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
const root = path.resolve(import.meta.dirname, "../../..");
|
||||
const evidenceRoot = path.join(root, "tests/golden/WBV2-P12-003");
|
||||
const materialFixture = fs.readFileSync(path.join(root, "tests/files/web/generated/WBV2-P3-001-MATERIAL.PBR_UV.blend"));
|
||||
const animationFixture = fs.readFileSync(path.join(root, "tests/files/web/generated/WBV2-P3-002-ANIMATION.TRS_ACTION.blend"));
|
||||
const digest = (bytes: Uint8Array): string => crypto.createHash("sha256").update(bytes).digest("hex");
|
||||
|
||||
test("WBV2-P12-003 executes material and animation mutations through compiled WASM Main", async ({ page }) => {
|
||||
test.setTimeout(240_000);
|
||||
await page.goto("/");
|
||||
const result = await page.evaluate(async (input) => {
|
||||
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
|
||||
const buffer = (values: number[]): ArrayBuffer => Uint8Array.from(values).buffer;
|
||||
const digestBytes = async (value: ArrayBuffer): Promise<string> => { const hash = await crypto.subtle.digest("SHA-256", value); return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, "0")).join(""); };
|
||||
const shape = (error: any) => ({ code: error?.code, message: error?.message });
|
||||
const materialClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const materialReopenedClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const animationClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const animationReopenedClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
try {
|
||||
const materialOpened = await materialClient.openBlend(buffer(input.materialBytes));
|
||||
const materialId = "material:WBV2P3001PrincipledMaterial";
|
||||
const meshId = "mesh:WBV2P3001MaterialCubeMesh";
|
||||
const sourceMaterial: any = materialOpened.snapshot.materials.find((candidate: any) => candidate.id === materialId);
|
||||
const sourceMesh: any = materialOpened.snapshot.meshes.find((candidate: any) => candidate.id === meshId);
|
||||
if (!sourceMaterial || !sourceMesh) throw new Error("material fixture is incomplete");
|
||||
const createdUV = await materialClient.applyCommand({ type: "createUVMap", meshId, name: "WBV2P3001SecondaryUV", baseRevision: materialOpened.snapshot.revision } as any);
|
||||
const activeUV = await materialClient.applyCommand({ type: "setActiveUVMap", meshId, name: "WBV2P3001SecondaryUV", baseRevision: createdUV.snapshot.revision } as any);
|
||||
const unwrapped = await materialClient.applyCommand({ type: "unwrapUV", meshId, faceIndices: [0, 1, 2, 3, 4, 5], method: "CUBE", baseRevision: activeUV.snapshot.revision } as any);
|
||||
const editedMaterial = await materialClient.applyCommand({ type: "setMaterialPrincipled", materialId, baseColor: [0.2, 0.4, 0.6, 1], roughness: 0.31, metallic: 0.72, ior: 1.5, alpha: 1, baseRevision: unwrapped.snapshot.revision } as any);
|
||||
const invalidUV = await materialClient.applyCommand({ type: "setActiveUVMap", meshId, name: "missing-uv", baseRevision: editedMaterial.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch(shape);
|
||||
const materialAfterFailure = await materialClient.snapshot();
|
||||
const materialSaved = await materialClient.saveBlend();
|
||||
const materialSavedSha256 = await digestBytes(materialSaved.slice(0));
|
||||
const materialReopened = await materialReopenedClient.openBlend(materialSaved.slice(0));
|
||||
const material = materialReopened.snapshot.materials.find((candidate: any) => candidate.id === materialId);
|
||||
const materialMesh = materialReopened.snapshot.meshes.find((candidate: any) => candidate.id === meshId);
|
||||
|
||||
const animationOpened = await animationClient.openBlend(buffer(input.animationBytes));
|
||||
const animationObject: any = animationOpened.snapshot.nodes.find((candidate: any) => candidate.id === "object:WBV2P3002AnimatedCube");
|
||||
const animation: any = animationOpened.snapshot.animations.find((candidate: any) => candidate.targetId === animationObject?.id);
|
||||
if (!animationObject || !animation) throw new Error("animation fixture is incomplete");
|
||||
const inserted = await animationClient.applyCommand({ type: "insertObjectKeyframe", objectId: animationObject.id, frame: 25, property: "LOCATION", interpolation: "BEZIER", baseRevision: animationOpened.snapshot.revision } as any);
|
||||
const interpolated = await animationClient.applyCommand({ type: "setFCurveInterpolation", animationId: animation.id, path: "location[0]", interpolation: "LINEAR", baseRevision: inserted.snapshot.revision } as any);
|
||||
const staleFrame = await animationClient.applyCommand({ type: "insertObjectKeyframe", objectId: animationObject.id, frame: 30, property: "ROTATION_EULER", interpolation: "BEZIER", baseRevision: animationOpened.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch(shape);
|
||||
const animationAfterFailure = await animationClient.snapshot();
|
||||
const animationSaved = await animationClient.saveBlend();
|
||||
const animationSavedSha256 = await digestBytes(animationSaved.slice(0));
|
||||
const animationReopened = await animationReopenedClient.openBlend(animationSaved.slice(0));
|
||||
const reopenedAnimation: any = animationReopened.snapshot.animations.find((candidate: any) => candidate.id === animation.id);
|
||||
return {
|
||||
material: { sourceUnsupportedNode: sourceMaterial.nodes?.some((node: any) => node.type === "UNSUPPORTED") ?? false, baseRevision: materialOpened.snapshot.revision, finalRevision: editedMaterial.snapshot.revision, materialId, meshId, activeUVMap: materialMesh?.activeUVMap, baseColor: material?.baseColor, roughness: material?.roughness, metallic: material?.metallic, invalidUV, revisionAfterFailure: materialAfterFailure.snapshot.revision, savedByteLength: materialSaved.byteLength, sourceSha256: await digestBytes(buffer(input.materialBytes)), saveReopenExact: material?.baseColor?.join(",") === "0.20000000298023224,0.4000000059604645,0.6000000238418579,1" && materialMesh?.activeUVMap === "WBV2P3001SecondaryUV" },
|
||||
animation: { baseRevision: animationOpened.snapshot.revision, insertedRevision: inserted.snapshot.revision, finalRevision: interpolated.snapshot.revision, animationId: animation.id, channelCount: animation.channels.length, locationFrames: interpolated.snapshot.animations.find((candidate: any) => candidate.id === animation.id)?.channels.find((channel: any) => channel.path === "location[0]")?.keyframes.map((keyframe: any) => keyframe.frame), interpolation: interpolated.snapshot.animations.find((candidate: any) => candidate.id === animation.id)?.channels.find((channel: any) => channel.path === "location[0]")?.keyframes.at(-1)?.interpolation, staleFrame, revisionAfterFailure: animationAfterFailure.snapshot.revision, savedByteLength: animationSaved.byteLength, sourceSha256: await digestBytes(buffer(input.animationBytes)), reopenedFrames: reopenedAnimation?.channels.find((channel: any) => channel.path === "location[0]")?.keyframes.map((keyframe: any) => keyframe.frame), reopenedInterpolation: reopenedAnimation?.channels.find((channel: any) => channel.path === "location[0]")?.keyframes.at(-1)?.interpolation, saveReopenExact: reopenedAnimation?.channels.find((channel: any) => channel.path === "location[0]")?.keyframes.at(-1)?.interpolation === "LINEAR" },
|
||||
};
|
||||
}
|
||||
finally { materialClient.terminate(); materialReopenedClient.terminate(); animationClient.terminate(); animationReopenedClient.terminate(); }
|
||||
}, { materialBytes: Array.from(materialFixture), animationBytes: Array.from(animationFixture) });
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true });
|
||||
const output = process.env.WBV2_MATERIAL_ANIMATION_REPORT ?? "material-animation-production.json";
|
||||
fs.writeFileSync(path.join(evidenceRoot, output), `${JSON.stringify({ schemaVersion: 1, task: "WBV2-P12-003", operation: "MATERIAL_ANIMATION_ENGINE_CHROMIUM", browser: "chromium", queueMutation: false, ...result }, null, 2)}\n`);
|
||||
expect(result.material.sourceUnsupportedNode).toBe(true);
|
||||
expect(result.material.finalRevision).toBe(result.material.baseRevision + 4);
|
||||
expect(result.material.activeUVMap).toBe("WBV2P3001SecondaryUV");
|
||||
expect(result.material.baseColor[0]).toBeCloseTo(0.2, 5);
|
||||
expect(result.material.roughness).toBeCloseTo(0.31, 5);
|
||||
expect(result.material.metallic).toBeCloseTo(0.72, 5);
|
||||
expect(result.material.invalidUV.code).not.toBe("NO_ERROR");
|
||||
expect(result.material.revisionAfterFailure).toBe(result.material.finalRevision);
|
||||
expect(result.material.saveReopenExact).toBe(true);
|
||||
expect(result.material.savedSha256).not.toBe(result.material.sourceSha256);
|
||||
expect(result.animation.insertedRevision).toBe(result.animation.baseRevision + 1);
|
||||
expect(result.animation.finalRevision).toBe(result.animation.baseRevision + 2);
|
||||
expect(result.animation.locationFrames).toEqual([1, 10, 20, 25]);
|
||||
expect(result.animation.interpolation).toBe("LINEAR");
|
||||
expect(result.animation.staleFrame.code).not.toBe("NO_ERROR");
|
||||
expect(result.animation.revisionAfterFailure).toBe(result.animation.finalRevision);
|
||||
expect(result.animation.reopenedFrames).toEqual([1, 10, 20, 25]);
|
||||
expect(result.animation.reopenedInterpolation).toBe("LINEAR");
|
||||
expect(result.animation.saveReopenExact).toBe(true);
|
||||
expect(result.animation.savedSha256).not.toBe(result.animation.sourceSha256);
|
||||
});
|
||||
62
web/tests/e2e/wbv2-scene-object-production.spec.ts
Normal file
62
web/tests/e2e/wbv2-scene-object-production.spec.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
const root = path.resolve(import.meta.dirname, "../../..");
|
||||
const evidenceRoot = path.join(root, "tests/golden/WBV2-P12-002");
|
||||
const fixture = fs.readFileSync(path.join(root, "tests/files/web/generated/WBV2-P2-002-OBJECT.TRANSFORM_HIERARCHY.blend"));
|
||||
const sourceSha256 = crypto.createHash("sha256").update(fixture).digest("hex");
|
||||
|
||||
test("WBV2-P12-002 executes visibility and transform transactions through compiled WASM Main", async ({ page }) => {
|
||||
test.setTimeout(180_000);
|
||||
await page.goto("/");
|
||||
const result = await page.evaluate(async (input) => {
|
||||
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
|
||||
const client = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const reopenedClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const shape = (error: any) => ({ code: error?.code, message: error?.message });
|
||||
const objectState = (snapshot: any, id: string) => {
|
||||
const object = snapshot.nodes.find((candidate: any) => candidate.id === id);
|
||||
if (!object) throw new Error(`object missing: ${id}`);
|
||||
return { id: object.id, visible: object.visible, parentId: object.parentId, translation: object.transform?.translation ?? object.translation, worldMatrix: object.worldMatrix };
|
||||
};
|
||||
const digest = async (value: ArrayBuffer): Promise<string> => { const hash = await crypto.subtle.digest("SHA-256", value); return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, "0")).join(""); };
|
||||
try {
|
||||
const opened = await client.openBlend(Uint8Array.from(input.bytes).buffer);
|
||||
const parentId = "object:WBV2P2002Parent";
|
||||
const childId = "object:WBV2P2002Child";
|
||||
const beforeParent = objectState(opened.snapshot, parentId);
|
||||
const beforeChild = objectState(opened.snapshot, childId);
|
||||
const hidden = await client.applyCommand({ type: "setObjectVisibility", objectId: parentId, visible: false, baseRevision: opened.snapshot.revision } as any);
|
||||
const transformed = await client.applyCommand({ type: "setObjectTransform", objectId: childId, translation: [0.5, 2.5, 0], rotationEuler: [0, 0, 0], scale: [1, 1, 1], baseRevision: hidden.snapshot.revision } as any);
|
||||
const afterParent = objectState(transformed.snapshot, parentId);
|
||||
const afterChild = objectState(transformed.snapshot, childId);
|
||||
const stale = await client.applyCommand({ type: "setObjectVisibility", objectId: parentId, visible: true, baseRevision: opened.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch(shape);
|
||||
const malformed = await client.applyCommand({ type: "setObjectTransform", objectId: childId, translation: [0.5, 2.5], rotationEuler: [0, 0, 0], scale: [1, 1, 1], baseRevision: transformed.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch(shape);
|
||||
const unchanged = (await client.snapshot()).snapshot;
|
||||
const saved = await client.saveBlend();
|
||||
const savedSha256 = await digest(saved.slice(0));
|
||||
const reopened = await reopenedClient.openBlend(saved.slice(0));
|
||||
const reopenedParent = objectState(reopened.snapshot, parentId);
|
||||
const reopenedChild = objectState(reopened.snapshot, childId);
|
||||
return { baseRevision: opened.snapshot.revision, hiddenRevision: hidden.snapshot.revision, transformedRevision: transformed.snapshot.revision, beforeParent, beforeChild, afterParent, afterChild, stale, malformed, unchangedParent: objectState(unchanged, parentId), unchangedChild: objectState(unchanged, childId), reopenedParent, reopenedChild, savedSha256, sourceSha256: await digest(Uint8Array.from(input.bytes).buffer), exactSaveReopen: JSON.stringify({ parent: afterParent, child: afterChild }) === JSON.stringify({ parent: reopenedParent, child: reopenedChild }) };
|
||||
}
|
||||
finally { client.terminate(); reopenedClient.terminate(); }
|
||||
}, { bytes: Array.from(fixture) });
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true });
|
||||
const output = process.env.WBV2_SCENE_OBJECT_REPORT ?? "scene-object-production.json";
|
||||
fs.writeFileSync(path.join(evidenceRoot, output), `${JSON.stringify({ schemaVersion: 1, task: "WBV2-P12-002", operation: "SCENE_OBJECT_WORKFLOW_ENGINE_CHROMIUM", browser: "chromium", queueMutation: false, ...result }, null, 2)}\n`);
|
||||
expect(result.sourceSha256).toBe(sourceSha256);
|
||||
expect(result.hiddenRevision).toBe(result.baseRevision + 1);
|
||||
expect(result.transformedRevision).toBe(result.baseRevision + 2);
|
||||
expect(result.afterParent.visible).toBe(false);
|
||||
expect(result.afterChild.translation).toEqual([0.5, 2.5, 0]);
|
||||
expect(result.exactSaveReopen).toBe(true);
|
||||
expect(result.stale.code).not.toBe("NO_ERROR");
|
||||
expect(result.stale.message).toContain("REVISION_CONFLICT");
|
||||
expect(result.malformed.code).not.toBe("NO_ERROR");
|
||||
expect(result.unchangedParent).toEqual(result.afterParent);
|
||||
expect(result.unchangedChild).toEqual(result.afterChild);
|
||||
expect(result.savedSha256).not.toBe(sourceSha256);
|
||||
});
|
||||
83
web/tests/e2e/wbv2-viewport-nonmesh-production.spec.ts
Normal file
83
web/tests/e2e/wbv2-viewport-nonmesh-production.spec.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
const root = path.resolve(import.meta.dirname, "../../..");
|
||||
const evidenceRoot = path.join(root, "tests/golden/WBV2-P12-004");
|
||||
const viewportFixture = fs.readFileSync(path.join(root, "tests/files/web/generated/WBV2-P2-004-VIEWPORT.MAIN_OFFSCREEN.blend"));
|
||||
const nonMeshFixture = fs.readFileSync(path.join(root, "tests/files/web/generated/WBV2-P4-003-SCULPT.NONMESH.PAINT_BOUNDED.blend"));
|
||||
const digest = (bytes: Uint8Array): string => crypto.createHash("sha256").update(bytes).digest("hex");
|
||||
|
||||
test("WBV2-P12-004 binds viewport pixels and non-mesh boundaries to compiled WASM Main", async ({ page }) => {
|
||||
test.setTimeout(240_000);
|
||||
await page.goto("/");
|
||||
const result = await page.evaluate(async (input) => {
|
||||
const [{ WebEngineClient }, { ViewportRenderer }] = await Promise.all([
|
||||
import("/src/engine-client/WebEngineClient.ts"),
|
||||
import("/src/three-adapter/viewport.ts"),
|
||||
]);
|
||||
const buffer = (values: number[]): ArrayBuffer => Uint8Array.from(values).buffer;
|
||||
const digestBytes = async (value: ArrayBuffer): Promise<string> => { const hash = await crypto.subtle.digest("SHA-256", value); return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, "0")).join(""); };
|
||||
const viewportClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const nonMeshClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const nonMeshReopenedClient = new WebEngineClient({ timeoutMs: 60_000 });
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = 320;
|
||||
canvas.height = 240;
|
||||
canvas.style.cssText = "position:fixed;left:0;top:0;width:320px;height:240px";
|
||||
document.body.append(canvas);
|
||||
let renderer: any;
|
||||
try {
|
||||
const viewport = await viewportClient.openBlend(buffer(input.viewportBytes));
|
||||
renderer = new ViewportRenderer(canvas);
|
||||
renderer.setSnapshot(viewport.snapshot, viewport.geometryBuffers, viewport.nonMeshGeometryBuffers ?? []);
|
||||
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
||||
const gl = renderer.renderer.getContext();
|
||||
const pixels = new Uint8Array(32 * 32 * 4);
|
||||
gl.readPixels(0, 0, 32, 32, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
||||
const readbackPixels = Array.from({ length: 32 * 32 }, (_, index) => pixels[index * 4] + pixels[index * 4 + 1] + pixels[index * 4 + 2] > 30).filter(Boolean).length;
|
||||
const viewportResources = await viewportClient.openResourceStatus();
|
||||
|
||||
const opened = await nonMeshClient.openBlend(buffer(input.nonMeshBytes));
|
||||
const data = opened.snapshot.nonMeshData ?? [];
|
||||
const curve = data.find((entry: any) => entry.type === "CURVE");
|
||||
if (!curve) throw new Error("non-mesh fixture has no Curve data");
|
||||
const gates = data.map((entry: any) => ({ id: entry.id, type: entry.type, status: nonMeshClient.queryNonMeshCapability(entry.id) }));
|
||||
const resolvedGates = [];
|
||||
for (const entry of gates) resolvedGates.push({ id: entry.id, type: entry.type, gate: await entry.status });
|
||||
const curveControlPoints = [0, 0, 0, 1, 0, 0, 2, 0, 0];
|
||||
const curveSplineOffsets = [0, 3];
|
||||
const editedCurve = await nonMeshClient.applyCommand({ type: "setCurveControlPoints", dataId: curve.id, controlPoints: curveControlPoints, splineOffsets: curveSplineOffsets, resolution: curve.resolution ?? 12, baseRevision: opened.snapshot.revision } as any);
|
||||
const unknown = await nonMeshClient.queryNonMeshCapability("nonmesh:missing");
|
||||
const saved = await nonMeshClient.saveBlend();
|
||||
const savedSha256 = await digestBytes(saved.slice(0));
|
||||
const reopened = await nonMeshReopenedClient.openBlend(saved.slice(0));
|
||||
const reopenedCurve = reopened.snapshot.nonMeshData?.find((entry: any) => entry.id === curve.id);
|
||||
const malformed = await nonMeshClient.applyCommand({ type: "setCurveControlPoints", dataId: curve.id, controlPoints: [0, 1], splineOffsets: [0, 1], resolution: curve.resolution, baseRevision: editedCurve.snapshot.revision } as any).then(() => ({ code: "NO_ERROR" })).catch((error: any) => ({ code: error?.code, message: error?.message }));
|
||||
const afterMalformed = (await nonMeshClient.snapshot()).snapshot;
|
||||
return { viewport: { revision: viewport.snapshot.revision, sceneId: viewport.snapshot.sceneId, meshCount: viewport.snapshot.meshes.length, geometryBuffers: viewport.geometryBuffers.length, readbackPixels, resources: viewportResources }, nonMesh: { baseRevision: opened.snapshot.revision, editedRevision: editedCurve.snapshot.revision, data: data.map((entry: any) => ({ id: entry.id, type: entry.type, geometryStatus: entry.geometryStatus, pointCount: entry.pointCount, splineCount: entry.splineCount })), gates: resolvedGates.map((entry: any) => ({ id: entry.id, type: entry.type, status: entry.gate.status, capability: entry.gate.capability, issueCodes: entry.gate.issues.map((issue: any) => issue.code) })), unknown: { status: unknown.status, capability: unknown.capability, issueCode: unknown.issues[0]?.code }, curveId: curve.id, curveBefore: { controlPoints: curve.controlPoints, pointCount: curve.pointCount }, curveAfter: { controlPoints: editedCurve.snapshot.nonMeshData?.find((entry: any) => entry.id === curve.id)?.controlPoints, pointCount: editedCurve.snapshot.nonMeshData?.find((entry: any) => entry.id === curve.id)?.pointCount }, reopenedCurve: { controlPoints: reopenedCurve?.controlPoints, pointCount: reopenedCurve?.pointCount }, malformed, revisionAfterMalformed: afterMalformed.revision, savedSha256, sourceSha256: await digestBytes(buffer(input.nonMeshBytes)), saveReopenExact: JSON.stringify(editedCurve.snapshot.nonMeshData?.find((entry: any) => entry.id === curve.id)) === JSON.stringify(reopenedCurve) } };
|
||||
}
|
||||
catch (error: any) { return { error: { code: error?.code, message: error?.message, detail: String(error) } } as any; }
|
||||
finally { renderer?.dispose(); canvas.remove(); viewportClient.terminate(); nonMeshClient.terminate(); nonMeshReopenedClient.terminate(); }
|
||||
}, { viewportBytes: Array.from(viewportFixture), nonMeshBytes: Array.from(nonMeshFixture) });
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true });
|
||||
const output = process.env.WBV2_VIEWPORT_NONMESH_REPORT ?? "viewport-nonmesh-production.json";
|
||||
fs.writeFileSync(path.join(evidenceRoot, output), `${JSON.stringify({ schemaVersion: 1, task: "WBV2-P12-004", operation: "VIEWPORT_NONMESH_ENGINE_CHROMIUM", browser: "chromium", queueMutation: false, ...result }, null, 2)}\n`);
|
||||
expect(result.error).toBeUndefined();
|
||||
expect(result.viewport.sceneId).toBe("scene:WBV2P2004ViewportScene");
|
||||
expect(result.viewport.meshCount).toBeGreaterThan(0);
|
||||
expect(result.viewport.geometryBuffers).toBeGreaterThan(0);
|
||||
expect(result.viewport.readbackPixels).toBeGreaterThan(0);
|
||||
expect(result.viewport.resources).toMatchObject({ activeRequests: 0, liveInputBytes: 0, liveStagingFiles: 0 });
|
||||
expect(result.nonMesh.data.length).toBe(2);
|
||||
expect(result.nonMesh.data.map((entry) => entry.type)).toEqual(["CURVE", "POINT_CLOUD"]);
|
||||
expect(result.nonMesh.gates.some((gate) => gate.status === "READY")).toBe(true);
|
||||
expect(result.nonMesh.unknown.status).toBe("BLOCKED");
|
||||
expect(result.nonMesh.unknown.issueCode).toBe("NON_MESH_DATA_UNSUPPORTED");
|
||||
expect(result.nonMesh.editedRevision).toBe(result.nonMesh.baseRevision + 1);
|
||||
expect(result.nonMesh.saveReopenExact).toBe(true);
|
||||
expect(result.nonMesh.malformed.code).not.toBe("NO_ERROR");
|
||||
expect(result.nonMesh.revisionAfterMalformed).toBe(result.nonMesh.editedRevision);
|
||||
expect(result.nonMesh.savedSha256).not.toBe(result.nonMesh.sourceSha256);
|
||||
});
|
||||
Reference in New Issue
Block a user