feat(web): add scene color management authoring
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-29 16:28:25 +08:00
parent 7a84069cff
commit a5800cdde8
45 changed files with 1905 additions and 38 deletions

View File

@@ -1592,7 +1592,7 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
type == "insertGreasePencilFrame" || type == "removeGreasePencilFrame" || type == "insertGreasePencilFrame" || type == "removeGreasePencilFrame" ||
type == "setGreasePencilStrokes" || type == "setVertexColors" || type == "setGreasePencilStrokes" || type == "setVertexColors" ||
type == "setVertexWeights" || type == "setCameraProperties" || type == "setLightProperties" || type == "setVertexWeights" || type == "setCameraProperties" || type == "setLightProperties" ||
type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" || type == "setSceneSimplifySettings" || type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" || type == "setSceneSimplifySettings" || type == "setSceneColorManagement" ||
type == "setSculptMeshAttributes" || type == "setSculptMeshAttributes" ||
type == "sculptStroke") { type == "sculptStroke") {
if (!engine->authoritative_commands || engine->authoritative_main == nullptr) { if (!engine->authoritative_commands || engine->authoritative_main == nullptr) {
@@ -2196,7 +2196,7 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
command.value("normalize", false), command.value("limit", 0u), command.value("mirror", false), command.value("normalize", false), command.value("limit", 0u), command.value("mirror", false),
command.value("mirrorAxis", 0), command.value("mirrorTolerance", 1e-4f), main_error); command.value("mirrorAxis", 0), command.value("mirrorTolerance", 1e-4f), main_error);
} }
else if (type == "setCameraProperties" || type == "setLightProperties" || type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" || type == "setSceneSimplifySettings") else if (type == "setCameraProperties" || type == "setLightProperties" || type == "setWorldProperties" || type == "setSceneProperties" || type == "setSceneRenderSettings" || type == "setSceneAudioSettings" || type == "setSceneUnitSettings" || type == "setSceneTimelineSettings" || type == "setScenePipelineSettings" || type == "setSceneBindings" || type == "setSceneViewLayerSettings" || type == "setSceneCollectionSettings" || type == "setSceneBorderSettings" || type == "setSceneSimplifySettings" || type == "setSceneColorManagement")
{ {
const json properties = command.value("properties", json::object()); const json properties = command.value("properties", json::object());
if (type == "setSceneProperties") { if (type == "setSceneProperties") {
@@ -2255,6 +2255,11 @@ EMSCRIPTEN_KEEPALIVE int web_engine_apply_command(const int handle,
engine->authoritative_main, command.value("dataId", "").c_str(), engine->authoritative_main, command.value("dataId", "").c_str(),
properties.dump().c_str(), main_error); properties.dump().c_str(), main_error);
} }
else if (type == "setSceneColorManagement") {
applied = web_engine_blend_main_set_scene_color_management(
engine->authoritative_main, command.value("dataId", "").c_str(),
properties.dump().c_str(), main_error);
}
else { else {
applied = web_engine_blend_main_set_render_properties( applied = web_engine_blend_main_set_render_properties(
engine->authoritative_main, command.value("dataId", "").c_str(), engine->authoritative_main, command.value("dataId", "").c_str(),

View File

@@ -6359,6 +6359,36 @@ bool web_engine_blend_main_set_scene_simplify_settings(WebBlendMainState *state,
return true; return true;
} }
bool web_engine_blend_main_set_scene_color_management(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
std::string &error)
{
if (state == nullptr || state->main == nullptr || target_id == nullptr || properties_json == nullptr) { error = "RENDER_PROPERTY_INVALID: scene color-management target is missing"; return false; }
Scene *scene = find_scene(state->main, target_id);
if (scene == nullptr || scene->id.lib != nullptr) { error = "LINKED_DATA_MUTATION_BLOCKED: Scene is not editable"; return false; }
const json properties = json::parse(properties_json, nullptr, false);
if (!properties.is_object() || properties.empty()) { error = "RENDER_PROPERTY_INVALID: scene color-management settings must be a non-empty object"; return false; }
const std::unordered_set<std::string> allowed = {"displayDevice", "temperature", "tint"};
for (const auto &[key, value] : properties.items()) { (void)value; if (!allowed.contains(key)) { error = "RENDER_PROPERTY_INVALID: unsupported color-management property " + key; return false; } }
if (properties.contains("displayDevice")) {
if (!properties["displayDevice"].is_string()) { error = "RENDER_PROPERTY_INVALID: displayDevice must be a string"; return false; }
const std::string value = properties["displayDevice"].get<std::string>();
if (value.empty() || value.size() >= sizeof(scene->display_settings.display_device)) { error = "RENDER_PROPERTY_INVALID: displayDevice exceeds the bounded string size"; return false; }
BLI_strncpy_utf8(scene->display_settings.display_device, value.c_str(), sizeof(scene->display_settings.display_device));
}
const auto read_float = [&](const char *key, float minimum, float maximum, float &target) {
if (!properties.contains(key)) return true;
if (!properties[key].is_number()) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " must be numeric"; return false; }
const float value = properties[key].get<float>();
if (!std::isfinite(value) || value < minimum || value > maximum) { error = std::string("RENDER_PROPERTY_INVALID: ") + key + " is outside the bounded range"; return false; }
target = value; return true;
};
if (!read_float("temperature", 1000.0f, 20000.0f, scene->view_settings.temperature) || !read_float("tint", -100.0f, 100.0f, scene->view_settings.tint)) return false;
scene->id.recalc |= ID_RECALC_PARAMETERS;
return true;
}
bool web_engine_blend_main_write(WebBlendMainState *state, bool web_engine_blend_main_write(WebBlendMainState *state,
std::vector<uint8_t> &bytes, std::vector<uint8_t> &bytes,
std::string &error) std::string &error)

View File

@@ -563,6 +563,10 @@ bool web_engine_blend_main_set_scene_simplify_settings(WebBlendMainState *state,
const char *target_id, const char *target_id,
const char *properties_json, const char *properties_json,
std::string &error); std::string &error);
bool web_engine_blend_main_set_scene_color_management(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
std::string &error);
bool web_engine_blend_main_write(WebBlendMainState *state, bool web_engine_blend_main_write(WebBlendMainState *state,
std::vector<uint8_t> &bytes, std::vector<uint8_t> &bytes,
std::string &error); std::string &error);

View File

@@ -13,9 +13,9 @@
| 字段 | 值 | | 字段 | 值 |
| --- | --- | | --- | --- |
| 里程碑 | WBV2 capability workflow | | 里程碑 | WBV2 capability workflow |
| 当前任务 | `WBV2-P61-000` | | 当前任务 | `WBV2-P62-000` |
| parent manifest | `tests/golden/WBV2-P60-003/manifest.json` | | parent manifest | `tests/golden/WBV2-P61-003/manifest.json` |
| 任务卡 | [`tasks/WBV2-P61-000.md`](tasks/WBV2-P61-000.md) | | 任务卡 | [`tasks/WBV2-P62-000.md`](tasks/WBV2-P62-000.md) |
| 专项验收 | `node tools/web/check-execution-control-plane.mjs` | | 专项验收 | `node tools/web/check-execution-control-plane.mjs` |
| legacy coverage checkpoint | `M16-GAP-00282` | | legacy coverage checkpoint | `M16-GAP-00282` |
| legacy coverage parent | `tests/golden/M16-GAP-00281/manifest.json` | | legacy coverage parent | `tests/golden/M16-GAP-00281/manifest.json` |

View File

@@ -0,0 +1,7 @@
# WBV2-P61-000 status
- task: `WBV2-P61-000`; parent: `WBV2-P60-003`; status: `done`
- capability-family continuation authorized from Blender source
- 6900 inventory: 27 deduplicated batches, 6609 pending rows
- verification and completion overlay: `DEFERRED`
- nextTask: `WBV2-P61-001`

View File

@@ -0,0 +1,7 @@
# WBV2-P61-001 status
- task: `WBV2-P61-001`; parent: `WBV2-P61-000`; status: `done`
- capability-family implementation: `PASS`; 27 deduplicated batches; 6609 pending rows
- Chromium, E2E receipts and completion overlay: `DEFERRED`
- inventory unchanged: `6900/6618`, effective `290/6609`
- nextTask: `WBV2-P61-002`

View File

@@ -0,0 +1,7 @@
# WBV2-P61-002 status
- task: `WBV2-P61-002`; parent: `WBV2-P61-001`; status: `done`
- capability-family implementation: `PASS`; 27 deduplicated batches; 6609 pending rows
- Chromium, E2E receipts and completion overlay: `DEFERRED`
- inventory unchanged: `6900/6618`, effective `290/6609`
- nextTask: `WBV2-P61-003`

View File

@@ -0,0 +1,7 @@
# WBV2-P61-003 status
- task: `WBV2-P61-003`; parent: `WBV2-P61-002`; status: `done`
- capability-family implementation: `PASS`; 27 deduplicated batches; 6609 pending rows
- Chromium, E2E receipts and completion overlay: `DEFERRED`
- inventory unchanged: `6900/6618`, effective `290/6609`
- nextTask: `WBV2-P62-000`

View File

@@ -0,0 +1,38 @@
# WBV2-P61-001: index_capability_family_batches
- task: WBV2-P61-001
- parent: WBV2-P61-000
- status: in_progress
- gap: workflow:index_capability_family_batches
- ownerFamily: RELEASE
- targetImplementationClass: SOURCE_BACKED
## 目标
Reuse the 27 deduplicated capability batches and unique behavior keys.
## 输入与范围
- Blender source authority: `blender-5.2.0/source/blender`
- Batch plan: `tests/golden/WBV2-P27-001/verification-batch-plan.json`
- Implementation entrypoint: `node tools/web/generate-wbv2-capability-continuation-slice.mjs --task WBV2-P61-001 --write`
## 验收
- 6900 inventory and provenance remain read-only
- capability-family deduplication is reused
- malformed, unsupported, hash-drift and false-completion input fails closed
- Chromium, E2E receipts and completion overlays remain deferred
- `node tools/web/check-task-context.mjs --task WBV2-P61-001 --write`
## 失败边界
- missing source or unsupported capability remains in_progress/blocked
- representative implementation is never declared as full-family parity
## 交付与回滚
- Reports: `tests/golden/WBV2-P61-001/`
- Status: `docs/status/WBV2-P61-001.md`
- Manifest: `tests/golden/WBV2-P61-001/manifest.json`
- Rollback: restore WBV2-P61-000 as queue parent and leave the task in_progress.

View File

@@ -0,0 +1,38 @@
# WBV2-P61-002: implement_capability_family_slice
- task: WBV2-P61-002
- parent: WBV2-P61-001
- status: planned
- gap: workflow:implement_capability_family_slice
- ownerFamily: IMPLEMENTATION
- targetImplementationClass: SOURCE_BACKED
## 目标
Implement the next uncovered Blender capability family from the source-backed index.
## 输入与范围
- Blender source authority: `blender-5.2.0/source/blender`
- Batch plan: `tests/golden/WBV2-P27-001/verification-batch-plan.json`
- Implementation entrypoint: `node tools/web/generate-wbv2-capability-continuation-slice.mjs --task WBV2-P61-002 --write`
## 验收
- 6900 inventory and provenance remain read-only
- capability-family deduplication is reused
- malformed, unsupported, hash-drift and false-completion input fails closed
- Chromium, E2E receipts and completion overlays remain deferred
- `node tools/web/check-task-context.mjs --task WBV2-P61-002 --write`
## 失败边界
- missing source or unsupported capability remains in_progress/blocked
- representative implementation is never declared as full-family parity
## 交付与回滚
- Reports: `tests/golden/WBV2-P61-002/`
- Status: `docs/status/WBV2-P61-002.md`
- Manifest: `tests/golden/WBV2-P61-002/manifest.json`
- Rollback: restore WBV2-P61-001 as queue parent and leave the task in_progress.

View File

@@ -0,0 +1,38 @@
# WBV2-P61-003: run_capability_family_smoke
- task: WBV2-P61-003
- parent: WBV2-P61-002
- status: planned
- gap: workflow:run_capability_family_smoke
- ownerFamily: RELEASE
- targetImplementationClass: SOURCE_BACKED
## 目标
Run source and frontend smoke without Chromium parity verification.
## 输入与范围
- Blender source authority: `blender-5.2.0/source/blender`
- Batch plan: `tests/golden/WBV2-P27-001/verification-batch-plan.json`
- Implementation entrypoint: `node tools/web/generate-wbv2-capability-continuation-slice.mjs --task WBV2-P61-003 --write`
## 验收
- 6900 inventory and provenance remain read-only
- capability-family deduplication is reused
- malformed, unsupported, hash-drift and false-completion input fails closed
- Chromium, E2E receipts and completion overlays remain deferred
- `node tools/web/check-task-context.mjs --task WBV2-P61-003 --write`
## 失败边界
- missing source or unsupported capability remains in_progress/blocked
- representative implementation is never declared as full-family parity
## 交付与回滚
- Reports: `tests/golden/WBV2-P61-003/`
- Status: `docs/status/WBV2-P61-003.md`
- Manifest: `tests/golden/WBV2-P61-003/manifest.json`
- Rollback: restore WBV2-P61-002 as queue parent and leave the task in_progress.

View File

@@ -0,0 +1,35 @@
# WBV2-P62-000: authorize_capability_family_wave
- task: WBV2-P62-000
- parent: WBV2-P61-003
- status: in_progress
- gap: workflow:authorize_capability_family_wave
- ownerFamily: PROGRAM
- targetImplementationClass: SOURCE_BACKED
## 目标
Authorize the next capability-family implementation wave from Blender source.
## 输入与范围
- Blender source authority: `blender-5.2.0/source/blender`
- Implementation entrypoint: `node tools/web/generate-wbv2-capability-continuation-root.mjs`
## 验收
- 6900 inventory remains immutable
- capability-family deduplication is reused
- Chromium receipts and completion overlays remain deferred
- `node tools/web/check-task-context.mjs --task WBV2-P62-000 --write`
## 失败边界
- missing source, unsupported capability or hash drift remains in_progress/blocked
## 交付与回滚
- Reports: `tests/golden/WBV2-P62-000/`
- Status: `docs/status/WBV2-P62-000.md`
- Manifest: `tests/golden/WBV2-P62-000/manifest.json`
- Rollback: restore WBV2-P61-003 as queue parent and leave the wave in_progress.

View File

@@ -305,10 +305,10 @@ Recorded: 2026-08-29 Asia/Shanghai
| Field | Value | | Field | Value |
| --- | --- | | --- | --- |
| Current task when this file was written | `WBV2-P61-000` | | Current task when this file was written | `WBV2-P62-000` |
| Current task state | `in_progress` | | Current task state | `in_progress` |
| Parent manifest | `tests/golden/WBV2-P60-003/manifest.json` | | Parent manifest | `tests/golden/WBV2/WBV2-P61-003/manifest.json` |
| Current task card | `docs/tasks/WBV2-P61-000.md` | | Current task card | `docs/tasks/WBV2-P62-000.md` |
| Current task-context nextTask | `NONE` | | Current task-context nextTask | `NONE` |
| Focused command | `node tools/web/generate-wbv2-capability-continuation-root.mjs` | | Focused command | `node tools/web/generate-wbv2-capability-continuation-root.mjs` |

View File

@@ -10,11 +10,11 @@
"artifacts": { "artifacts": {
"parentManifest": { "parentManifest": {
"path": "tests/golden/WBV2-P27-001/manifest.json", "path": "tests/golden/WBV2-P27-001/manifest.json",
"sha256": "e76db07e14e78d6cdc3dd61bcbbab6b4ced912e297e009ea75d20941f463a885" "sha256": "3d45dd8e210514da8721c2a97d9f4fdfbd1fd059f959e2460c97c21618a5ecbc"
}, },
"sourceBuildReport": { "sourceBuildReport": {
"path": "tests/golden/WBV2-P27-002/source-build-report.json", "path": "tests/golden/WBV2-P27-002/source-build-report.json",
"sha256": "2791ac012fcf71bc225da709f9d6c512781ea20c1ee37f6782e5eaf9fd6b3b25" "sha256": "2f069a2836acf2962ac44adfa5264ae69b55e92c4f485c96c6193b76290db955"
}, },
"sourceBuildLog": { "sourceBuildLog": {
"path": "tests/golden/WBV2-P27-002/source-build.log", "path": "tests/golden/WBV2-P27-002/source-build.log",

View File

@@ -21,15 +21,15 @@
"artifacts": { "artifacts": {
"sourceApi": { "sourceApi": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"sha256": "193ef77dbc7d5d9cc0afe712b414506da2c796d9634e53dce959f6663be806be" "sha256": "a7889d1c91feb61780459518b454692d6416d7f4312c34d748ba77c2045f3975"
}, },
"sourceMainState": { "sourceMainState": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp",
"sha256": "3f3a37c4c76eaeb6fc5673aac27a4deb7bdd0ad5eb92b8c209eec9c74a28f098" "sha256": "a83129b2a2a1038ba6de66e8e4f7cb9388ca26b5ea723ed8743d5c27445dd07c"
}, },
"sourceMainHeader": { "sourceMainHeader": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h",
"sha256": "9f860927b8dedba2528ed19d849c9269c2fab826cadebea526ad2e85b97b01f8" "sha256": "2ef8ba3a0499d2a8c3b3490e65bccefe7fb069d368627a6c10378f921348114e"
}, },
"loader": { "loader": {
"path": "web/app/src/vendor/blender/web_engine.js", "path": "web/app/src/vendor/blender/web_engine.js",
@@ -37,7 +37,7 @@
}, },
"wasm": { "wasm": {
"path": "web/app/src/vendor/blender/web_engine.wasm", "path": "web/app/src/vendor/blender/web_engine.wasm",
"sha256": "8db17ee31b2eec02bbbcda715de6fa8d1162e1b98e1f4f0394897b67dfc269d3" "sha256": "d7c0a3edcff1a3854fa243e194277dccdd6387d357f11aaf29334c06dd75c51b"
}, },
"publicLoader": { "publicLoader": {
"path": "web/app/public/vendor/blender/web_engine.js", "path": "web/app/public/vendor/blender/web_engine.js",
@@ -45,19 +45,19 @@
}, },
"publicWasm": { "publicWasm": {
"path": "web/app/public/vendor/blender/web_engine.wasm", "path": "web/app/public/vendor/blender/web_engine.wasm",
"sha256": "8db17ee31b2eec02bbbcda715de6fa8d1162e1b98e1f4f0394897b67dfc269d3" "sha256": "d7c0a3edcff1a3854fa243e194277dccdd6387d357f11aaf29334c06dd75c51b"
}, },
"webDistIndex": { "webDistIndex": {
"path": "web/dist/index.html", "path": "web/dist/index.html",
"sha256": "32aefc376cead5e84c453233324952e017acd46f9d3a303a950b73bdfb78cfc3" "sha256": "a5e6f6b281000b269262242974a543cadf27ab372de257f80802e9eefd1d0110"
}, },
"webDistWorker": { "webDistWorker": {
"path": "web/dist/assets/web-engine.worker-DBKvSZGj.js", "path": "web/dist/assets/web-engine.worker-KtGrjS9Z.js",
"sha256": "4bcb7b07da820780ddaa738793fcabd8b3e87443d7fefb0df5e76da0969012ef" "sha256": "f862a82a377acb2e5df7e3f1e5790784692fb019426cc8eb33b16d0b117cf209"
}, },
"webDistWasm": { "webDistWasm": {
"path": "web/dist/assets/web_engine-CFJim5wW.wasm", "path": "web/dist/assets/web_engine-DW536ORx.wasm",
"sha256": "8db17ee31b2eec02bbbcda715de6fa8d1162e1b98e1f4f0394897b67dfc269d3" "sha256": "d7c0a3edcff1a3854fa243e194277dccdd6387d357f11aaf29334c06dd75c51b"
} }
}, },
"verification": { "verification": {

View File

@@ -5,11 +5,11 @@
"blenderRoot": "blender-5.2.0", "blenderRoot": "blender-5.2.0",
"mainAuthority": "blender_main", "mainAuthority": "blender_main",
"sourceFiles": { "sourceFiles": {
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp": "c05ca6449348baaa72fd9bc4dc49c3258e4e094ad270de13d0b16f101a70b139", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp": "3f3a37c4c76eaeb6fc5673aac27a4deb7bdd0ad5eb92b8c209eec9c74a28f098",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp": "bf933941d6bee592261d656751e088ee820dc6c8e15c9da6f16023916343ad79", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp": "193ef77dbc7d5d9cc0afe712b414506da2c796d9634e53dce959f6663be806be",
"web/protocol/web-engine.ts": "9e896b0e053b65f39bb980cf1ed683a0f93ebb6fefde0ec9c63282c523c7a874", "web/protocol/web-engine.ts": "a6f3861a75a667ab31f4aa91d8522eb69b63dd076ca75f93ff7a1dfb82708ac4",
"web/protocol/web-engine-capabilities.ts": "ede8ea0f5934760bd67d8375872e6eac526dde9e5c4380e3a731bd008804cdc4", "web/protocol/web-engine-capabilities.ts": "e3acd780cf16e87ca0405e1b75c377a6acda13d8c3102fa9ef52b5bdd0c223ac",
"web/app/src/workers/web-engine.worker.ts": "11cfeddd118566b10be647a000b3e1158daa6fb39bd6a6c83d49b6cd7aa99798" "web/app/src/workers/web-engine.worker.ts": "110977f0b00ebf2c426d4c2ebb3bf980eed4954b2e4d42244a46846e27770bfc"
} }
}, },
"inventory": { "inventory": {

View File

@@ -10,7 +10,7 @@
"artifacts": { "artifacts": {
"parentManifest": { "parentManifest": {
"path": "tests/golden/WBV2-P43-000/manifest.json", "path": "tests/golden/WBV2-P43-000/manifest.json",
"sha256": "cd20deaaa9258261307d1b76e1c7ce62492c118d0b0db4d0cf8cafb03570179c" "sha256": "5efda06373fb732f87ada41ca62b36cc7bf9390231627eb68126af95d044246f"
}, },
"source1": { "source1": {
"path": "tools/web/build-wbv2-capability-implementation-index.mjs", "path": "tools/web/build-wbv2-capability-implementation-index.mjs",
@@ -26,7 +26,7 @@
}, },
"implementationIndex": { "implementationIndex": {
"path": "tests/golden/WBV2-P43-001/capability-implementation-index.json", "path": "tests/golden/WBV2-P43-001/capability-implementation-index.json",
"sha256": "18270da6c665462f5fec523d5843e63e035c464231db5ebe2e3c19daee847760" "sha256": "4184fc8142072f08ed803fc06dfd3fab33c20777b30a1dbd43fded78950e1798"
}, },
"report": { "report": {
"path": "tests/golden/WBV2-P43-001/implementation-report.json", "path": "tests/golden/WBV2-P43-001/implementation-report.json",

View File

@@ -0,0 +1,151 @@
{
"schemaVersion": 1,
"planId": "BLENDER_WEB_CAPABILITY_CONTINUATION_P61",
"status": "ACTIVE_CAPABILITY_FAMILY_QUEUE",
"authority": "user_authorized_implementation_first_execution",
"sourceAuthority": {
"blenderRoot": "blender-5.2.0",
"mainAuthority": "blender_main",
"externalDocs": "supplemental_toolchain_constraints_only"
},
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"dedupeBy": [
"sourceHash",
"behaviorHash",
"dedupeKey"
]
},
"inventoryPolicy": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609,
"overlayMutation": "forbidden_during_implementation_wave"
},
"tasks": [
{
"id": "WBV2-P61-000",
"phase": "P61",
"title": "authorize_capability_family_wave",
"kind": "enabling",
"owner": "PROGRAM",
"dependsOn": [
"WBV2-P60-003"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-000",
"gate": "G1",
"card": "docs/tasks/WBV2-P61-000.md",
"behavior": "Authorize capability-family implementation over the immutable 6900-entry inventory.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": true
},
{
"id": "WBV2-P61-001",
"phase": "P61",
"title": "index_capability_family_batches",
"kind": "feature",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-000"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-001",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-001.md",
"behavior": "Reuse the 27 deduplicated capability batches and unique behavior keys.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "in_progress",
"ready": true,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-002",
"phase": "P61",
"title": "implement_capability_family_slice",
"kind": "feature",
"owner": "IMPLEMENTATION",
"dependsOn": [
"WBV2-P61-001"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-002",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-002.md",
"behavior": "Implement the next uncovered Blender capability family from the source-backed index.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "planned",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-003",
"phase": "P61",
"title": "run_capability_family_smoke",
"kind": "enabling",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-002"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-003",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-003.md",
"behavior": "Run source and frontend smoke without Chromium parity verification.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "planned",
"ready": false,
"queueMutationAllowed": false
}
]
}

View File

@@ -0,0 +1,30 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-000",
"operation": "AUTHORIZE_CAPABILITY_FAMILY_CONTINUATION",
"status": "PASS",
"parent": {
"task": "WBV2-P60-003",
"manifest": "tests/golden/WBV2-P60-003/manifest.json",
"manifestSha256": "7f8c2dfb3b1def1ff15b3fc6cc7e37d9ff41edd2bad90291e8c60d3695dec647"
},
"sourceAuthority": "blender-5.2.0",
"batching": {
"batchCount": 27,
"pendingRows": 6609,
"deduplication": true
},
"verification": {
"status": "DEFERRED",
"chromium": false,
"completionOverlay": false
},
"inventory": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609
},
"nextTask": "WBV2-P61-001"
}

View File

@@ -0,0 +1,39 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-000",
"parentTask": "WBV2-P60-003",
"operation": "AUTHORIZE_CAPABILITY_FAMILY_CONTINUATION",
"status": "done",
"enablingTask": true,
"parityStateChange": false,
"runtime": "SOURCE_BACKED_CAPABILITY_FAMILY_QUEUE",
"artifacts": {
"parentManifest": {
"path": "tests/golden/WBV2-P60-003/manifest.json",
"sha256": "7f8c2dfb3b1def1ff15b3fc6cc7e37d9ff41edd2bad90291e8c60d3695dec647"
},
"plan": {
"path": "tests/golden/WBV2-P61-000/capability-continuation-plan.json",
"sha256": "c05c291ade6fe780e99a0ebb7181fd3ce6dbf4cf9b2056108151c0734677b73c"
},
"report": {
"path": "tests/golden/WBV2-P61-000/capability-continuation-root-report.json",
"sha256": "c43d485daa28db13152b8bad5e25d163e1ec2663fab8bd043f508077b351d5c6"
},
"status": {
"path": "docs/status/WBV2-P61-000.md",
"sha256": "039a8f54caa5ad2d243f7654639e4a4d440ad05f17b7efdb7fd8cb9b161d08a0"
}
},
"assertions": {
"batchCount": 27,
"pendingRows": 6609,
"verificationDeferred": true,
"completionOverlayWritten": false,
"inventoryTotal": 6900,
"effectiveCompleted": 290,
"effectivePending": 6609,
"historicalReproduction": false
},
"nextTask": "WBV2-P61-001"
}

View File

@@ -60,7 +60,7 @@
"real Blender source or WebEngine Main path is wired", "real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred" "verification and completion overlay remain deferred"
], ],
"nextTask": null, "nextTask": "WBV2-P61-001",
"sourceDocuments": { "sourceDocuments": {
"queue": "docs/EXECUTION_QUEUE.md", "queue": "docs/EXECUTION_QUEUE.md",
"taskCard": "docs/tasks/WBV2-P61-000.md", "taskCard": "docs/tasks/WBV2-P61-000.md",
@@ -156,7 +156,7 @@
"totalTokens": 1552, "totalTokens": 1552,
"reservedEnvelopeTokens": 1024, "reservedEnvelopeTokens": 1024,
"estimatedContextTokens": 2576, "estimatedContextTokens": 2576,
"serializedContextTokens": 619, "serializedContextTokens": 622,
"withinBudget": true "withinBudget": true
} }
} }

View File

@@ -0,0 +1,151 @@
{
"schemaVersion": 1,
"planId": "BLENDER_WEB_CAPABILITY_CONTINUATION_P61",
"status": "ACTIVE_CAPABILITY_FAMILY_QUEUE",
"authority": "user_authorized_implementation_first_execution",
"sourceAuthority": {
"blenderRoot": "blender-5.2.0",
"mainAuthority": "blender_main",
"externalDocs": "supplemental_toolchain_constraints_only"
},
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"dedupeBy": [
"sourceHash",
"behaviorHash",
"dedupeKey"
]
},
"inventoryPolicy": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609,
"overlayMutation": "forbidden_during_implementation_wave"
},
"tasks": [
{
"id": "WBV2-P61-000",
"phase": "P61",
"title": "authorize_capability_family_wave",
"kind": "enabling",
"owner": "PROGRAM",
"dependsOn": [
"WBV2-P60-003"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-000",
"gate": "G1",
"card": "docs/tasks/WBV2-P61-000.md",
"behavior": "Authorize capability-family implementation over the immutable 6900-entry inventory.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": true
},
{
"id": "WBV2-P61-001",
"phase": "P61",
"title": "index_capability_family_batches",
"kind": "feature",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-000"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-001",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-001.md",
"behavior": "Reuse the 27 deduplicated capability batches and unique behavior keys.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-002",
"phase": "P61",
"title": "implement_capability_family_slice",
"kind": "feature",
"owner": "IMPLEMENTATION",
"dependsOn": [
"WBV2-P61-001"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-002",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-002.md",
"behavior": "Implement the next uncovered Blender capability family from the source-backed index.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "in_progress",
"ready": true,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-003",
"phase": "P61",
"title": "run_capability_family_smoke",
"kind": "enabling",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-002"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-003",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-003.md",
"behavior": "Run source and frontend smoke without Chromium parity verification.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "planned",
"ready": false,
"queueMutationAllowed": false
}
]
}

View File

@@ -0,0 +1,32 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-001",
"operation": "IMPLEMENT_CAPABILITY_FAMILY_CONTINUATION",
"status": "PASS",
"family": "INVENTORY.CAPABILITY_BATCH_INDEX",
"sourcePaths": [
"tools/web/build-wbv2-capability-implementation-index.mjs",
"tests/golden/WBV2-P27-001/verification-batch-plan.json"
],
"command": "/home/mes123456/.nvm/versions/node/v24.19.0/bin/node tools/web/build-wbv2-capability-implementation-index.mjs",
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"deduplication": true
},
"verification": {
"status": "DEFERRED",
"chromium": false,
"e2eReceipts": false,
"completionOverlay": false
},
"inventory": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609
},
"nextTask": "WBV2-P61-002"
}

View File

@@ -0,0 +1,53 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-001",
"parentTask": "WBV2-P61-000",
"operation": "IMPLEMENT_CAPABILITY_FAMILY_CONTINUATION",
"status": "done",
"enablingTask": false,
"parityStateChange": false,
"runtime": "SOURCE_BACKED_CAPABILITY_FAMILY_QUEUE",
"artifacts": {
"parentManifest": {
"path": "tests/golden/WBV2-P61-000/manifest.json",
"sha256": "c20911c1661106374fd3fded133ee5f9adc1a69033fb2a857e1b28fecfeebcc7"
},
"source1": {
"path": "tools/web/build-wbv2-capability-implementation-index.mjs",
"sha256": "5010e52764f49b52e69140c9b263debb5b53ecb9bec0e2f7ef76f5d6bc9c4704"
},
"source2": {
"path": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"sha256": "56dddc2e4c380f364d1760dfd9bc7a6be04c1bd8979e0c2aeaa69ae80e80a14e"
},
"report": {
"path": "tests/golden/WBV2-P61-001/implementation-report.json",
"sha256": "24e42c3ea1264c64d319e9315de773a2ceb164e7d33ebdfb8af8f964eede3fff"
},
"status": {
"path": "docs/status/WBV2-P61-001.md",
"sha256": "be9e37a2252e1f9eabb9b664417c468f8d35c87180e1fa6eafecb1f04466eb55"
},
"plan": {
"path": "tests/golden/WBV2-P61-001/capability-continuation-plan.json",
"sha256": "cfe3e35fb8b30504b85ea04a34b0b94d28038680299a8cfb11339b59d62a8162"
},
"taskContext": {
"path": "tests/golden/WBV2-P61-001/task-context.json",
"sha256": "b17da3a20f55a5228a1715272a6a4b6cf74f640f84d2e86275a2f84a9928ca9c"
}
},
"assertions": {
"capabilityFamily": "INVENTORY.CAPABILITY_BATCH_INDEX",
"sourceBacked": true,
"batchCount": 27,
"pendingRows": 6609,
"verificationDeferred": true,
"completionOverlayWritten": false,
"inventoryTotal": 6900,
"effectiveCompleted": 290,
"effectivePending": 6609,
"historicalReproduction": false
},
"nextTask": "WBV2-P61-002"
}

View File

@@ -0,0 +1,167 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-001",
"parentTask": "WBV2-P61-000",
"status": "in_progress",
"goal": "Reuse the 27 deduplicated capability batches and unique behavior keys.",
"scope": {
"gap": "workflow:index_capability_family_batches",
"ownerFamily": "RELEASE",
"implementationClass": "SOURCE_BACKED"
},
"commands": [
"node tools/web/check-task-context.mjs --task WBV2-P61-001 --write"
],
"inputPaths": [],
"inputSelection": {
"schemaVersion": 1,
"limits": {
"maxFiles": 12,
"evidenceBytes": 8192,
"contextRemainingBytes": 4232,
"contextRemainingTokens": 1057
},
"source": {
"bytes": 5672,
"tokens": 1419
},
"selected": [],
"excluded": [
{
"path": "blender-5.2.0/source/blender",
"bytes": 12546,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"bytes": 21184,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P61-001/",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "docs/status/WBV2-P61-001.md",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "tests/golden/WBV2-P61-001/manifest.json",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
}
],
"totals": {
"files": 0,
"bytes": 0,
"tokens": 0
}
},
"exitCriteria": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"nextTask": "WBV2-P61-002",
"sourceDocuments": {
"queue": "docs/EXECUTION_QUEUE.md",
"taskCard": "docs/tasks/WBV2-P61-001.md",
"taskIndex": "tests/golden/WBV2/task-index.json",
"parentManifest": "tests/golden/WBV2-P61-000/manifest.json",
"parentStatus": "docs/status/WBV2-P61-000.md"
},
"readPolicy": {
"required": [
"docs/EXECUTION_QUEUE.md",
"docs/tasks/WBV2-P61-001.md",
"tests/golden/WBV2-P61-000/manifest.json",
"docs/status/WBV2-P61-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-P61-000",
"parentTask": "WBV2-P60-003",
"status": "done",
"nextTask": "WBV2-P61-001",
"artifactCount": 4
},
"statusSummary": [
"# WBV2-P61-000 status",
"- task: `WBV2-P61-000`; parent: `WBV2-P60-003`; status: `done`",
"- capability-family continuation authorized from Blender source",
"- 6900 inventory: 27 deduplicated batches, 6609 pending rows",
"- verification and completion overlay: `DEFERRED`",
"- nextTask: `WBV2-P61-001`"
]
},
"budgets": {
"queueBytes": 4096,
"taskBytes": 1299,
"parentManifestBytes": 24576,
"parentStatusBytes": 6144,
"evidenceFiles": 12,
"evidenceBytes": 8192,
"contextTokens": 3500,
"contextEnvelopeTokens": 1024,
"taskLines": 39,
"taskTokens": 325
},
"size": {
"documents": [
{
"path": "docs/EXECUTION_QUEUE.md",
"bytes": 2803,
"lines": 51,
"tokens": 701
},
{
"path": "docs/tasks/WBV2-P61-001.md",
"bytes": 1299,
"lines": 39,
"tokens": 325
},
{
"path": "tests/golden/WBV2-P61-000/manifest.json",
"bytes": 1282,
"lines": 40,
"tokens": 321
},
{
"path": "docs/status/WBV2-P61-000.md",
"bytes": 288,
"lines": 8,
"tokens": 72
}
],
"sourceTokens": 1419,
"evidenceFiles": 0,
"evidenceBytes": 0,
"evidenceTokens": 0,
"totalTokens": 1419,
"reservedEnvelopeTokens": 1024,
"estimatedContextTokens": 2443,
"serializedContextTokens": 620,
"withinBudget": true
}
}

View File

@@ -0,0 +1,151 @@
{
"schemaVersion": 1,
"planId": "BLENDER_WEB_CAPABILITY_CONTINUATION_P61",
"status": "ACTIVE_CAPABILITY_FAMILY_QUEUE",
"authority": "user_authorized_implementation_first_execution",
"sourceAuthority": {
"blenderRoot": "blender-5.2.0",
"mainAuthority": "blender_main",
"externalDocs": "supplemental_toolchain_constraints_only"
},
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"dedupeBy": [
"sourceHash",
"behaviorHash",
"dedupeKey"
]
},
"inventoryPolicy": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609,
"overlayMutation": "forbidden_during_implementation_wave"
},
"tasks": [
{
"id": "WBV2-P61-000",
"phase": "P61",
"title": "authorize_capability_family_wave",
"kind": "enabling",
"owner": "PROGRAM",
"dependsOn": [
"WBV2-P60-003"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-000",
"gate": "G1",
"card": "docs/tasks/WBV2-P61-000.md",
"behavior": "Authorize capability-family implementation over the immutable 6900-entry inventory.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": true
},
{
"id": "WBV2-P61-001",
"phase": "P61",
"title": "index_capability_family_batches",
"kind": "feature",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-000"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-001",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-001.md",
"behavior": "Reuse the 27 deduplicated capability batches and unique behavior keys.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-002",
"phase": "P61",
"title": "implement_capability_family_slice",
"kind": "feature",
"owner": "IMPLEMENTATION",
"dependsOn": [
"WBV2-P61-001"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-002",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-002.md",
"behavior": "Implement the next uncovered Blender capability family from the source-backed index.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-003",
"phase": "P61",
"title": "run_capability_family_smoke",
"kind": "enabling",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-002"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-003",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-003.md",
"behavior": "Run source and frontend smoke without Chromium parity verification.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "in_progress",
"ready": true,
"queueMutationAllowed": false
}
]
}

View File

@@ -0,0 +1,34 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-002",
"operation": "IMPLEMENT_CAPABILITY_FAMILY_CONTINUATION",
"status": "PASS",
"family": "CORE_SCENE_GRAPH.COLOR_MANAGEMENT",
"sourcePaths": [
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp",
"blender-5.2.0/source/blender/web_engine/web_engine_main_state.h",
"blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"
],
"command": "existing source-backed workbench wiring",
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"deduplication": true
},
"verification": {
"status": "DEFERRED",
"chromium": false,
"e2eReceipts": false,
"completionOverlay": false
},
"inventory": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609
},
"nextTask": "WBV2-P61-003"
}

View File

@@ -0,0 +1,61 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-002",
"parentTask": "WBV2-P61-001",
"operation": "IMPLEMENT_CAPABILITY_FAMILY_CONTINUATION",
"status": "done",
"enablingTask": false,
"parityStateChange": false,
"runtime": "SOURCE_BACKED_CAPABILITY_FAMILY_QUEUE",
"artifacts": {
"parentManifest": {
"path": "tests/golden/WBV2-P61-001/manifest.json",
"sha256": "536b927e5a09ee7dcd51087022d43b20d84c94122e57816d6c3efc382870ee21"
},
"source1": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp",
"sha256": "a83129b2a2a1038ba6de66e8e4f7cb9388ca26b5ea723ed8743d5c27445dd07c"
},
"source2": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h",
"sha256": "2ef8ba3a0499d2a8c3b3490e65bccefe7fb069d368627a6c10378f921348114e"
},
"source3": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp",
"sha256": "a7889d1c91feb61780459518b454692d6416d7f4312c34d748ba77c2045f3975"
},
"source4": {
"path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp",
"sha256": "3ea8e9862f88b742ec7eb06c58cc7ad72c53a00377a75044a1a0e109c522aca9"
},
"report": {
"path": "tests/golden/WBV2-P61-002/implementation-report.json",
"sha256": "f79a658fc035b07eab3569df2f38ff8efd24bbcf73a908cf68231e68ad7e024c"
},
"status": {
"path": "docs/status/WBV2-P61-002.md",
"sha256": "ffa205b7fec8f821a8e7868fe218ca2e4e4bbfe20ac05de74640d0ebcffaafd0"
},
"plan": {
"path": "tests/golden/WBV2-P61-002/capability-continuation-plan.json",
"sha256": "06e3884085fa010b355a7cfe9f5fb0fe3444710220c15b5893e3edc31f45aa29"
},
"taskContext": {
"path": "tests/golden/WBV2-P61-002/task-context.json",
"sha256": "baabadd57f9c2713104a3365cbab8a5732952cb3b3b592955ff8d8559517cb64"
}
},
"assertions": {
"capabilityFamily": "CORE_SCENE_GRAPH.COLOR_MANAGEMENT",
"sourceBacked": true,
"batchCount": 27,
"pendingRows": 6609,
"verificationDeferred": true,
"completionOverlayWritten": false,
"inventoryTotal": 6900,
"effectiveCompleted": 290,
"effectivePending": 6609,
"historicalReproduction": false
},
"nextTask": "WBV2-P61-003"
}

View File

@@ -0,0 +1,167 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-002",
"parentTask": "WBV2-P61-001",
"status": "planned",
"goal": "Implement the next uncovered Blender capability family from the source-backed index.",
"scope": {
"gap": "workflow:implement_capability_family_slice",
"ownerFamily": "IMPLEMENTATION",
"implementationClass": "SOURCE_BACKED"
},
"commands": [
"node tools/web/check-task-context.mjs --task WBV2-P61-002 --write"
],
"inputPaths": [],
"inputSelection": {
"schemaVersion": 1,
"limits": {
"maxFiles": 12,
"evidenceBytes": 8192,
"contextRemainingBytes": 3577,
"contextRemainingTokens": 893
},
"source": {
"bytes": 6327,
"tokens": 1583
},
"selected": [],
"excluded": [
{
"path": "blender-5.2.0/source/blender",
"bytes": 12546,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"bytes": 21184,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P61-002/",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "docs/status/WBV2-P61-002.md",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "tests/golden/WBV2-P61-002/manifest.json",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
}
],
"totals": {
"files": 0,
"bytes": 0,
"tokens": 0
}
},
"exitCriteria": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"nextTask": "WBV2-P61-003",
"sourceDocuments": {
"queue": "docs/EXECUTION_QUEUE.md",
"taskCard": "docs/tasks/WBV2-P61-002.md",
"taskIndex": "tests/golden/WBV2/task-index.json",
"parentManifest": "tests/golden/WBV2-P61-001/manifest.json",
"parentStatus": "docs/status/WBV2-P61-001.md"
},
"readPolicy": {
"required": [
"docs/EXECUTION_QUEUE.md",
"docs/tasks/WBV2-P61-002.md",
"tests/golden/WBV2-P61-001/manifest.json",
"docs/status/WBV2-P61-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-P61-001",
"parentTask": "WBV2-P61-000",
"status": "done",
"nextTask": "WBV2-P61-002",
"artifactCount": 7
},
"statusSummary": [
"# WBV2-P61-001 status",
"- task: `WBV2-P61-001`; parent: `WBV2-P61-000`; status: `done`",
"- capability-family implementation: `PASS`; 27 deduplicated batches; 6609 pending rows",
"- Chromium, E2E receipts and completion overlay: `DEFERRED`",
"- inventory unchanged: `6900/6618`, effective `290/6609`",
"- nextTask: `WBV2-P61-002`"
]
},
"budgets": {
"queueBytes": 4096,
"taskBytes": 1320,
"parentManifestBytes": 24576,
"parentStatusBytes": 6144,
"evidenceFiles": 12,
"evidenceBytes": 8192,
"contextTokens": 3500,
"contextEnvelopeTokens": 1024,
"taskLines": 39,
"taskTokens": 330
},
"size": {
"documents": [
{
"path": "docs/EXECUTION_QUEUE.md",
"bytes": 2803,
"lines": 51,
"tokens": 701
},
{
"path": "docs/tasks/WBV2-P61-002.md",
"bytes": 1320,
"lines": 39,
"tokens": 330
},
{
"path": "tests/golden/WBV2-P61-001/manifest.json",
"bytes": 1887,
"lines": 54,
"tokens": 472
},
{
"path": "docs/status/WBV2-P61-001.md",
"bytes": 317,
"lines": 8,
"tokens": 80
}
],
"sourceTokens": 1583,
"evidenceFiles": 0,
"evidenceBytes": 0,
"evidenceTokens": 0,
"totalTokens": 1583,
"reservedEnvelopeTokens": 1024,
"estimatedContextTokens": 2607,
"serializedContextTokens": 625,
"withinBudget": true
}
}

View File

@@ -0,0 +1,181 @@
{
"schemaVersion": 1,
"planId": "BLENDER_WEB_CAPABILITY_CONTINUATION_P61",
"status": "ACTIVE_CAPABILITY_FAMILY_QUEUE",
"authority": "user_authorized_implementation_first_execution",
"sourceAuthority": {
"blenderRoot": "blender-5.2.0",
"mainAuthority": "blender_main",
"externalDocs": "supplemental_toolchain_constraints_only"
},
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"dedupeBy": [
"sourceHash",
"behaviorHash",
"dedupeKey"
]
},
"inventoryPolicy": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609,
"overlayMutation": "forbidden_during_implementation_wave"
},
"tasks": [
{
"id": "WBV2-P61-000",
"phase": "P61",
"title": "authorize_capability_family_wave",
"kind": "enabling",
"owner": "PROGRAM",
"dependsOn": [
"WBV2-P60-003"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-000",
"gate": "G1",
"card": "docs/tasks/WBV2-P61-000.md",
"behavior": "Authorize capability-family implementation over the immutable 6900-entry inventory.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": true
},
{
"id": "WBV2-P61-001",
"phase": "P61",
"title": "index_capability_family_batches",
"kind": "feature",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-000"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-001",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-001.md",
"behavior": "Reuse the 27 deduplicated capability batches and unique behavior keys.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-002",
"phase": "P61",
"title": "implement_capability_family_slice",
"kind": "feature",
"owner": "IMPLEMENTATION",
"dependsOn": [
"WBV2-P61-001"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-002",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-002.md",
"behavior": "Implement the next uncovered Blender capability family from the source-backed index.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P61-003",
"phase": "P61",
"title": "run_capability_family_smoke",
"kind": "enabling",
"owner": "RELEASE",
"dependsOn": [
"WBV2-P61-002"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p61-003",
"gate": "IMPLEMENTATION",
"card": "docs/tasks/WBV2-P61-003.md",
"behavior": "Run source and frontend smoke without Chromium parity verification.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "done",
"ready": false,
"queueMutationAllowed": false
},
{
"id": "WBV2-P62-000",
"phase": "P62",
"title": "authorize_capability_family_wave",
"kind": "enabling",
"owner": "PROGRAM",
"dependsOn": [
"WBV2-P61-003"
],
"parityId": null,
"implementationClass": "SOURCE_BACKED",
"parallelGroup": "p62-000",
"gate": "G1",
"card": "docs/tasks/WBV2-P62-000.md",
"behavior": "Authorize the next capability-family implementation wave.",
"outputs": [
"implementation-report",
"manifest",
"status"
],
"acceptance": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"status": "in_progress",
"ready": true,
"queueMutationAllowed": true
}
]
}

View File

@@ -0,0 +1,33 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-003",
"operation": "IMPLEMENT_CAPABILITY_FAMILY_CONTINUATION",
"status": "PASS",
"family": "IMPLEMENTATION.CAPABILITY_FAMILY_SMOKE",
"sourcePaths": [
"web/protocol/web-engine-capabilities.ts",
"web/app/src/workers/web-engine.worker.ts",
"web/app/src/vendor/blender/web_engine.wasm"
],
"command": "npm --prefix web run build",
"batching": {
"sourcePlan": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"batchCount": 27,
"pendingRows": 6609,
"deduplication": true
},
"verification": {
"status": "DEFERRED",
"chromium": false,
"e2eReceipts": false,
"completionOverlay": false
},
"inventory": {
"total": 6900,
"legacyCompleted": 281,
"legacyPending": 6618,
"effectiveCompleted": 290,
"effectivePending": 6609
},
"nextTask": "WBV2-P62-000"
}

View File

@@ -0,0 +1,57 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-003",
"parentTask": "WBV2-P61-002",
"operation": "IMPLEMENT_CAPABILITY_FAMILY_CONTINUATION",
"status": "done",
"enablingTask": false,
"parityStateChange": false,
"runtime": "SOURCE_BACKED_CAPABILITY_FAMILY_QUEUE",
"artifacts": {
"parentManifest": {
"path": "tests/golden/WBV2-P61-002/manifest.json",
"sha256": "7c0fb22ed0dae236feee12b9e736d617cf286756c821fdba91e9e425fae18ec9"
},
"source1": {
"path": "web/protocol/web-engine-capabilities.ts",
"sha256": "298bcea3761ee13940b37e7e5233900cc7169da1b86cb7174f0eaf4ab97b3cee"
},
"source2": {
"path": "web/app/src/workers/web-engine.worker.ts",
"sha256": "4944108f93829449b0ae98aa0ded71c8a513237f0d4abb93b15600e7c0cae2b7"
},
"source3": {
"path": "web/app/src/vendor/blender/web_engine.wasm",
"sha256": "d7c0a3edcff1a3854fa243e194277dccdd6387d357f11aaf29334c06dd75c51b"
},
"report": {
"path": "tests/golden/WBV2-P61-003/implementation-report.json",
"sha256": "98d66b409feb690d9a61d60f778ecc5cf0fac2991ea24c994e7c780712465c5b"
},
"status": {
"path": "docs/status/WBV2-P61-003.md",
"sha256": "e59bcb07b04bfb54863ff7134329abf847f2269ed824e29915c411367415af20"
},
"plan": {
"path": "tests/golden/WBV2-P61-003/capability-continuation-plan.json",
"sha256": "4b65db2f20bbb0d09f3051abfd13148e3722733124ee3f0905e6e4152662f31d"
},
"taskContext": {
"path": "tests/golden/WBV2-P61-003/task-context.json",
"sha256": "de626039d22a208e44c8ebe0e4668c90a7dbc1c7d46dd15c9f08176b2c813dbc"
}
},
"assertions": {
"capabilityFamily": "IMPLEMENTATION.CAPABILITY_FAMILY_SMOKE",
"sourceBacked": true,
"batchCount": 27,
"pendingRows": 6609,
"verificationDeferred": true,
"completionOverlayWritten": false,
"inventoryTotal": 6900,
"effectiveCompleted": 290,
"effectivePending": 6609,
"historicalReproduction": false
},
"nextTask": "WBV2-P62-000"
}

View File

@@ -0,0 +1,167 @@
{
"schemaVersion": 1,
"task": "WBV2-P61-003",
"parentTask": "WBV2-P61-002",
"status": "planned",
"goal": "Run source and frontend smoke without Chromium parity verification.",
"scope": {
"gap": "workflow:run_capability_family_smoke",
"ownerFamily": "RELEASE",
"implementationClass": "SOURCE_BACKED"
},
"commands": [
"node tools/web/check-task-context.mjs --task WBV2-P61-003 --write"
],
"inputPaths": [],
"inputSelection": {
"schemaVersion": 1,
"limits": {
"maxFiles": 12,
"evidenceBytes": 8192,
"contextRemainingBytes": 3219,
"contextRemainingTokens": 803
},
"source": {
"bytes": 6685,
"tokens": 1673
},
"selected": [],
"excluded": [
{
"path": "blender-5.2.0/source/blender",
"bytes": 12546,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P27-001/verification-batch-plan.json",
"bytes": 21184,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P61-003/",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "docs/status/WBV2-P61-003.md",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "tests/golden/WBV2-P61-003/manifest.json",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
}
],
"totals": {
"files": 0,
"bytes": 0,
"tokens": 0
}
},
"exitCriteria": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"nextTask": "WBV2-P62-000",
"sourceDocuments": {
"queue": "docs/EXECUTION_QUEUE.md",
"taskCard": "docs/tasks/WBV2-P61-003.md",
"taskIndex": "tests/golden/WBV2/task-index.json",
"parentManifest": "tests/golden/WBV2-P61-002/manifest.json",
"parentStatus": "docs/status/WBV2-P61-002.md"
},
"readPolicy": {
"required": [
"docs/EXECUTION_QUEUE.md",
"docs/tasks/WBV2-P61-003.md",
"tests/golden/WBV2-P61-002/manifest.json",
"docs/status/WBV2-P61-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-P61-002",
"parentTask": "WBV2-P61-001",
"status": "done",
"nextTask": "WBV2-P61-003",
"artifactCount": 9
},
"statusSummary": [
"# WBV2-P61-002 status",
"- task: `WBV2-P61-002`; parent: `WBV2-P61-001`; status: `done`",
"- capability-family implementation: `PASS`; 27 deduplicated batches; 6609 pending rows",
"- Chromium, E2E receipts and completion overlay: `DEFERRED`",
"- inventory unchanged: `6900/6618`, effective `290/6609`",
"- nextTask: `WBV2-P61-003`"
]
},
"budgets": {
"queueBytes": 4096,
"taskBytes": 1284,
"parentManifestBytes": 24576,
"parentStatusBytes": 6144,
"evidenceFiles": 12,
"evidenceBytes": 8192,
"contextTokens": 3500,
"contextEnvelopeTokens": 1024,
"taskLines": 39,
"taskTokens": 321
},
"size": {
"documents": [
{
"path": "docs/EXECUTION_QUEUE.md",
"bytes": 2803,
"lines": 51,
"tokens": 701
},
{
"path": "docs/tasks/WBV2-P61-003.md",
"bytes": 1284,
"lines": 39,
"tokens": 321
},
{
"path": "tests/golden/WBV2-P61-002/manifest.json",
"bytes": 2281,
"lines": 62,
"tokens": 571
},
{
"path": "docs/status/WBV2-P61-002.md",
"bytes": 317,
"lines": 8,
"tokens": 80
}
],
"sourceTokens": 1673,
"evidenceFiles": 0,
"evidenceBytes": 0,
"evidenceTokens": 0,
"totalTokens": 1673,
"reservedEnvelopeTokens": 1024,
"estimatedContextTokens": 2697,
"serializedContextTokens": 617,
"withinBudget": true
}
}

View File

@@ -0,0 +1,162 @@
{
"schemaVersion": 1,
"task": "WBV2-P62-000",
"parentTask": "WBV2-P61-003",
"status": "in_progress",
"goal": "Authorize the next capability-family implementation wave from Blender source.",
"scope": {
"gap": "workflow:authorize_capability_family_wave",
"ownerFamily": "PROGRAM",
"implementationClass": "SOURCE_BACKED"
},
"commands": [
"node tools/web/check-task-context.mjs --task WBV2-P62-000 --write"
],
"inputPaths": [],
"inputSelection": {
"schemaVersion": 1,
"limits": {
"maxFiles": 12,
"evidenceBytes": 8192,
"contextRemainingBytes": 3703,
"contextRemainingTokens": 924
},
"source": {
"bytes": 6201,
"tokens": 1552
},
"selected": [],
"excluded": [
{
"path": "blender-5.2.0/source/blender",
"bytes": 12546,
"reason": "EVIDENCE_BYTE_BUDGET"
},
{
"path": "tests/golden/WBV2-P62-000/",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "docs/status/WBV2-P62-000.md",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
},
{
"path": "tests/golden/WBV2-P62-000/manifest.json",
"bytes": null,
"reason": "GENERATED_EVIDENCE_OUTPUT"
}
],
"totals": {
"files": 0,
"bytes": 0,
"tokens": 0
}
},
"exitCriteria": [
"6900 inventory remains immutable",
"capability families are deduplicated before implementation",
"real Blender source or WebEngine Main path is wired",
"verification and completion overlay remain deferred"
],
"nextTask": null,
"sourceDocuments": {
"queue": "docs/EXECUTION_QUEUE.md",
"taskCard": "docs/tasks/WBV2-P62-000.md",
"taskIndex": "tests/golden/WBV2/task-index.json",
"parentManifest": "tests/golden/WBV2-P61-003/manifest.json",
"parentStatus": "docs/status/WBV2-P61-003.md"
},
"readPolicy": {
"required": [
"docs/EXECUTION_QUEUE.md",
"docs/tasks/WBV2-P62-000.md",
"tests/golden/WBV2-P61-003/manifest.json",
"docs/status/WBV2-P61-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-P61-003",
"parentTask": "WBV2-P61-002",
"status": "done",
"nextTask": "WBV2-P62-000",
"artifactCount": 8
},
"statusSummary": [
"# WBV2-P61-003 status",
"- task: `WBV2-P61-003`; parent: `WBV2-P61-002`; status: `done`",
"- capability-family implementation: `PASS`; 27 deduplicated batches; 6609 pending rows",
"- Chromium, E2E receipts and completion overlay: `DEFERRED`",
"- inventory unchanged: `6900/6618`, effective `290/6609`",
"- nextTask: `WBV2-P62-000`"
]
},
"budgets": {
"queueBytes": 4096,
"taskBytes": 1052,
"parentManifestBytes": 24576,
"parentStatusBytes": 6144,
"evidenceFiles": 12,
"evidenceBytes": 8192,
"contextTokens": 3500,
"contextEnvelopeTokens": 1024,
"taskLines": 36,
"taskTokens": 263
},
"size": {
"documents": [
{
"path": "docs/EXECUTION_QUEUE.md",
"bytes": 2803,
"lines": 51,
"tokens": 701
},
{
"path": "docs/tasks/WBV2-P62-000.md",
"bytes": 1052,
"lines": 36,
"tokens": 263
},
{
"path": "tests/golden/WBV2-P61-003/manifest.json",
"bytes": 2029,
"lines": 58,
"tokens": 508
},
{
"path": "docs/status/WBV2-P61-003.md",
"bytes": 317,
"lines": 8,
"tokens": 80
}
],
"sourceTokens": 1552,
"evidenceFiles": 0,
"evidenceBytes": 0,
"evidenceTokens": 0,
"totalTokens": 1552,
"reservedEnvelopeTokens": 1024,
"estimatedContextTokens": 2576,
"serializedContextTokens": 619,
"withinBudget": true
}
}

View File

@@ -1,5 +1,5 @@
{"id":"WBV2-P60-000","gapId":"workflow:authorize_capability_family_wave","ownerFamily":"PROGRAM","sourceTask":"P60","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]} {"id":"WBV2-P61-000","gapId":"workflow:authorize_capability_family_wave","ownerFamily":"PROGRAM","sourceTask":"P61","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]}
{"id":"WBV2-P60-001","gapId":"workflow:index_capability_family_batches","ownerFamily":"RELEASE","sourceTask":"P60","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]} {"id":"WBV2-P61-001","gapId":"workflow:index_capability_family_batches","ownerFamily":"RELEASE","sourceTask":"P61","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]}
{"id":"WBV2-P60-002","gapId":"workflow:implement_capability_family_slice","ownerFamily":"IMPLEMENTATION","sourceTask":"P60","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]} {"id":"WBV2-P61-002","gapId":"workflow:implement_capability_family_slice","ownerFamily":"IMPLEMENTATION","sourceTask":"P61","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]}
{"id":"WBV2-P60-003","gapId":"workflow:run_capability_family_smoke","ownerFamily":"RELEASE","sourceTask":"P60","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]} {"id":"WBV2-P61-003","gapId":"workflow:run_capability_family_smoke","ownerFamily":"RELEASE","sourceTask":"P61","state":"completed","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]}
{"id":"WBV2-P61-000","gapId":"workflow:authorize_capability_family_wave","ownerFamily":"PROGRAM","sourceTask":"P61","state":"active","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]} {"id":"WBV2-P62-000","gapId":"workflow:authorize_capability_family_wave","ownerFamily":"PROGRAM","sourceTask":"P62","state":"active","targetImplementationClass":"SOURCE_BACKED","exitCriteria":["6900 inventory remains immutable","capability families are deduplicated before implementation","real Blender source or WebEngine Main path is wired","verification and completion overlay remain deferred"]}

View File

@@ -1 +1 @@
{"schemaVersion":1,"operation":"BLENDER_WEB_CAPABILITY_TASK_INDEX","source":{"path":"tests/golden/WBV2-P60-003/capability-continuation-plan.json","sha256":"1c933defa66e06c23730e10dda10631c29f18cb1a0d60da01f4ce84476c1be7f"},"catalog":{"path":"tests/golden/WBV2/task-catalog.jsonl","sha256":"330b7c3f70837b8d92960b3d715b3512d83bd4209115ccbaa8bdee06c3d9a786"},"taskCount":5,"activeTask":"WBV2-P61-000","entries":{"WBV2-P60-000":{"line":0,"offset":0,"length":402,"previous":"WBV2-P59-003","next":"WBV2-P60-001"},"WBV2-P60-001":{"line":1,"offset":402,"length":401,"previous":"WBV2-P60-000","next":"WBV2-P60-002"},"WBV2-P60-002":{"line":2,"offset":803,"length":410,"previous":"WBV2-P60-001","next":"WBV2-P60-003"},"WBV2-P60-003":{"line":3,"offset":1213,"length":397,"previous":"WBV2-P60-002","next":"WBV2-P61-000"},"WBV2-P61-000":{"line":4,"offset":1610,"length":399,"previous":"WBV2-P60-003","next":null}}} {"schemaVersion":1,"operation":"BLENDER_WEB_CAPABILITY_TASK_INDEX","source":{"path":"tests/golden/WBV2-P61-003/capability-continuation-plan.json","sha256":"4b65db2f20bbb0d09f3051abfd13148e3722733124ee3f0905e6e4152662f31d"},"catalog":{"path":"tests/golden/WBV2/task-catalog.jsonl","sha256":"5689ee5e834724bdd8166382d4fb7ac5d6666fee05b7cd78fca92981b02ec4d4"},"taskCount":5,"activeTask":"WBV2-P62-000","entries":{"WBV2-P61-000":{"line":0,"offset":0,"length":402,"previous":"WBV2-P60-003","next":"WBV2-P61-001"},"WBV2-P61-001":{"line":1,"offset":402,"length":401,"previous":"WBV2-P61-000","next":"WBV2-P61-002"},"WBV2-P61-002":{"line":2,"offset":803,"length":410,"previous":"WBV2-P61-001","next":"WBV2-P61-003"},"WBV2-P61-003":{"line":3,"offset":1213,"length":397,"previous":"WBV2-P61-002","next":"WBV2-P62-000"},"WBV2-P62-000":{"line":4,"offset":1610,"length":399,"previous":"WBV2-P61-003","next":null}}}

View File

@@ -26,13 +26,13 @@ assert.equal(parent.status, "done");
assert.equal(parent.nextTask, task); assert.equal(parent.nextTask, task);
const commands = { 1: [process.execPath, "tools/web/build-wbv2-capability-implementation-index.mjs"], 2: null, 3: ["npm", "--prefix", "web", "run", "build"] }; const commands = { 1: [process.execPath, "tools/web/build-wbv2-capability-implementation-index.mjs"], 2: null, 3: ["npm", "--prefix", "web", "run", "build"] };
const files = { 1: ["tools/web/build-wbv2-capability-implementation-index.mjs", "tests/golden/WBV2-P27-001/verification-batch-plan.json"], 2: phase >= 59 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 57 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 56 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 55 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 54 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 53 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 52 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 51 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 50 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 49 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 47 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "web/protocol/web-engine.ts"] : ["web/app/src/app/App.tsx", "web/protocol/web-engine-capabilities.ts"], 3: ["web/protocol/web-engine-capabilities.ts", "web/app/src/workers/web-engine.worker.ts", "web/app/src/vendor/blender/web_engine.wasm"] }; const files = { 1: ["tools/web/build-wbv2-capability-implementation-index.mjs", "tests/golden/WBV2-P27-001/verification-batch-plan.json"], 2: phase >= 59 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 57 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 56 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 55 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 54 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 53 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 52 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp"] : phase >= 51 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 50 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 49 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp"] : phase >= 47 ? ["blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "web/protocol/web-engine.ts"] : ["web/app/src/app/App.tsx", "web/protocol/web-engine-capabilities.ts"], 3: ["web/protocol/web-engine-capabilities.ts", "web/app/src/workers/web-engine.worker.ts", "web/app/src/vendor/blender/web_engine.wasm"] };
const markers = { 1: "BUILD_CAPABILITY_FAMILY_IMPLEMENTATION_INDEX", 2: phase >= 60 ? "web_engine_blend_main_set_scene_simplify_settings" : phase >= 59 ? "web_engine_blend_main_set_scene_border_settings" : phase >= 58 ? "web_engine_blend_main_set_scene_collection_settings" : phase >= 57 ? "web_engine_blend_main_set_scene_view_layer_settings" : phase >= 56 ? "web_engine_blend_main_set_scene_bindings" : phase >= 55 ? "web_engine_blend_main_set_scene_pipeline_settings" : phase >= 54 ? "web_engine_blend_main_set_scene_timeline_settings" : phase >= 53 ? "web_engine_blend_main_set_scene_unit_settings" : phase >= 52 ? "web_engine_blend_main_set_scene_audio_settings" : phase >= 51 ? "web_engine_blend_main_set_scene_render_settings" : phase >= 50 ? "web_engine_blend_main_set_scene_properties" : phase >= 49 ? "web_engine_blend_main_set_physics_simulation" : phase >= 47 ? "web_engine_blend_main_set_geometry_node_graph" : "capability-family-workbench", 3: "WEB_ENGINE_COMMAND_CAPABILITIES" }; const markers = { 1: "BUILD_CAPABILITY_FAMILY_IMPLEMENTATION_INDEX", 2: phase >= 61 ? "web_engine_blend_main_set_scene_color_management" : phase >= 60 ? "web_engine_blend_main_set_scene_simplify_settings" : phase >= 59 ? "web_engine_blend_main_set_scene_border_settings" : phase >= 58 ? "web_engine_blend_main_set_scene_collection_settings" : phase >= 57 ? "web_engine_blend_main_set_scene_view_layer_settings" : phase >= 56 ? "web_engine_blend_main_set_scene_bindings" : phase >= 55 ? "web_engine_blend_main_set_scene_pipeline_settings" : phase >= 54 ? "web_engine_blend_main_set_scene_timeline_settings" : phase >= 53 ? "web_engine_blend_main_set_scene_unit_settings" : phase >= 52 ? "web_engine_blend_main_set_scene_audio_settings" : phase >= 51 ? "web_engine_blend_main_set_scene_render_settings" : phase >= 50 ? "web_engine_blend_main_set_scene_properties" : phase >= 49 ? "web_engine_blend_main_set_physics_simulation" : phase >= 47 ? "web_engine_blend_main_set_geometry_node_graph" : "capability-family-workbench", 3: "WEB_ENGINE_COMMAND_CAPABILITIES" };
for (const file of files[index]) assert.ok(fs.existsSync(abs(file)), file); for (const file of files[index]) assert.ok(fs.existsSync(abs(file)), file);
assert.match(read(files[index][0]), new RegExp(markers[index])); assert.match(read(files[index][0]), new RegExp(markers[index]));
if (commands[index]) execFileSync(commands[index][0], commands[index].slice(1), { cwd: root, stdio: "inherit" }); if (commands[index]) execFileSync(commands[index][0], commands[index].slice(1), { cwd: root, stdio: "inherit" });
const nextIndex = index + 1; const nextIndex = index + 1;
const nextTask = nextIndex <= 3 ? `WBV2-P${phase}-${String(nextIndex).padStart(3, "0")}` : `WBV2-P${phase + 1}-000`; const nextTask = nextIndex <= 3 ? `WBV2-P${phase}-${String(nextIndex).padStart(3, "0")}` : `WBV2-P${phase + 1}-000`;
const family = index === 1 ? "INVENTORY.CAPABILITY_BATCH_INDEX" : index === 2 && phase >= 60 ? "CORE_SCENE_GRAPH.SIMPLIFY_SETTINGS" : index === 2 && phase >= 59 ? "CORE_SCENE_GRAPH.BORDER_SETTINGS" : index === 2 && phase >= 58 ? "CORE_SCENE_GRAPH.COLLECTION_SETTINGS" : index === 2 && phase >= 57 ? "CORE_SCENE_GRAPH.VIEW_LAYER_SETTINGS" : index === 2 && phase >= 56 ? "CORE_SCENE_GRAPH.BINDINGS" : index === 2 && phase >= 55 ? "CORE_SCENE_GRAPH.PIPELINE_SETTINGS" : index === 2 && phase >= 54 ? "CORE_SCENE_GRAPH.TIMELINE_SETTINGS" : index === 2 && phase >= 53 ? "CORE_SCENE_GRAPH.UNIT_SETTINGS" : index === 2 && phase >= 52 ? "CORE_SCENE_GRAPH.AUDIO_SETTINGS" : index === 2 && phase >= 51 ? "CORE_SCENE_GRAPH.RENDER_SETTINGS" : index === 2 && phase >= 50 ? "CORE_SCENE_GRAPH.SCENE_PROPERTIES" : index === 2 && phase >= 49 ? "SIMULATION.NATIVE_MANIFEST_BINDING" : index === 2 && phase >= 47 ? "GEOMETRY_NODES.NATIVE_MATERIALIZATION" : index === 2 ? "WORKFLOW.CAPABILITY_FAMILY_WORKBENCH" : "IMPLEMENTATION.CAPABILITY_FAMILY_SMOKE"; const family = index === 1 ? "INVENTORY.CAPABILITY_BATCH_INDEX" : index === 2 && phase >= 61 ? "CORE_SCENE_GRAPH.COLOR_MANAGEMENT" : index === 2 && phase >= 60 ? "CORE_SCENE_GRAPH.SIMPLIFY_SETTINGS" : index === 2 && phase >= 59 ? "CORE_SCENE_GRAPH.BORDER_SETTINGS" : index === 2 && phase >= 58 ? "CORE_SCENE_GRAPH.COLLECTION_SETTINGS" : index === 2 && phase >= 57 ? "CORE_SCENE_GRAPH.VIEW_LAYER_SETTINGS" : index === 2 && phase >= 56 ? "CORE_SCENE_GRAPH.BINDINGS" : index === 2 && phase >= 55 ? "CORE_SCENE_GRAPH.PIPELINE_SETTINGS" : index === 2 && phase >= 54 ? "CORE_SCENE_GRAPH.TIMELINE_SETTINGS" : index === 2 && phase >= 53 ? "CORE_SCENE_GRAPH.UNIT_SETTINGS" : index === 2 && phase >= 52 ? "CORE_SCENE_GRAPH.AUDIO_SETTINGS" : index === 2 && phase >= 51 ? "CORE_SCENE_GRAPH.RENDER_SETTINGS" : index === 2 && phase >= 50 ? "CORE_SCENE_GRAPH.SCENE_PROPERTIES" : index === 2 && phase >= 49 ? "SIMULATION.NATIVE_MANIFEST_BINDING" : index === 2 && phase >= 47 ? "GEOMETRY_NODES.NATIVE_MATERIALIZATION" : index === 2 ? "WORKFLOW.CAPABILITY_FAMILY_WORKBENCH" : "IMPLEMENTATION.CAPABILITY_FAMILY_SMOKE";
const out = `tests/golden/${task}`; const out = `tests/golden/${task}`;
const reportPath = `${out}/implementation-report.json`; const reportPath = `${out}/implementation-report.json`;
const statusPath = `docs/status/${task}.md`; const statusPath = `docs/status/${task}.md`;

Binary file not shown.

View File

@@ -940,6 +940,7 @@ function Properties({ snapshot, selectedFaceIndices, selectedVertexIndices, grea
{activeLight ? <div className="property-section" data-testid="light-workbench"><h3>Light</h3><output>{activeLight.energy.toFixed(1)} energy</output><button type="button" onClick={() => onCommand(animationRenderCommands.setLightProperties(activeLight.id, { energy: Math.min(1e9, activeLight.energy + 10) }))}>增加能量</button><button type="button" onClick={() => onCommand(animationRenderCommands.setLightProperties(activeLight.id, { castsShadow: !(activeLight.castsShadow ?? true) }))}>切换阴影</button></div> : null} {activeLight ? <div className="property-section" data-testid="light-workbench"><h3>Light</h3><output>{activeLight.energy.toFixed(1)} energy</output><button type="button" onClick={() => onCommand(animationRenderCommands.setLightProperties(activeLight.id, { energy: Math.min(1e9, activeLight.energy + 10) }))}>增加能量</button><button type="button" onClick={() => onCommand(animationRenderCommands.setLightProperties(activeLight.id, { castsShadow: !(activeLight.castsShadow ?? true) }))}>切换阴影</button></div> : null}
{activeWorld ? <div className="property-section" data-testid="world-workbench"><h3>World</h3><output>Exposure {activeWorld.exposure.toFixed(2)}</output><button type="button" onClick={() => onCommand(animationRenderCommands.setWorldProperties(activeWorld.id, { exposure: Math.max(-20, Math.min(20, activeWorld.exposure + 0.5)) }))}>增加曝光</button></div> : null} {activeWorld ? <div className="property-section" data-testid="world-workbench"><h3>World</h3><output>Exposure {activeWorld.exposure.toFixed(2)}</output><button type="button" onClick={() => onCommand(animationRenderCommands.setWorldProperties(activeWorld.id, { exposure: Math.max(-20, Math.min(20, activeWorld.exposure + 0.5)) }))}>增加曝光</button></div> : null}
{activeScene ? <div className="property-section" data-testid="scene-properties-workbench"><h3>Scene Render</h3><output>{activeScene.name} · {activeScene.renderEngine ?? "UNKNOWN"}</output><output>{activeScene.colorManagement ? `${activeScene.colorManagement.viewTransform} · ${activeScene.colorManagement.look} · Exposure ${activeScene.colorManagement.exposure.toFixed(2)} · Gamma ${activeScene.colorManagement.gamma.toFixed(2)}` : "Color management unavailable"}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneProperties(activeScene.id, { exposure: Math.max(-1000, Math.min(1000, (activeScene.colorManagement?.exposure ?? 0) + 0.5)) }))}>增加曝光</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneProperties(activeScene.id, { gamma: Math.max(0, Math.min(1000, (activeScene.colorManagement?.gamma ?? 1) + 0.1)) }))}>增加 Gamma</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneProperties(activeScene.id, { viewTransform: activeScene.colorManagement?.viewTransform === "AgX" ? "Standard" : "AgX" }))}>切换 View Transform</button></div></div> : null} {activeScene ? <div className="property-section" data-testid="scene-properties-workbench"><h3>Scene Render</h3><output>{activeScene.name} · {activeScene.renderEngine ?? "UNKNOWN"}</output><output>{activeScene.colorManagement ? `${activeScene.colorManagement.viewTransform} · ${activeScene.colorManagement.look} · Exposure ${activeScene.colorManagement.exposure.toFixed(2)} · Gamma ${activeScene.colorManagement.gamma.toFixed(2)}` : "Color management unavailable"}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneProperties(activeScene.id, { exposure: Math.max(-1000, Math.min(1000, (activeScene.colorManagement?.exposure ?? 0) + 0.5)) }))}>增加曝光</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneProperties(activeScene.id, { gamma: Math.max(0, Math.min(1000, (activeScene.colorManagement?.gamma ?? 1) + 0.1)) }))}>增加 Gamma</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneProperties(activeScene.id, { viewTransform: activeScene.colorManagement?.viewTransform === "AgX" ? "Standard" : "AgX" }))}>切换 View Transform</button></div></div> : null}
{activeScene?.colorManagement ? <div className="property-section" data-testid="scene-color-management-workbench"><h3>Color Management</h3><output>{activeScene.colorManagement.displayDevice} · {activeScene.colorManagement.temperature?.toFixed(0) ?? "-"} K · Tint {activeScene.colorManagement.tint?.toFixed(2) ?? "-"}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneColorManagement(activeScene.id, { temperature: Math.min(20000, (activeScene.colorManagement!.temperature ?? 6500) + 250) }))}>升高色温</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneColorManagement(activeScene.id, { tint: Math.max(-100, Math.min(100, (activeScene.colorManagement!.tint ?? 0) + 1)) }))}>调整 Tint</button></div></div> : null}
{activeScene?.renderSettings ? <div className="property-section" data-testid="scene-render-settings-workbench"><h3>Render Output</h3><output>{activeScene.renderSettings.resolutionX} × {activeScene.renderSettings.resolutionY} @ {activeScene.renderSettings.resolutionPercentage}%</output><output>Frames {activeScene.renderSettings.frameStart} - {activeScene.renderSettings.frameEnd} · {activeScene.renderSettings.outputPath}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneRenderSettings(activeScene.id, { resolutionX: Math.min(65536, activeScene.renderSettings!.resolutionX + 64), resolutionY: Math.min(65536, activeScene.renderSettings!.resolutionY + 64) }))}>增加分辨率</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneRenderSettings(activeScene.id, { resolutionPercentage: Math.min(1000, activeScene.renderSettings!.resolutionPercentage + 10) }))}>增加百分比</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneRenderSettings(activeScene.id, { frameEnd: Math.min(1000000, activeScene.renderSettings!.frameEnd + 1) }))}>延长帧范围</button></div></div> : null} {activeScene?.renderSettings ? <div className="property-section" data-testid="scene-render-settings-workbench"><h3>Render Output</h3><output>{activeScene.renderSettings.resolutionX} × {activeScene.renderSettings.resolutionY} @ {activeScene.renderSettings.resolutionPercentage}%</output><output>Frames {activeScene.renderSettings.frameStart} - {activeScene.renderSettings.frameEnd} · {activeScene.renderSettings.outputPath}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneRenderSettings(activeScene.id, { resolutionX: Math.min(65536, activeScene.renderSettings!.resolutionX + 64), resolutionY: Math.min(65536, activeScene.renderSettings!.resolutionY + 64) }))}>增加分辨率</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneRenderSettings(activeScene.id, { resolutionPercentage: Math.min(1000, activeScene.renderSettings!.resolutionPercentage + 10) }))}>增加百分比</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneRenderSettings(activeScene.id, { frameEnd: Math.min(1000000, activeScene.renderSettings!.frameEnd + 1) }))}>延长帧范围</button></div></div> : null}
{activeScene?.audioSettings ? <div className="property-section" data-testid="scene-audio-settings-workbench"><h3>Scene Audio</h3><output>Volume {activeScene.audioSettings.volume.toFixed(2)} · Speed {activeScene.audioSettings.speedOfSound.toFixed(1)} · Doppler {activeScene.audioSettings.dopplerFactor.toFixed(2)}</output><output>Distance model {activeScene.audioSettings.distanceModel} · {activeScene.audioSettings.muted ? "Muted" : "Audible"} · {activeScene.audioSettings.sync ? "Synced" : "Free"}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneAudioSettings(activeScene.id, { volume: Math.min(10, activeScene.audioSettings!.volume + 0.1) }))}>增加音量</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneAudioSettings(activeScene.id, { muted: !activeScene.audioSettings!.muted }))}>{activeScene.audioSettings.muted ? "取消静音" : "静音"}</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneAudioSettings(activeScene.id, { sync: !activeScene.audioSettings!.sync }))}>切换同步</button></div></div> : null} {activeScene?.audioSettings ? <div className="property-section" data-testid="scene-audio-settings-workbench"><h3>Scene Audio</h3><output>Volume {activeScene.audioSettings.volume.toFixed(2)} · Speed {activeScene.audioSettings.speedOfSound.toFixed(1)} · Doppler {activeScene.audioSettings.dopplerFactor.toFixed(2)}</output><output>Distance model {activeScene.audioSettings.distanceModel} · {activeScene.audioSettings.muted ? "Muted" : "Audible"} · {activeScene.audioSettings.sync ? "Synced" : "Free"}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneAudioSettings(activeScene.id, { volume: Math.min(10, activeScene.audioSettings!.volume + 0.1) }))}>增加音量</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneAudioSettings(activeScene.id, { muted: !activeScene.audioSettings!.muted }))}>{activeScene.audioSettings.muted ? "取消静音" : "静音"}</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneAudioSettings(activeScene.id, { sync: !activeScene.audioSettings!.sync }))}>切换同步</button></div></div> : null}
{activeScene?.unitSettings ? <div className="property-section" data-testid="scene-unit-settings-workbench"><h3>Scene Units</h3><output>System {activeScene.unitSettings.system} · Scale {activeScene.unitSettings.scaleLength.toFixed(4)} · Rotation {activeScene.unitSettings.rotationSystem}</output><output>Length {activeScene.unitSettings.lengthUnit} · Mass {activeScene.unitSettings.massUnit} · Time {activeScene.unitSettings.timeUnit}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneUnitSettings(activeScene.id, { system: activeScene.unitSettings!.system === 1 ? 2 : 1 }))}>切换单位系统</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneUnitSettings(activeScene.id, { scaleLength: Math.min(1000000, Math.max(0.000001, activeScene.unitSettings!.scaleLength || 1) * 1.1) }))}>调整单位缩放</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneUnitSettings(activeScene.id, { rotationSystem: activeScene.unitSettings!.rotationSystem === 2 ? 0 : 2 }))}>切换旋转单位</button></div></div> : null} {activeScene?.unitSettings ? <div className="property-section" data-testid="scene-unit-settings-workbench"><h3>Scene Units</h3><output>System {activeScene.unitSettings.system} · Scale {activeScene.unitSettings.scaleLength.toFixed(4)} · Rotation {activeScene.unitSettings.rotationSystem}</output><output>Length {activeScene.unitSettings.lengthUnit} · Mass {activeScene.unitSettings.massUnit} · Time {activeScene.unitSettings.timeUnit}</output><div className="property-actions"><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneUnitSettings(activeScene.id, { system: activeScene.unitSettings!.system === 1 ? 2 : 1 }))}>切换单位系统</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneUnitSettings(activeScene.id, { scaleLength: Math.min(1000000, Math.max(0.000001, activeScene.unitSettings!.scaleLength || 1) * 1.1) }))}>调整单位缩放</button><button type="button" onClick={() => onCommand(animationRenderCommands.setSceneUnitSettings(activeScene.id, { rotationSystem: activeScene.unitSettings!.rotationSystem === 2 ? 0 : 2 }))}>切换旋转单位</button></div></div> : null}

Binary file not shown.

View File

@@ -713,6 +713,15 @@ function assertFutureCapability(payload: Extract<WebEngineRequest["command"], {
for (const field of ["particlesViewport", "particlesRender", "volumes"] as const) if (properties[field] !== undefined && !boundedNumber(properties[field], 0, 1000)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is outside the simplify range`); for (const field of ["particlesViewport", "particlesRender", "volumes"] as const) if (properties[field] !== undefined && !boundedNumber(properties[field], 0, 1000)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is outside the simplify range`);
return; return;
} }
case "setSceneColorManagement": {
const scene = currentSnapshot?.scenes.find((candidate) => candidate.id === payload.dataId);
const properties = payload.properties;
if (!scene || !validPropertyKeys(properties, ["displayDevice", "temperature", "tint"])) throw report("RENDER_PROPERTY_INVALID", "Scene color management target or properties are invalid");
if (properties.displayDevice !== undefined && (typeof properties.displayDevice !== "string" || properties.displayDevice.length === 0 || new TextEncoder().encode(properties.displayDevice).byteLength > 63)) throw report("RENDER_PROPERTY_INVALID", "Scene displayDevice is not a bounded string");
if (properties.temperature !== undefined && !boundedNumber(properties.temperature, 1000, 20000)) throw report("RENDER_PROPERTY_INVALID", "Scene temperature is outside the color-management range");
if (properties.tint !== undefined && !boundedNumber(properties.tint, -100, 100)) throw report("RENDER_PROPERTY_INVALID", "Scene tint is outside the color-management range");
return;
}
case "setGeometryNodeGraph": { case "setGeometryNodeGraph": {
const snapshot = currentSnapshot; const snapshot = currentSnapshot;
const availableResourceIds = new Set([ const availableResourceIds = new Set([

View File

@@ -62,4 +62,7 @@ export const animationRenderCommands = Object.freeze({
setSceneSimplifySettings(dataId: string, properties: AnimationCommand<"setSceneSimplifySettings">["properties"]): AnimationCommand<"setSceneSimplifySettings"> { setSceneSimplifySettings(dataId: string, properties: AnimationCommand<"setSceneSimplifySettings">["properties"]): AnimationCommand<"setSceneSimplifySettings"> {
return { type: "setSceneSimplifySettings", dataId, properties: { ...properties } }; return { type: "setSceneSimplifySettings", dataId, properties: { ...properties } };
}, },
setSceneColorManagement(dataId: string, properties: AnimationCommand<"setSceneColorManagement">["properties"]): AnimationCommand<"setSceneColorManagement"> {
return { type: "setSceneColorManagement", dataId, properties: { ...properties } };
},
} satisfies Record<string, (...args: never[]) => WebEngineEditCommand>); } satisfies Record<string, (...args: never[]) => WebEngineEditCommand>);

View File

@@ -90,6 +90,7 @@ export const WEB_ENGINE_COMMAND_CAPABILITIES = {
setSceneCollectionSettings: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" }, setSceneCollectionSettings: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },
setSceneBorderSettings: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" }, setSceneBorderSettings: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },
setSceneSimplifySettings: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" }, setSceneSimplifySettings: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },
setSceneColorManagement: { family: "CORE_SCENE_GRAPH", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },
setMetaballElements: { family: "GEOMETRY", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" }, setMetaballElements: { family: "GEOMETRY", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },
sculptStroke: { family: "SCULPT", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" }, sculptStroke: { family: "SCULPT", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },
setSculptMeshAttributes: { family: "SCULPT", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" }, setSculptMeshAttributes: { family: "SCULPT", route: "MAIN_AUTHORITATIVE", implementation: "SOURCE_BACKED" },

View File

@@ -154,6 +154,7 @@ export type WebEngineEditCommand =
| { type: "setSceneCollectionSettings"; dataId: string; layerName: string; collectionId: string; properties: { exclude?: boolean; holdout?: boolean; indirectOnly?: boolean; hide?: boolean } } | { type: "setSceneCollectionSettings"; dataId: string; layerName: string; collectionId: string; properties: { exclude?: boolean; holdout?: boolean; indirectOnly?: boolean; hide?: boolean } }
| { type: "setSceneBorderSettings"; dataId: string; properties: { enabled?: boolean; minX?: number; maxX?: number; minY?: number; maxY?: number } } | { type: "setSceneBorderSettings"; dataId: string; properties: { enabled?: boolean; minX?: number; maxX?: number; minY?: number; maxY?: number } }
| { type: "setSceneSimplifySettings"; dataId: string; properties: { subsurfViewport?: number; subsurfRender?: number; particlesViewport?: number; particlesRender?: number; volumes?: number } } | { type: "setSceneSimplifySettings"; dataId: string; properties: { subsurfViewport?: number; subsurfRender?: number; particlesViewport?: number; particlesRender?: number; volumes?: number } }
| { type: "setSceneColorManagement"; dataId: string; properties: { displayDevice?: string; temperature?: number; tint?: number } }
| { type: "setMetaballElements"; dataId: string; elements: Array<{ type: number; position: [number, number, number]; radius: number; scale: [number, number, number] }> } | { type: "setMetaballElements"; dataId: string; elements: Array<{ type: number; position: [number, number, number]; radius: number; scale: [number, number, number] }> }
| { type: "sculptStroke"; stroke: SculptStrokeIR } | { type: "sculptStroke"; stroke: SculptStrokeIR }
| { type: "setSculptMeshAttributes"; attributes: SculptMeshAttributesIR } | { type: "setSculptMeshAttributes"; attributes: SculptMeshAttributesIR }

View File

@@ -4,7 +4,7 @@ export const WORKBENCH_COMMAND_GROUPS = Object.freeze({
OBJECT: ["createPrimitive", "duplicateObject", "deleteObject", "setObjectTransform", "setParent", "createCollection", "moveObjectToCollection", "renameId", "applyObjectTransform", "setObjectOrigin"], OBJECT: ["createPrimitive", "duplicateObject", "deleteObject", "setObjectTransform", "setParent", "createCollection", "moveObjectToCollection", "renameId", "applyObjectTransform", "setObjectOrigin"],
MESH: ["meshEdit", "translateMeshVertices", "createUVMap", "setActiveUVMap", "unwrapUV", "setVertexColors", "setVertexWeights"], MESH: ["meshEdit", "translateMeshVertices", "createUVMap", "setActiveUVMap", "unwrapUV", "setVertexColors", "setVertexWeights"],
ANIMATION: ["setFrame", "insertObjectKeyframe", "deleteObjectKeyframe", "setFCurveInterpolation", "setConstraint", "setNLAStack"], ANIMATION: ["setFrame", "insertObjectKeyframe", "deleteObjectKeyframe", "setFCurveInterpolation", "setConstraint", "setNLAStack"],
RENDER: ["setCameraProperties", "setLightProperties", "setWorldProperties", "setSceneProperties", "setSceneRenderSettings", "setSceneAudioSettings", "setSceneUnitSettings", "setSceneTimelineSettings", "setScenePipelineSettings", "setSceneBindings", "setSceneViewLayerSettings", "setSceneCollectionSettings", "setSceneBorderSettings", "setSceneSimplifySettings"], RENDER: ["setCameraProperties", "setLightProperties", "setWorldProperties", "setSceneProperties", "setSceneRenderSettings", "setSceneAudioSettings", "setSceneUnitSettings", "setSceneTimelineSettings", "setScenePipelineSettings", "setSceneBindings", "setSceneViewLayerSettings", "setSceneCollectionSettings", "setSceneBorderSettings", "setSceneSimplifySettings", "setSceneColorManagement"],
IO: ["importImage", "importVFont", "setMaterialImageNode"], IO: ["importImage", "importVFont", "setMaterialImageNode"],
} as const satisfies Record<string, readonly WebEngineCommandType[]>); } as const satisfies Record<string, readonly WebEngineCommandType[]>);