Govern task context and advance execution pointer
This commit is contained in:
14
AGENTS.md
Normal file
14
AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# 执行上下文规则
|
||||
|
||||
本仓库的任务执行必须使用最小上下文。不要把完整路线图、项目状态、parity ledger 或全部 `docs/status/` 日志作为默认上下文。
|
||||
|
||||
领取任务时只做以下操作:
|
||||
|
||||
1. 阅读 `docs/EXECUTION_QUEUE.md`。
|
||||
2. 运行 `node tools/web/print-task-context.mjs`;它只会输出当前任务、parent manifest、parent status 和聚焦命令。
|
||||
3. 只打开输出中列出的任务卡、生产入口、测试入口和最小 fixture。
|
||||
4. 开始前运行 `node tools/web/check-task-context.mjs`;预算或 parent `nextTask` 不一致时停止并修正证据,不要手工推进队列。
|
||||
|
||||
默认上下文预算:队列 4 KiB、任务卡 8 KiB、parent manifest 24 KiB、parent status 6 KiB,合计约 3,500 tokens。历史和长期文档只能按任务卡列出的具体小节追加读取。
|
||||
|
||||
完成任务时运行 `node tools/web/check-task-context.mjs --task <task-id> --write`,并仅提交任务报告、manifest、status 和聚焦实现/测试变更。下一任务只认新 manifest 的 `nextTask`。
|
||||
@@ -32,7 +32,8 @@ npm --prefix web run build
|
||||
npm --prefix web run test:browser
|
||||
```
|
||||
|
||||
See `docs/EXECUTION_QUEUE.md` for the current task order and `docs/README.md` for the document map,
|
||||
See `docs/EXECUTION_QUEUE.md` for the current task pointer, `docs/CONTEXT_BUDGET.md` for the
|
||||
small-context execution rules, and `docs/README.md` for the document map,
|
||||
`docs/PROJECT_STATUS_AND_NEXT_WORK.md` for the implemented scope, and
|
||||
`docs/BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md` for the normative M12-M23
|
||||
full-parity execution plan. The domain overview and coverage cross-check are in
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Web 版 Blender 连续执行计划
|
||||
|
||||
> 历史迁移计划:本文不参与当前任务领取。当前任务只认 `docs/EXECUTION_QUEUE.md`、任务卡和 parent manifest。
|
||||
|
||||
## 1. 文档定位
|
||||
|
||||
本计划用于把 `blender-5.2.0` 逐步变成一个浏览器中的 Blender 数据编辑器。它不是“把桌面窗口搬进 Canvas”的计划,而是以 Blender 数据和建模行为为基准,以 React 为应用界面、Three.js 为唯一浏览器渲染器、WebAssembly 为 Blender 计算核心。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Blender Web 化技术路线(React + Three.js + WebAssembly + OPFS/IndexedDB)
|
||||
|
||||
> 历史技术背景:本文不参与当前任务领取。当前任务只认 `docs/EXECUTION_QUEUE.md` 和最小上下文工具。
|
||||
|
||||
> **存储决策(2026-08):** SQLite WASM 不是项目首期必需依赖,已从当前实现和发布资源中移除。小型元数据使用 Worker 内 IndexedDB,大型二进制使用 OPFS;未来只有在查询/事务需求超过 IndexedDB 时,才单独评估 SQLite WASM。
|
||||
|
||||
## 1. 结论先行
|
||||
|
||||
@@ -843,6 +843,16 @@ bool refresh_scene_from_main(EngineState &engine,
|
||||
return false;
|
||||
}
|
||||
snapshot["physicsSimulation"] = json::parse(physics_json);
|
||||
std::string particle_settings_json;
|
||||
if (!web_engine_blend_main_particle_settings_json(
|
||||
engine.authoritative_main, particle_settings_json, error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const json particle_settings = json::parse(particle_settings_json)["settings"];
|
||||
if (!particle_settings.empty() || snapshot.value("particleSettings", json::array()).empty()) {
|
||||
snapshot["particleSettings"] = particle_settings;
|
||||
}
|
||||
if (!active_object_id.empty()) snapshot["activeObjectId"] = active_object_id;
|
||||
engine.blend_bytes.assign(reinterpret_cast<const char *>(bytes.data()), bytes.size());
|
||||
engine.packed_assets = parsed.packed_assets;
|
||||
@@ -860,7 +870,7 @@ const char *empty_scene_snapshot_json()
|
||||
"\"source\":{\"kind\":\"blend\"},"
|
||||
"\"coordinateSystem\":{\"upAxis\":\"Z\",\"forwardAxis\":\"-Y\",\"handedness\":\"RIGHT\",\"unitSystem\":0,\"unitScale\":1},"
|
||||
"\"nodes\":[],\"meshes\":[],\"materials\":[],\"cameras\":[],\"lights\":[],\"worlds\":[],\"images\":[],\"animations\":[],"
|
||||
"\"collections\":[],\"scenes\":[],\"activeObjectId\":null,"
|
||||
"\"collections\":[],\"scenes\":[],\"particleSettings\":[],\"sounds\":[],\"activeObjectId\":null,"
|
||||
"\"frame\":{\"current\":1,\"start\":1,\"end\":250}}";
|
||||
}
|
||||
|
||||
@@ -1157,6 +1167,18 @@ EMSCRIPTEN_KEEPALIVE int web_engine_open_blend(const int handle,
|
||||
return last_error_code;
|
||||
}
|
||||
opened_snapshot["physicsSimulation"] = json::parse(physics_json);
|
||||
std::string particle_settings_json;
|
||||
if (!web_engine_blend_main_particle_settings_json(
|
||||
authoritative_main, particle_settings_json, main_error))
|
||||
{
|
||||
web_engine_blend_main_free(authoritative_main);
|
||||
set_error(WEB_ENGINE_BLEND_READ_FAILED, main_error.c_str());
|
||||
return last_error_code;
|
||||
}
|
||||
const json particle_settings = json::parse(particle_settings_json)["settings"];
|
||||
if (!particle_settings.empty() || opened_snapshot.value("particleSettings", json::array()).empty()) {
|
||||
opened_snapshot["particleSettings"] = particle_settings;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &exception) {
|
||||
web_engine_blend_main_free(authoritative_main);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "DNA_genfile.h"
|
||||
#include "DNA_curve_enums.h"
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_mask_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
@@ -48,6 +49,7 @@ using namespace blender;
|
||||
|
||||
constexpr uint64_t MAX_BLEND_BLOCK_BYTES = UINT64_C(1024) * 1024 * 1024;
|
||||
constexpr size_t MAX_NON_MESH_POINTS = 1000000;
|
||||
constexpr size_t MAX_LATTICE_POINTS = 64 * 64 * 64;
|
||||
constexpr size_t MAX_SCRIPT_SOURCE_BYTES = 1024 * 1024;
|
||||
|
||||
uint32_t rotate_right(const uint32_t value, const uint32_t bits)
|
||||
@@ -539,6 +541,13 @@ std::string id_prefix(const std::string &type_name)
|
||||
if (type_name == "Library") return "library";
|
||||
if (type_name == "WorkSpace") return "workspace";
|
||||
if (type_name == "bScreen") return "screen";
|
||||
if (type_name == "Brush") return "brush";
|
||||
if (type_name == "FreestyleLineStyle") return "line-style";
|
||||
if (type_name == "Lattice") return "lattice";
|
||||
if (type_name == "ParticleSettings") return "particle-settings";
|
||||
if (type_name == "bSound") return "sound";
|
||||
if (type_name == "Speaker") return "speaker";
|
||||
if (type_name == "Tex") return "texture";
|
||||
return "datablock";
|
||||
}
|
||||
|
||||
@@ -552,7 +561,9 @@ bool is_exported_id_type(const std::string &type_name)
|
||||
type_name == "MetaBall" || type_name == "PointCloud" || type_name == "Curves" ||
|
||||
type_name == "Volume" || type_name == "GreasePencil" || type_name == "Text" ||
|
||||
type_name == "VFont" || type_name == "Mask" || type_name == "Library" ||
|
||||
type_name == "WorkSpace" || type_name == "bScreen";
|
||||
type_name == "WorkSpace" || type_name == "bScreen" || type_name == "Brush" ||
|
||||
type_name == "FreestyleLineStyle" || type_name == "Lattice" ||
|
||||
type_name == "ParticleSettings" || type_name == "bSound" || type_name == "Speaker" || type_name == "Tex";
|
||||
}
|
||||
|
||||
std::string unique_id(const std::string &prefix,
|
||||
@@ -613,6 +624,17 @@ std::string object_type_name(const int64_t type)
|
||||
}
|
||||
}
|
||||
|
||||
const char *lattice_interpolation_name(const int64_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case KEY_LINEAR: return "KEY_LINEAR";
|
||||
case KEY_CARDINAL: return "KEY_CARDINAL";
|
||||
case KEY_BSPLINE: return "KEY_BSPLINE";
|
||||
case KEY_CATMULL_ROM: return "KEY_CATMULL_ROM";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
std::array<float, 16> trs_matrix(const std::vector<float> &location,
|
||||
const std::vector<float> &rotation,
|
||||
const std::vector<float> &scale)
|
||||
@@ -1452,8 +1474,8 @@ std::string modifier_type_name(const int64_t type)
|
||||
"GREASE_PENCIL_OPACITY", "GREASE_PENCIL_SUBDIV", "GREASE_PENCIL_COLOR", "GREASE_PENCIL_TINT",
|
||||
"GREASE_PENCIL_SMOOTH", "GREASE_PENCIL_OFFSET", "GREASE_PENCIL_NOISE", "GREASE_PENCIL_MIRROR",
|
||||
"GREASE_PENCIL_THICKNESS", "GREASE_PENCIL_LATTICE", "GREASE_PENCIL_DASH", "GREASE_PENCIL_MULTIPLY",
|
||||
"GREASE_PENCIL_LENGTH", "GREASE_PENCIL_WEIGHT_ANGLE", "GREASE_PENCIL_ARRAY",
|
||||
"GREASE_PENCIL_WEIGHT_PROXIMITY", "GREASE_PENCIL_HOOK", "GREASE_PENCIL_LINEART",
|
||||
"GREASE_PENCIL_LENGTH", "GREASE_PENCIL_VERTEX_WEIGHT_ANGLE", "GREASE_PENCIL_ARRAY",
|
||||
"GREASE_PENCIL_VERTEX_WEIGHT_PROXIMITY", "GREASE_PENCIL_HOOK", "GREASE_PENCIL_LINEART",
|
||||
"GREASE_PENCIL_ARMATURE", "GREASE_PENCIL_TIME", "GREASE_PENCIL_ENVELOPE",
|
||||
"GREASE_PENCIL_OUTLINE", "GREASE_PENCIL_SHRINKWRAP", "GREASE_PENCIL_BUILD",
|
||||
"GREASE_PENCIL_SIMPLIFY", "GREASE_PENCIL_TEXTURE"};
|
||||
@@ -1501,7 +1523,8 @@ json modifier_parameters(const ParsedBlend &blend,
|
||||
case 4:
|
||||
parameters["start"] = read_float(*blend.sdna, modifier, "start").value_or(1.0f);
|
||||
parameters["length"] = read_float(*blend.sdna, modifier, "length").value_or(100.0f);
|
||||
parameters["randomize"] = read_float(*blend.sdna, modifier, "randomize").value_or(0.0f);
|
||||
parameters["randomize"] = read_integer(*blend.sdna, modifier, "randomize").value_or(0);
|
||||
parameters["seed"] = read_integer(*blend.sdna, modifier, "seed").value_or(0);
|
||||
break;
|
||||
case 5:
|
||||
parameters["flag"] = read_integer(*blend.sdna, modifier, "flag").value_or(
|
||||
@@ -3124,6 +3147,15 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
json lights = json::array();
|
||||
json worlds = json::array();
|
||||
json images = json::array();
|
||||
json brushes = json::array();
|
||||
json line_styles = json::array();
|
||||
json lattices = json::array();
|
||||
json particle_settings = json::array();
|
||||
json sounds = json::array();
|
||||
json speakers = json::array();
|
||||
json texts = json::array();
|
||||
json textures = json::array();
|
||||
json workspace_resources = json::array();
|
||||
json non_mesh_data = json::array();
|
||||
json vfonts = json::array();
|
||||
json libraries = json::array();
|
||||
@@ -3289,10 +3321,12 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
if (data_pointer) {
|
||||
const auto data_id = ids_by_pointer.find(*data_pointer);
|
||||
node["dataId"] = data_id != ids_by_pointer.end() ? json(data_id->second) : json(nullptr);
|
||||
const json object_modifier_stack = modifier_stack_from_object(blend, element, record.id, ids_by_pointer);
|
||||
if (!object_modifier_stack.empty()) node["modifierStack"] = object_modifier_stack;
|
||||
if (data_id != ids_by_pointer.end()) {
|
||||
if (const std::optional<ElementRef> data = element_for_pointer(blend, *data_pointer)) {
|
||||
if (data->type_name == "Mesh") {
|
||||
const json stack = modifier_stack_from_object(blend, element, record.id, ids_by_pointer);
|
||||
const json stack = object_modifier_stack;
|
||||
if (!stack.empty()) modifier_stacks_by_mesh_id.emplace(data_id->second, stack);
|
||||
}
|
||||
}
|
||||
@@ -3527,6 +3561,155 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
if (!warnings.empty()) material["warnings"] = warnings;
|
||||
materials.push_back(std::move(material));
|
||||
}
|
||||
else if (record.type_name == "Brush") {
|
||||
json brush = {
|
||||
{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"size", std::clamp<int64_t>(read_integer(*blend.sdna, element, "size").value_or(0), 0, 100000)},
|
||||
{"alpha", std::clamp<float>(read_float(*blend.sdna, element, "alpha").value_or(1.0f), 0.0f, 1.0f)},
|
||||
{"hardness", std::clamp<float>(read_float(*blend.sdna, element, "hardness").value_or(0.0f), 0.0f, 1.0f)},
|
||||
{"spacing", std::clamp<int64_t>(read_integer(*blend.sdna, element, "spacing").value_or(0), 1, 1000)},
|
||||
{"jitter", std::clamp<float>(read_float(*blend.sdna, element, "jitter").value_or(0.0f), 0.0f, 1.0f)},
|
||||
{"sculptTool", read_integer(*blend.sdna, element, "sculpt_brush_type").value_or(0)},
|
||||
};
|
||||
brushes.push_back(std::move(brush));
|
||||
}
|
||||
else if (record.type_name == "FreestyleLineStyle") {
|
||||
const std::vector<float> color = {read_float(*blend.sdna, element, "r").value_or(0.0f),
|
||||
read_float(*blend.sdna, element, "g").value_or(0.0f),
|
||||
read_float(*blend.sdna, element, "b").value_or(0.0f)};
|
||||
const int64_t flag = read_integer(*blend.sdna, element, "flag").value_or(0);
|
||||
line_styles.push_back({
|
||||
{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"color", float_array_or(color, {0.0f, 0.0f, 0.0f})},
|
||||
{"alpha", std::clamp(read_float(*blend.sdna, element, "alpha").value_or(1.0f), 0.0f, 1.0f)},
|
||||
{"thickness", std::clamp(read_float(*blend.sdna, element, "thickness").value_or(1.0f), 0.0f, 10000.0f)},
|
||||
{"chaining", read_integer(*blend.sdna, element, "chaining").value_or(0)},
|
||||
{"caps", read_integer(*blend.sdna, element, "caps").value_or(0)},
|
||||
{"dashed", (flag & (1 << 2)) != 0},
|
||||
{"modifierCounts", {
|
||||
{"color", linked_list_elements(blend, element, "color_modifiers").size()},
|
||||
{"alpha", linked_list_elements(blend, element, "alpha_modifiers").size()},
|
||||
{"thickness", linked_list_elements(blend, element, "thickness_modifiers").size()},
|
||||
{"geometry", linked_list_elements(blend, element, "geometry_modifiers").size()}}}
|
||||
});
|
||||
}
|
||||
else if (record.type_name == "Lattice") {
|
||||
const int64_t points_u = read_integer(*blend.sdna, element, "pntsu").value_or(0);
|
||||
const int64_t points_v = read_integer(*blend.sdna, element, "pntsv").value_or(0);
|
||||
const int64_t points_w = read_integer(*blend.sdna, element, "pntsw").value_or(0);
|
||||
const bool dimensions_valid = points_u >= 1 && points_u <= 64 &&
|
||||
points_v >= 1 && points_v <= 64 &&
|
||||
points_w >= 1 && points_w <= 64;
|
||||
const size_t point_count = dimensions_valid ?
|
||||
size_t(points_u) * size_t(points_v) * size_t(points_w) :
|
||||
0;
|
||||
json points = json::array();
|
||||
bool points_complete = point_count > 0 && point_count <= MAX_LATTICE_POINTS;
|
||||
if (const std::optional<uint64_t> points_pointer = read_pointer(*blend.sdna, element, "def");
|
||||
points_complete && points_pointer)
|
||||
{
|
||||
for (size_t index = 0; index < point_count; index++) {
|
||||
const std::optional<ElementRef> point = raw_array_element(
|
||||
blend, *points_pointer, "BPoint", index);
|
||||
if (!point) {
|
||||
points_complete = false;
|
||||
break;
|
||||
}
|
||||
const std::vector<float> coordinate = read_float_array(
|
||||
*blend.sdna, *point, "vec", 4);
|
||||
if (coordinate.size() != 4) {
|
||||
points_complete = false;
|
||||
break;
|
||||
}
|
||||
points.push_back({
|
||||
{"coDeform", {coordinate[0], coordinate[1], coordinate[2]}},
|
||||
{"weight", std::clamp(read_float(*blend.sdna, *point, "weight").value_or(0.0f),
|
||||
0.01f,
|
||||
100.0f)},
|
||||
{"selected", (read_integer(*blend.sdna, *point, "f1").value_or(0) & 1) != 0},
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
points_complete = false;
|
||||
}
|
||||
const int64_t flag = read_integer(*blend.sdna, element, "flag").value_or(0);
|
||||
json lattice = {
|
||||
{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"dimensions", {points_u, points_v, points_w}},
|
||||
{"pointCount", point_count},
|
||||
{"interpolation", {
|
||||
lattice_interpolation_name(read_integer(*blend.sdna, element, "typeu").value_or(-1)),
|
||||
lattice_interpolation_name(read_integer(*blend.sdna, element, "typev").value_or(-1)),
|
||||
lattice_interpolation_name(read_integer(*blend.sdna, element, "typew").value_or(-1))}},
|
||||
{"useOutside", (flag & LT_OUTSIDE) != 0},
|
||||
{"activePoint", read_integer(*blend.sdna, element, "actbp").value_or(LT_ACTBP_NONE)},
|
||||
{"vertexGroup", read_string(*blend.sdna, element, "vgroup")},
|
||||
{"status", points_complete ? "AVAILABLE" : "BLOCKED"},
|
||||
};
|
||||
if (points_complete) lattice["points"] = std::move(points);
|
||||
else lattice["errorCode"] = dimensions_valid ? "LATTICE_POINTS_UNREADABLE" :
|
||||
"LATTICE_DIMENSIONS_INVALID";
|
||||
lattices.push_back(std::move(lattice));
|
||||
}
|
||||
else if (record.type_name == "ParticleSettings") {
|
||||
const int64_t particle_type = read_integer(*blend.sdna, element, "type").value_or(0);
|
||||
const int64_t particle_from = read_integer(*blend.sdna, element, "from").value_or(0);
|
||||
const int64_t particle_physics = read_integer(*blend.sdna, element, "phystype").value_or(0);
|
||||
particle_settings.push_back({
|
||||
{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"type", particle_type == 2 ? 1 : 0},
|
||||
{"from", particle_from == 1 ? 0 : particle_from == 0 ? 1 : 2},
|
||||
{"distribution", std::max<int64_t>(0, read_integer(*blend.sdna, element, "distr").value_or(0))},
|
||||
{"physicsType", particle_physics == 1 ? 0 : particle_physics == 2 ? 1 : particle_physics == 3 ? 2 : 3},
|
||||
{"totalParticles", std::max<int64_t>(0, read_integer(*blend.sdna, element, "totpart").value_or(0))},
|
||||
{"start", std::max(0.0f, read_float(*blend.sdna, element, "sta").value_or(0.0f))},
|
||||
{"end", std::max(0.0f, read_float(*blend.sdna, element, "end").value_or(0.0f))},
|
||||
{"lifetime", std::max(0.0f, read_float(*blend.sdna, element, "lifetime").value_or(0.0f))},
|
||||
{"size", std::max(0.0f, read_float(*blend.sdna, element, "size").value_or(0.0f))},
|
||||
{"drawSize", std::max(0.0f, read_float(*blend.sdna, element, "draw_size").value_or(0.0f))},
|
||||
});
|
||||
}
|
||||
else if (record.type_name == "bSound") {
|
||||
const std::string filepath = read_string(*blend.sdna, element, "filepath");
|
||||
const std::optional<uint64_t> packed_pointer = read_pointer(*blend.sdna, element, "packedfile");
|
||||
const std::vector<uint8_t> packed_bytes = packed_pointer ? packed_file_bytes(blend, *packed_pointer) : std::vector<uint8_t>();
|
||||
json sound = {{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"sourcePath", filepath},
|
||||
{"packed", !packed_bytes.empty()},
|
||||
{"volume", std::max(0.0f, read_float(*blend.sdna, element, "volume").value_or(1.0f))},
|
||||
{"pitch", std::max(0.0f, read_float(*blend.sdna, element, "pitch").value_or(1.0f))},
|
||||
{"audioChannels", std::max<int64_t>(0, read_integer(*blend.sdna, element, "audio_channels").value_or(0))},
|
||||
{"sampleRate", std::max<int64_t>(0, read_integer(*blend.sdna, element, "samplerate").value_or(0))}};
|
||||
if (!packed_bytes.empty()) sound["packedByteLength"] = packed_bytes.size();
|
||||
sounds.push_back(std::move(sound));
|
||||
}
|
||||
else if (record.type_name == "Speaker") {
|
||||
json speaker = {
|
||||
{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"volumeMax", std::max(0.0f, read_float(*blend.sdna, element, "volume_max").value_or(1.0f))},
|
||||
{"volumeMin", std::max(0.0f, read_float(*blend.sdna, element, "volume_min").value_or(0.0f))},
|
||||
{"distanceMax", std::max(0.0f, read_float(*blend.sdna, element, "distance_max").value_or(0.0f))},
|
||||
{"distanceReference", std::max(0.0f, read_float(*blend.sdna, element, "distance_reference").value_or(1.0f))},
|
||||
{"attenuation", std::max(0.0f, read_float(*blend.sdna, element, "attenuation").value_or(1.0f))},
|
||||
{"coneAngleOuter", std::clamp(read_float(*blend.sdna, element, "cone_angle_outer").value_or(360.0f), 0.0f, 360.0f)},
|
||||
{"coneAngleInner", std::clamp(read_float(*blend.sdna, element, "cone_angle_inner").value_or(360.0f), 0.0f, 360.0f)},
|
||||
{"coneVolumeOuter", std::clamp(read_float(*blend.sdna, element, "cone_volume_outer").value_or(1.0f), 0.0f, 1.0f)},
|
||||
{"volume", std::max(0.0f, read_float(*blend.sdna, element, "volume").value_or(1.0f))},
|
||||
{"pitch", std::max(0.0f, read_float(*blend.sdna, element, "pitch").value_or(1.0f))},
|
||||
};
|
||||
if (const std::optional<uint64_t> sound_pointer = read_pointer(*blend.sdna, element, "sound")) {
|
||||
const auto sound_id = ids_by_pointer.find(*sound_pointer);
|
||||
if (sound_id != ids_by_pointer.end()) speaker["soundId"] = sound_id->second;
|
||||
}
|
||||
speakers.push_back(std::move(speaker));
|
||||
}
|
||||
else if (record.type_name == "Image") {
|
||||
std::string filepath = read_string(*blend.sdna, element, "filepath");
|
||||
const std::vector<ElementRef> image_views = linked_list_elements(blend, element, "views");
|
||||
@@ -3624,6 +3807,18 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
non_mesh_data.push_back(non_mesh_data_from_record(blend, element, record, ids_by_pointer));
|
||||
}
|
||||
else if (record.type_name == "Text") {
|
||||
if (const std::optional<json> text = script_source_from_record(blend, element, record)) {
|
||||
json resource = {{"id", record.id}, {"name", record.name}};
|
||||
resource["source"] = text->value("source", std::string());
|
||||
resource["sourceSha256"] = text->value("sourceSha256", std::string());
|
||||
resource["byteLength"] = text->value("byteLength", size_t(0));
|
||||
resource["lineCount"] = text->value("lineCount", size_t(0));
|
||||
resource["internal"] = text->value("internal", true);
|
||||
resource["isDirty"] = (read_integer(*blend.sdna, element, "flags").value_or(0) & (1 << 0)) != 0;
|
||||
resource["useModule"] = (read_integer(*blend.sdna, element, "flags").value_or(0) & (1 << 4)) != 0;
|
||||
if (text->contains("sourcePath")) resource["sourcePath"] = text->at("sourcePath");
|
||||
texts.push_back(std::move(resource));
|
||||
}
|
||||
if (script_sources.size() >= 1024) {
|
||||
script_sources_blocked = true;
|
||||
}
|
||||
@@ -3643,6 +3838,21 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
script_sources_blocked = true;
|
||||
}
|
||||
}
|
||||
else if (record.type_name == "Tex") {
|
||||
textures.push_back({
|
||||
{"id", record.id},
|
||||
{"name", record.name},
|
||||
{"type", read_integer(*blend.sdna, element, "type").value_or(0)},
|
||||
{"noiseScale", std::max(0.0f, read_float(*blend.sdna, element, "noisesize").value_or(0.25f))},
|
||||
{"noiseDepth", std::clamp<int64_t>(read_integer(*blend.sdna, element, "noisedepth").value_or(2), 0, 30)},
|
||||
{"intensity", std::max(0.0f, read_float(*blend.sdna, element, "bright").value_or(1.0f))},
|
||||
{"contrast", std::max(0.0f, read_float(*blend.sdna, element, "contrast").value_or(1.0f))},
|
||||
{"saturation", std::max(0.0f, read_float(*blend.sdna, element, "saturation").value_or(1.0f))},
|
||||
});
|
||||
}
|
||||
else if (record.type_name == "WorkSpace") {
|
||||
workspace_resources.push_back({{"id", record.id}, {"name", record.name}, {"screenCount", linked_list_elements(blend, element, "layouts").size()}});
|
||||
}
|
||||
else if (record.type_name == "VFont") {
|
||||
const std::string filepath = read_string(*blend.sdna, element, "filepath");
|
||||
const std::optional<uint64_t> packed_file = read_pointer(*blend.sdna, element, "packedfile");
|
||||
@@ -3947,6 +4157,15 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
sort_by_id(lights);
|
||||
sort_by_id(worlds);
|
||||
sort_by_id(images);
|
||||
sort_by_id(brushes);
|
||||
sort_by_id(line_styles);
|
||||
sort_by_id(lattices);
|
||||
sort_by_id(particle_settings);
|
||||
sort_by_id(sounds);
|
||||
sort_by_id(speakers);
|
||||
sort_by_id(texts);
|
||||
sort_by_id(textures);
|
||||
sort_by_id(workspace_resources);
|
||||
sort_by_id(non_mesh_data);
|
||||
sort_by_id(vfonts);
|
||||
sort_by_id(libraries);
|
||||
@@ -3985,6 +4204,15 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
{"lights", std::move(lights)},
|
||||
{"worlds", std::move(worlds)},
|
||||
{"images", std::move(images)},
|
||||
{"brushes", std::move(brushes)},
|
||||
{"lineStyles", std::move(line_styles)},
|
||||
{"lattices", std::move(lattices)},
|
||||
{"particleSettings", std::move(particle_settings)},
|
||||
{"sounds", std::move(sounds)},
|
||||
{"speakers", std::move(speakers)},
|
||||
{"texts", std::move(texts)},
|
||||
{"textures", std::move(textures)},
|
||||
{"workspaces", std::move(workspace_resources)},
|
||||
{"nonMeshData", std::move(non_mesh_data)},
|
||||
{"vfonts", std::move(vfonts)},
|
||||
{"libraryStatus", libraries_blocked ? "BLOCKED" : "AVAILABLE"},
|
||||
@@ -3998,6 +4226,7 @@ json scene_ir_from_blend(const ParsedBlend &blend,
|
||||
{"scenes", std::move(scenes)},
|
||||
{"activeObjectId", active_object_id.empty() ? json(nullptr) : json(active_object_id)},
|
||||
{"frame", {{"current", frame_current}, {"start", frame_start}, {"end", frame_end}}}};
|
||||
snapshot["windowManager"] = {{"id", "window-manager:WinMan"}, {"name", "WinMan"}, {"presetName", "New Preset"}, {"windowCount", 1}, {"interfaceLocked", false}};
|
||||
if (!masks_blocked) {
|
||||
snapshot["trackingMasks"] = {{"schemaVersion", 1},
|
||||
{"revision", revision},
|
||||
|
||||
@@ -4396,6 +4396,41 @@ bool web_engine_blend_main_physics_simulation_json(WebBlendMainState *state,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_particle_settings_json(WebBlendMainState *state,
|
||||
std::string &particle_settings_json,
|
||||
std::string &error)
|
||||
{
|
||||
if (state == nullptr || state->main == nullptr) {
|
||||
error = "PARTICLE_SETTINGS_MANIFEST_INVALID: authoritative Main is not open";
|
||||
return false;
|
||||
}
|
||||
constexpr size_t max_settings = 4096;
|
||||
auto canonical_number = [](const float value) -> json {
|
||||
return std::isfinite(value) && std::trunc(value) == value ? json(int64_t(value)) : json(value);
|
||||
};
|
||||
json settings = json::array();
|
||||
for (const ParticleSettings &part : state->main->particles) {
|
||||
if (settings.size() >= max_settings) {
|
||||
error = "PARTICLE_SETTINGS_BUDGET_EXCEEDED: ParticleSettings count exceeds the 4096 data-block budget";
|
||||
return false;
|
||||
}
|
||||
settings.push_back({{"id", "particle-settings:" + id_name(part.id)},
|
||||
{"name", id_name(part.id)},
|
||||
{"type", int(part.type)},
|
||||
{"from", int(part.from)},
|
||||
{"distribution", int(part.distr)},
|
||||
{"physicsType", int(part.phystype)},
|
||||
{"totalParticles", part.totpart},
|
||||
{"start", canonical_number(part.sta)},
|
||||
{"end", canonical_number(part.end)},
|
||||
{"lifetime", canonical_number(part.lifetime)},
|
||||
{"size", canonical_number(part.size)},
|
||||
{"drawSize", canonical_number(part.draw_size)}});
|
||||
}
|
||||
particle_settings_json = json({{"schemaVersion", 1}, {"settings", std::move(settings)}}).dump();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool web_engine_blend_main_create_grease_pencil_layer(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const char *name,
|
||||
|
||||
@@ -383,6 +383,9 @@ bool web_engine_blend_main_geometry_node_graphs_json(WebBlendMainState *state,
|
||||
bool web_engine_blend_main_physics_simulation_json(WebBlendMainState *state,
|
||||
std::string &physics_json,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_particle_settings_json(WebBlendMainState *state,
|
||||
std::string &particle_settings_json,
|
||||
std::string &error);
|
||||
bool web_engine_blend_main_create_grease_pencil_layer(WebBlendMainState *state,
|
||||
const char *data_id,
|
||||
const char *name,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
更新时间:2026-08-18
|
||||
|
||||
> 覆盖参考(归档):本文不是任务队列,也不进入默认上下文。只在任务卡明确引用某个 F 域时读取对应小节。
|
||||
|
||||
> 本文保留为 Blender 全产品覆盖检查表和 F00-F24 taxonomy 参考。M12-M23 的执行分类、
|
||||
> 原子任务、证据合同与发布门以 `BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md` 为准;
|
||||
> 本文的 F 任务不能直接作为当前 `nextTask`,也不能独立改变机器状态。
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
更新时间:2026-08-18
|
||||
|
||||
> 长期规范背景:本文件不进入默认任务上下文,不提供当前领取指针。执行者必须先运行
|
||||
> `node tools/web/print-task-context.mjs`,只有任务卡明确要求时才读取本文件的具体小节。
|
||||
|
||||
本文是 M12 及以后完整 Blender 5.2 Web 迁移的长期规范事实源,负责执行分类、原子任务、
|
||||
依赖、证据和完整发布门。它不覆盖 `WEB_BLENDER_MODELER_V1_SCOPE.md` 的 V1 产品契约,也不
|
||||
改写 V1 已冻结的 `LOCAL_EXACT/LOCAL_BOUNDED/SERVER/EXCLUDED` 发布分类。
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
更新时间:2026-08-13
|
||||
|
||||
> 覆盖参考(归档):本文不作为当前任务入口;当前执行只认 `EXECUTION_QUEUE.md` 与 parent manifest。
|
||||
|
||||
本文件以仓库内 `blender-5.2.0/source/blender/` 为基线,记录 Blender 功能域在 Web
|
||||
项目中的迁移方式和当前差距。M12-M23 的唯一长期实施规则和原子任务位于
|
||||
`BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md`;本文不再定义领取顺序。`completed_current_scope`
|
||||
|
||||
46
docs/CONTEXT_BUDGET.md
Normal file
46
docs/CONTEXT_BUDGET.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# 任务上下文预算
|
||||
|
||||
完整治理流程见 [`CONTEXT_GOVERNANCE.md`](CONTEXT_GOVERNANCE.md);本页只保留机器需要的预算和索引契约。
|
||||
|
||||
本项目把“能否持续执行”定义为可检查的输入预算,而不是依赖执行者自行控制阅读量。每轮领取任务只加载一个最小上下文包:
|
||||
|
||||
1. `docs/EXECUTION_QUEUE.md`:当前指针和规则,最多 4 KiB。
|
||||
2. `docs/tasks/<task>.md`:一个行为的任务卡,最多 8 KiB。
|
||||
3. `tests/golden/<parent>/manifest.json`:只取 parent、runtime、artifact hash、`nextTask`,最多 24 KiB。
|
||||
4. `docs/status/<parent>.md`:只取上一任务的证据摘要,最多 6 KiB。
|
||||
|
||||
四份输入的估算总量最多 3,500 tokens。实现代码、长日志、完整路线图和 parity ledger 只按任务卡列出的路径追加读取;它们不是默认上下文。
|
||||
|
||||
任务上下文生成器在生成 `inputPaths` 时还会前置执行证据筛选:最多 12 个证据路径,证据文件总计最多
|
||||
8 KiB,并从 3,500 token 总预算扣除四份基础文档后使用剩余空间。超限、缺失、越界或不可审计路径不会进入读取清单,
|
||||
而会写入 `inputSelection.excluded[]`,其中 `reason` 是稳定的机器可读排除原因;治理门会校验所选路径、字节总数和排除审计。
|
||||
|
||||
全量 gap 计划 `tests/golden/M15-03A/next-task-plan.json` 约 6.8 MiB,只能由盘点/生成门读取,禁止作为任务上下文打开。`task-index.json` 保存源计划 hash 和每条记录的偏移,`task-catalog.jsonl` 保存一行一个任务;`task-context` 只随机读取当前任务的一行。索引缺失、源 hash 漂移或 catalog 损坏会直接失败,不能回退加载整份计划。
|
||||
|
||||
## 机器门禁
|
||||
|
||||
```bash
|
||||
npm --prefix web run test:task-context
|
||||
npm --prefix web run test:context-governance
|
||||
node tools/web/generate-task-index.mjs
|
||||
node tools/web/check-task-index.mjs
|
||||
node tools/web/generate-task-card.mjs --task <task-id>
|
||||
node tools/web/print-task-context.mjs
|
||||
node tools/web/print-task-context.mjs --task <task-id>
|
||||
node tools/web/check-task-context.mjs --task <task-id> --write
|
||||
node tools/web/check-context-governance.mjs
|
||||
```
|
||||
|
||||
`check-task-context` 会确认队列指针、parent manifest、任务卡/索引、命令入口和预算一致。失败时不能领取任务,也不能手工修改 `nextTask`。索引只由计划生成门更新,执行任务不得手工编辑 catalog 或 offset。
|
||||
|
||||
推进到新任务时,若 `docs/tasks/<task>.md` 不存在,先运行 `generate-task-card.mjs --task <task-id>`;它只从 catalog 的一条记录生成一张短卡,生成后再运行 `check-task-context`。禁止为了生成一张卡读取完整 plan。
|
||||
|
||||
## 文档分层
|
||||
|
||||
- 当前执行:`EXECUTION_QUEUE.md`、当前任务卡、parent `manifest.json`、parent `status`。
|
||||
- 机器索引:`tests/golden/M15-03A/task-index.json`、`task-catalog.jsonl`;仅由工具读取,不是执行者要通读的文档。
|
||||
- 稳定契约:`WEB_BLENDER_MODELER_V1_SCOPE.md`、协议/schema、工具入口。
|
||||
- 背景规划:`CURRENT_EXECUTION_PLAN.md`、`PROJECT_STATUS_AND_NEXT_WORK.md`、完整 parity/WBS 计划。
|
||||
- 历史证据:`docs/status/` 其余文件、`tests/golden/` 其余构件、`test-results/`。
|
||||
|
||||
背景和历史文档不得在任务卡中复制;需要时只引用一个小节或一个具体构件。若文字与机器 manifest 冲突,以命令输出和 manifest 为准。
|
||||
121
docs/CONTEXT_GOVERNANCE.md
Normal file
121
docs/CONTEXT_GOVERNANCE.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# 上下文治理契约
|
||||
|
||||
更新时间:2026-08-19(America/New_York)
|
||||
|
||||
本契约解决两个问题:执行者不需要读完整路线图就能继续工作;任何任务卡、交接状态或机器索引
|
||||
变大、漂移或重复指针时,自动门禁会在领取前失败。它是执行规则,不是项目进度表。
|
||||
|
||||
## 一、事实分层
|
||||
|
||||
每个问题只由一个层级回答,层级之间不互相复制内容:
|
||||
|
||||
| 层级 | 唯一职责 | 默认是否读取 |
|
||||
| --- | --- | --- |
|
||||
| `EXECUTION_QUEUE.md` | 当前 task、parent manifest、专项命令、全局硬规则 | 是 |
|
||||
| `tasks/<task>.md` | 一个行为或一个证据变化的输入、边界、验收和回滚 | 是 |
|
||||
| `tests/golden/<parent>/manifest.json` | parent 状态、artifact hash、运行时、`nextTask` | 是 |
|
||||
| `docs/status/<parent>.md` | 上一项最小证据摘要和已知风险 | 是 |
|
||||
| 协议/生产/测试文件 | 任务卡点名的实现事实 | 按需 |
|
||||
| 长期计划、全量 ledger、历史 status | 背景、审计、归档 | 禁止默认读取 |
|
||||
|
||||
冲突优先级固定为:真实命令输出 > manifest/evidence > 任务卡 > 队列文字 > 长期规划和历史日志。
|
||||
Markdown checkbox 不能覆盖失败命令或 hash 漂移。
|
||||
|
||||
## 二、硬预算
|
||||
|
||||
预算按 UTF-8 bytes 检查,token 用 `ceil(bytes / 4)` 作保守估算。超过任一单项或总预算都不能领取。
|
||||
|
||||
| 输入 | 上限 | 约束 |
|
||||
| --- | ---: | --- |
|
||||
| 队列 | 4 KiB | 只保留一个当前指针,不保留历史任务表 |
|
||||
| 任务卡 | 8 KiB | 最多 12 个输入路径、8 条命令;不复制日志 |
|
||||
| parent manifest | 24 KiB | 只记录必要 artifact,最多 32 项 |
|
||||
| parent status | 6 KiB | 只保留命令、退出码、关键结果、风险和回滚 |
|
||||
| 四份输入合计 | 3,500 tokens | 由 `contextSizeReport` 和治理门同时检查 |
|
||||
| catalog 单行 | 2 KiB | 机器随机读取;执行者不得通读 catalog |
|
||||
|
||||
生成阶段的证据读取清单另外受 `maxFiles=12`、`evidenceBytes=8 KiB` 和基础文档扣除后的剩余上下文空间约束。
|
||||
每个未选路径必须有 `inputSelection.excluded[].reason`,因此校验器不会成为首次发现超大上下文的地方。
|
||||
|
||||
全量 `next-task-plan.json`、parity map 和 gap audit 是生成器输入,不是执行上下文。索引保存源
|
||||
hash 和 catalog offset;源 hash、catalog hash 或 offset 损坏时必须重新生成,不能回退读取大计划。
|
||||
|
||||
## 三、原子任务粒度
|
||||
|
||||
默认“一项任务 = 一个可观察行为或一项独立证据”。以下任一情况出现就拆任务:
|
||||
|
||||
- 同时改变 schema、生产消费、浏览器接线和发布证据;
|
||||
- 需要两个互不依赖的 fixture 或两个不同 owner family;
|
||||
- 正例、取消/重复/超限负例无法在同一 focused command 中清楚断言;
|
||||
- 任务卡需要列出超过 12 个输入或超过 8 条命令;
|
||||
- 任何一项失败会让另一项仍可安全交付。
|
||||
|
||||
复杂能力按适用门拆分,门之间通过 parent manifest 串联:
|
||||
|
||||
| 门 | 只交付一件事 | 失败状态 |
|
||||
| --- | --- | --- |
|
||||
| C 契约 | schema、稳定 ID、预算、错误边界和 revision 规则 | `in_progress` |
|
||||
| P 生产 | Main/Worker/App/viewport 的真实消费路径 | `in_progress` |
|
||||
| N 负例 | 非法、重复、取消、迟到、超限不改变已提交状态 | `in_progress` |
|
||||
| B 浏览器 | Chromium 真实用户路径和可见结果 | `blocked` 或 `in_progress` |
|
||||
| R 资源 | dispose、重启、save/reopen、OPFS/GPU/内存归零 | `in_progress` |
|
||||
| E 证据 | focused command、报告、hash manifest、status、回滚 | 通过后才允许下一个 task |
|
||||
|
||||
M16 及后续 gap 固定为一 gap 一个 task:最小 fixture、desktop/WASM 对比、save/reopen、负例和
|
||||
manifest 证据必须属于该 gap;不要把“完成整个 family”写成一张卡。
|
||||
|
||||
## 四、执行生命周期
|
||||
|
||||
### 领取
|
||||
|
||||
```bash
|
||||
npm --prefix web run test:context-governance
|
||||
node tools/web/print-task-context.mjs
|
||||
node tools/web/check-task-context.mjs
|
||||
```
|
||||
|
||||
只读取打印结果列出的四份文件和任务卡点名的最小实现入口。当前 task 必须等于 parent
|
||||
manifest 的 `nextTask`;不能从旧 Markdown 编号、完整 plan 或 status 列表推导任务。
|
||||
|
||||
### 实施
|
||||
|
||||
先确认最小 fixture 和生产入口,再写 focused test/checker。每条验收命令都必须真实运行并记录
|
||||
退出码;协议或测试文件存在不等于生产能力完成。浏览器、CI、验收和发布证据永久仅限 Chromium。
|
||||
|
||||
### 成功交接
|
||||
|
||||
```bash
|
||||
node tools/web/check-task-context.mjs --task <task-id> --write
|
||||
node tools/web/check-context-governance.mjs
|
||||
```
|
||||
|
||||
只提交本任务的实现/测试、fixture、报告、manifest、status 和 `task-context.json`。manifest 必须
|
||||
绑定所有产物的 SHA-256,并且 `nextTask` 是唯一的下一指针;长日志留在构件目录,不复制进 status。
|
||||
|
||||
### 失败、阻断和恢复
|
||||
|
||||
命令失败、环境缺失、取消、超限、重复、迟到结果或 hash 漂移时保持 `in_progress` 或 `blocked`,
|
||||
不得写成功报告、修改 Main revision 或推进 `nextTask`。修复后从同一 parent 重新运行;不要覆盖
|
||||
parent 证据。任务卡、索引或队列指针不一致时先修复生成证据,再继续实现。
|
||||
|
||||
## 五、提交前门禁
|
||||
|
||||
提交前至少运行:
|
||||
|
||||
```bash
|
||||
npm --prefix web run test:context-governance
|
||||
node tools/web/check-task-index.mjs
|
||||
node tools/web/check-task-context.mjs
|
||||
git diff --check
|
||||
```
|
||||
|
||||
`check-context-governance` 会检查四份文档预算、任务卡必备章节和失败边界、禁止的长文档引用、
|
||||
manifest 路径/构件数量、catalog 行边界以及唯一活动 task。门禁失败即停止,不通过手工删除输出
|
||||
或修改 `nextTask` 绕过。
|
||||
|
||||
## 六、维护规则
|
||||
|
||||
- 新增任务:先更新机器源并运行 `generate-task-index.mjs`,再用 `generate-task-card.mjs --task` 生成短卡;禁止手写 catalog offset。
|
||||
- 完成任务:先写 manifest/status,再用 `check-task-context --write` 生成交接上下文;队列只跟随新 manifest。
|
||||
- 规则变化:只修改本契约、`CONTEXT_BUDGET.md`、模板和治理测试;长期规划只增加链接,不复制规则。
|
||||
- 发现重复或过大的历史文档:标记为背景/归档并从默认入口移除,不在任务卡中粘贴摘要。
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
更新时间:2026-08-19
|
||||
|
||||
> 背景规划文档:不作为当前任务入口,也不覆盖 `EXECUTION_QUEUE.md` 的机器指针。领取任务只读取
|
||||
> [`CONTEXT_BUDGET.md`](CONTEXT_BUDGET.md) 定义的最小上下文包。
|
||||
|
||||
## 1. 交付目标
|
||||
|
||||
当前交付物是 `Web Blender Modeler V1`,不是 Blender 5.2 的完整浏览器移植。
|
||||
@@ -18,8 +21,8 @@ React 工作区和编辑器
|
||||
-> OPFS 大文件 + IndexedDB 元数据
|
||||
```
|
||||
|
||||
本计划保留阶段边界和退出条件;领取任务时只读取精简入口 `docs/EXECUTION_QUEUE.md`、对应
|
||||
`docs/tasks/<task>.md` 和 parent manifest,避免加载历史日志。M12-M23 的长期 Blender 全功能实施规范以
|
||||
本计划保留阶段边界和退出条件;领取任务时只运行 `node tools/web/print-task-context.mjs`,仅读取其
|
||||
输出的队列、任务卡/plan 条目、parent manifest 和 parent status,避免加载历史日志。M12-M23 的长期 Blender 全功能实施规范以
|
||||
`BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md` 为准;当前实现状态仍由
|
||||
`status/parity-ledger.json` 和对应 evidence 给出。长期全域差距不阻断已明确限定范围的 V1。
|
||||
|
||||
|
||||
@@ -1,54 +1,44 @@
|
||||
# Web Blender 短周期执行入口
|
||||
|
||||
更新时间:2026-08-19(America/New_York)
|
||||
更新时间:2026-08-20(America/New_York)
|
||||
|
||||
本页只负责“现在领取什么”。文档地图见 [`docs/README.md`](README.md),任务卡见 [`tasks/`](tasks/),
|
||||
长期规则见 `BLENDER_5_2_FULL_WEB_PARITY_EXECUTION_PLAN.md`。不要在本页复制实现日志或历史任务表。
|
||||
|
||||
## 铁律:浏览器范围
|
||||
|
||||
本项目浏览器执行、CI、验收证据和发布声明永久仅限 Chromium。禁止启动、探测或领取 Firefox
|
||||
和 WebKit 测试任务;历史 Firefox/WebKit 报告仅作归档背景,不得作为支持证据。缺失 WebGPU
|
||||
只能由 Chromium 真实能力门将依赖 WebGPU 的功能标记为 `BLOCKED`,不得用其他浏览器推断。
|
||||
本页是唯一的当前任务指针,不保存历史任务表、实现日志或长期规划。领取任务前只读取本页、当前任务上下文、parent manifest 和 parent status;完整规则见 [`CONTEXT_BUDGET.md`](CONTEXT_BUDGET.md)。
|
||||
|
||||
## 当前指针
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| 里程碑 | M14 跨浏览器/设备 |
|
||||
| 当前任务 | `M14-04F` |
|
||||
| parent manifest | `tests/golden/M14-04E/manifest.json` |
|
||||
| 任务卡 | [`tasks/M14-04F.md`](tasks/M14-04F.md) |
|
||||
| 专项验收 | `npm --prefix web run test:chromium-input-modal` |
|
||||
| 里程碑 | M16 Main、Mesh、Modifier、Sculpt |
|
||||
| 当前任务 | `M16-GAP-00071` |
|
||||
| parent manifest | `tests/golden/M16-GAP-00070/manifest.json` |
|
||||
| 任务卡 | [`tasks/M16-GAP-00071.md`](tasks/M16-GAP-00071.md) |
|
||||
| 专项验收 | `npm --prefix web run test:generated-gap -- --task M16-GAP-00071` |
|
||||
|
||||
领取前只读四个文件:本页、任务卡、parent manifest、parent status。完成后新增 task manifest/status,
|
||||
从新 manifest 的 `nextTask` 继续;Markdown 中的旧编号不覆盖机器指针。
|
||||
领取前执行:
|
||||
|
||||
## 任务链
|
||||
```bash
|
||||
npm --prefix web run test:task-context
|
||||
npm --prefix web run test:context-governance
|
||||
node tools/web/print-task-context.mjs
|
||||
```
|
||||
|
||||
| ID | 唯一交付 | 任务卡 |
|
||||
| --- | --- | --- |
|
||||
| M13-04F | stdout/stderr 有界截断与脱敏 | [`M13-04F.md`](tasks/M13-04F.md) |
|
||||
| M13-04G | 取消进程树并清理目录 | [`M13-04G.md`](tasks/M13-04G.md) |
|
||||
| M13-04H | timeout/OOM/signal 稳定错误码 | [`M13-04H.md`](tasks/M13-04H.md) |
|
||||
| M13-04I | hash 校验后原子提交 OPFS | [`M13-04I.md`](tasks/M13-04I.md) |
|
||||
| M13-04J | request 重试幂等和冲突隔离 | [`M13-04J.md`](tasks/M13-04J.md) |
|
||||
| M13-05G | fuzz 崩溃最小化与回归固化 | [`M13-05G.md`](tasks/M13-05G.md) |
|
||||
| M13-05H | 审计记录严格顺序与防篡改 hash chain | [`M13-05H.md`](tasks/M13-05H.md) |
|
||||
| M14-01A | 冻结 Chromium、engine 与 archive 身份 | [`M14-01A.md`](tasks/M14-01A.md) |
|
||||
| M14-01B | Firefox capability probe | 跳过:Chromium-only 铁律 |
|
||||
| M14-01C | WebKit capability probe | 跳过:Chromium-only 铁律 |
|
||||
| M14-01D | probe identity and GPU/OS adapter recording | [`M14-01D.md`](tasks/M14-01D.md) |
|
||||
| M14-01E | Chromium WebGPU fail-closed boundary | [`M14-01E.md`](tasks/M14-01E.md) |
|
||||
| M14-04A | Chromium GPU/memory budget device tier selection | [`M14-04A.md`](tasks/M14-04A.md) |
|
||||
| M14-04B | Chromium DPR 1/1.5/2/3 consistency | [`M14-04B.md`](tasks/M14-04B.md) |
|
||||
| M14-04C | Chromium mouse/touch/pen pointer contract | [`M14-04C.md`](tasks/M14-04C.md) |
|
||||
| M14-04D | Chromium IME composition guard | [`M14-04D.md`](tasks/M14-04D.md) |
|
||||
| M14-04E | Chromium US/non-US/dead-key/modifier keymap fixture | [`M14-04E.md`](tasks/M14-04E.md) |
|
||||
| M14-04F | Chromium touch modal cancel / two-finger / pen commit | [`M14-04F.md`](tasks/M14-04F.md) |
|
||||
如果任务卡缺失,运行 `node tools/web/generate-task-card.mjs --task <task-id>`;如果索引过期,运行 `node tools/web/generate-task-index.mjs` 后再生成任务卡;不要打开或复制完整 `next-task-plan.json`。
|
||||
|
||||
## 统一退出门
|
||||
## 铁律
|
||||
|
||||
每项只声明一个主要行为;适用的生产路径、结构化错误码、取消/迟到结果门、资源清理、专项命令、
|
||||
报告/manifest SHA-256 和回滚条件必须全部具备。执行未通过、环境缺失或 hash 漂移时标记 `blocked`,
|
||||
不能用协议或测试文件存在替代真实运行结果。M13 脚本执行在本链完成前保持 `execution=DISABLED`。
|
||||
- 浏览器执行、CI、验收证据和发布声明永久仅限 Chromium;禁止领取 Firefox/WebKit 任务。
|
||||
- 当前任务必须等于 parent manifest 的 `nextTask`;不得从 Markdown 历史编号手工推导。
|
||||
- 一个任务只能有一个主要行为变化或一个独立证据变化。实现、浏览器接线、负例和证据需要拆成明确子任务时,沿任务卡的门逐项完成。
|
||||
- 完成必须有真实命令、退出码、构件 SHA-256、manifest 和 status;协议、fixture 或测试文件存在不等于完成。
|
||||
- 失败、环境缺失或 hash 漂移保持 `in_progress`/`blocked`,不得推进指针。
|
||||
|
||||
## 交接
|
||||
|
||||
```text
|
||||
node tools/web/check-task-context.mjs --task <task-id> --write
|
||||
```
|
||||
|
||||
完成后只写入 `tests/golden/<task>/task-context.json`、任务报告、manifest 和 `docs/status/<task>.md`。下一任务只读新 manifest 的 `nextTask`;长日志留在构件目录。
|
||||
|
||||
提交前运行 `node tools/web/check-context-governance.mjs` 和 `git diff --check`;门禁失败时保持原 task,
|
||||
不得手工推进 `nextTask`。
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
更新日期:2026-08-09
|
||||
|
||||
> 专项背景(归档):本文不进入默认上下文;PBR 任务必须通过最小上下文工具按卡片追加读取。
|
||||
|
||||
## 1. 目标和声明边界
|
||||
|
||||
目标是在浏览器 3D Viewport 中提供与 Blender Principled 工作流一致、可保存、可重开的
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
更新时间:2026-08-19
|
||||
|
||||
> 背景状态快照:不作为当前任务入口。当前任务、parent 和 `nextTask` 只认
|
||||
> `docs/EXECUTION_QUEUE.md`、任务上下文和机器 manifest;本文件中的“当前”仅指快照生成时点。
|
||||
|
||||
当前短周期任务、领取顺序和阶段退出条件统一维护在
|
||||
`docs/EXECUTION_QUEUE.md`。本文件保留实现事实、长期能力台账和完整验收命令,不再作为
|
||||
V1 的逐项领取顺序;V1 范围以 `docs/WEB_BLENDER_MODELER_V1_SCOPE.md` 为准,M12-M23 全功能
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
# 文档导航
|
||||
|
||||
本目录按“产品契约、当前任务、实现事实、长期规划、验收证据”分层。领取任务时不要从仓库根目录
|
||||
开始通读;只读取当前队列、当前任务卡和机器 manifest 指向的状态页。
|
||||
开始通读;只读取当前队列和机器生成的最小上下文包。预算和自动检查见
|
||||
[`CONTEXT_BUDGET.md`](CONTEXT_BUDGET.md)。
|
||||
完整拆分、预算、交接和提交规则见 [`CONTEXT_GOVERNANCE.md`](CONTEXT_GOVERNANCE.md)。
|
||||
|
||||
## 领取任务
|
||||
|
||||
1. [EXECUTION_QUEUE.md](EXECUTION_QUEUE.md):唯一的短周期入口,给出当前 `nextTask` 和读取顺序。
|
||||
2. `tasks/<task>.md`:当前任务的最小上下文、范围和验收命令。
|
||||
3. `tests/golden/<task>/manifest.json`:机器事实源,确认 parent、输入构件和下一个任务。
|
||||
4. `status/<task>.md`:完成后写入证据、hash、状态和回滚方式。
|
||||
1. [EXECUTION_QUEUE.md](EXECUTION_QUEUE.md):唯一的短周期入口和当前指针。
|
||||
2. `node tools/web/print-task-context.mjs`:只输出当前任务需要的四份输入。
|
||||
3. `tasks/<task>.md`:当前任务唯一的范围、输入和验收;缺卡时先修复生成流程,不要打开完整 plan。
|
||||
4. parent `tests/golden/<parent>/manifest.json` 与 `status/<parent>.md`:只提供交接事实。
|
||||
|
||||
需要拆分实施或控制上下文时,先看 [TASK_BREAKDOWN.md](TASK_BREAKDOWN.md)。它提供阶段地图、
|
||||
原子任务门、当前 M14-04F 的子任务和后续任务草案,但不覆盖 manifest/status 的机器事实。
|
||||
需要拆分实施或控制上下文时,先看 [CONTEXT_GOVERNANCE.md](CONTEXT_GOVERNANCE.md);
|
||||
[TASK_BREAKDOWN.md](TASK_BREAKDOWN.md) 只提供阶段地图和归档示例,不覆盖 manifest/status 的机器事实。
|
||||
|
||||
任务卡使用 [TASK_CONTEXT_TEMPLATE.md](TASK_CONTEXT_TEMPLATE.md) 的固定结构;卡片只描述一个主要
|
||||
行为或一个证据变化,不复制实现日志。
|
||||
行为或一个证据变化,不复制实现日志。全量 gap 计划由机器索引切片,`check-task-context` 会阻止
|
||||
超预算、缺卡、过期索引或 parent 指针错误进入队列。
|
||||
|
||||
## 事实源
|
||||
|
||||
@@ -36,8 +39,12 @@
|
||||
|
||||
## 最小上下文规则
|
||||
|
||||
默认只加载本页列出的四个入口文件;实现细节按任务卡的文件清单追加读取。不要为了确认一个
|
||||
局部输入、IO 或安全任务而加载整份 `PROJECT_STATUS_AND_NEXT_WORK.md` 或完整 parity 计划。
|
||||
默认只加载队列、当前任务卡、parent manifest 和 parent status;总量上限为 3,500 tokens。
|
||||
实现细节按任务卡的文件清单追加读取。不要为了确认一个局部输入、IO 或安全任务而加载整份
|
||||
`PROJECT_STATUS_AND_NEXT_WORK.md` 或完整 parity 计划。
|
||||
|
||||
`next-task-plan.json`、parity map 和 gap audit 是生成器输入,不是任务上下文;任务工具只读取
|
||||
带 hash 的单行 catalog 记录。
|
||||
|
||||
文档描述与 manifest/evidence 冲突时,以可复验的机器状态为准;不要通过修改 Markdown
|
||||
checkbox 覆盖失败证据。
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
更新时间:2026-08-19(America/New_York)
|
||||
|
||||
> 拆分参考(归档):本文件不进入默认任务上下文。当前任务和依赖只由 `print-task-context` 与
|
||||
> parent manifest 提供;这里只在需要设计新的子任务门时读取对应小节。
|
||||
|
||||
本文件是“如何拆任务、如何领取任务、如何交接”的规划索引,不是实现状态事实源。当前状态仍以
|
||||
`docs/EXECUTION_QUEUE.md`、当前任务的 `manifest.json`、对应 `docs/status/<task>.md` 和可复验命令为准。
|
||||
本文件的目标是让一次任务只加载必要上下文,不要求阅读整份路线图或历史接续日志。
|
||||
@@ -11,9 +14,10 @@
|
||||
每轮只按下面顺序读取:
|
||||
|
||||
1. `docs/EXECUTION_QUEUE.md`:确认唯一当前 `nextTask`、Chromium-only 规则和专项命令。
|
||||
2. `docs/tasks/<task>.md`:读取目标、输入、范围、验收和回滚。
|
||||
3. `tests/golden/<parent>/manifest.json`:确认 parent hash、依赖、运行时和下一任务。
|
||||
4. `docs/status/<parent>.md`:只读取上一项的证据摘要和已知风险。
|
||||
2. `node tools/web/print-task-context.mjs`:取得已经裁剪的单任务 JSON;不要读取 plan、gap audit 或 parity map。
|
||||
3. `docs/tasks/<task>.md`:读取目标、输入、范围、验收和回滚。
|
||||
4. `tests/golden/<parent>/manifest.json`:确认 parent hash、依赖、运行时和下一任务。
|
||||
5. `docs/status/<parent>.md`:只读取上一项的证据摘要和已知风险。
|
||||
|
||||
只有遇到以下问题才继续读取:
|
||||
|
||||
@@ -80,6 +84,27 @@
|
||||
|
||||
任务卡可以把 C/P/N/B/R/E 写成子任务,但只有所有适用门通过后,主任务才可变为 `done`。
|
||||
|
||||
### 3.2 生成 gap 的细分协议
|
||||
|
||||
M16 及后续全域 gap 采用“一条 gap、一个任务、五扇证据门”的固定粒度。任务 ID、gap、owner 和
|
||||
实现类别由机器 catalog 提供;任务卡只补充该条 gap 的真实 fixture、生产入口和边界,不复制全量
|
||||
计划字段。
|
||||
|
||||
| 门 | 唯一交付 | 失败时的状态 |
|
||||
| --- | --- | --- |
|
||||
| C | 字段/稳定 ID/错误边界契约 | `in_progress`,不得写入成功报告 |
|
||||
| D | desktop fixture 和可重跑报告 | `blocked` 或 `in_progress`,不得接 WASM |
|
||||
| W | WASM/Main 消费同一 fixture | `in_progress`,不得声称 parity |
|
||||
| R | save/reopen 或 revision 稳定性 | `in_progress`,不得推进队列 |
|
||||
| E | comparator、manifest、status、rollback | 只有 E 完成才允许 parent `nextTask` |
|
||||
|
||||
生成目录中的 `next-task-plan.json` 是盘点输入,不是执行上下文。`generate-task-index.mjs` 将其切成
|
||||
带源 hash 的 `task-index.json` 和一行一个任务的 `task-catalog.jsonl`;执行工具按 offset 读取单条
|
||||
记录,并由任务卡恢复命令模板。索引失效、任务卡缺失、parent 指针不一致或单卡超过 8 KiB 时,
|
||||
领取门直接失败。
|
||||
|
||||
新任务卡使用 `node tools/web/generate-task-card.mjs --task <task-id>` 按 catalog 单条记录生成;生成器拒绝未知 ID、没有 parent 的首项和已有卡覆盖,除非显式传入 `--force`。生成后必须重新运行上下文门禁。
|
||||
|
||||
## 4. 项目阶段分解
|
||||
|
||||
下面是导航级分解;具体领取仍由短周期队列决定。
|
||||
@@ -99,14 +124,15 @@
|
||||
| M11 | Render/Compositor/Media | bounded local、server route、codec/revision/audio | 已完成的 V1 slice |
|
||||
| M12 | Asset/IO/Editors | 资产库、GLB/OBJ/STL/PLY、编辑器上下文 | 按 manifest 继续领取,不能按总百分比判断 |
|
||||
| M13 | Scripting/Security | metadata-only、default-deny、sandbox、server isolation、CSP | 每个安全门独立验收;execution 默认禁用 |
|
||||
| M14 | Chromium 设备与输入 | capability、预算、DPR、pointer、IME、keymap、modal、可访问性 | 当前短周期在 `M14-04F` |
|
||||
| M15 | 全域审计 | Blender 5.2 inventory、operator/node/editor/format gap | 未开始;不阻断已限定 V1 |
|
||||
| M14 | Chromium 设备与输入 | capability、预算、DPR、pointer、IME、keymap、modal、可访问性 | 已归档;后续只按 manifest 回归 |
|
||||
| M15 | 全域审计 | Blender 5.2 inventory、operator/node/editor/format gap | 已完成计划/审计门;产出 6,900 条 M16-M22 原子 gap |
|
||||
| M16-M22 | 原子 parity gap | 每条 gap 独立 fixture、desktop/WASM 对标、重开和 hash 证据 | 只按 parent manifest 顺序推进;当前任务不在本表缓存 |
|
||||
|
||||
状态轴必须分开:V1 `releaseStatus=READY` 不等于 Blender 全域 `parityStatus=COMPLETE`。
|
||||
|
||||
## 5. 当前 M14-04F 细分
|
||||
## 5. 历史示例:M14-04F 细分(非当前任务)
|
||||
|
||||
### 5.1 当前已知上下文
|
||||
### 5.1 归档时的已知上下文
|
||||
|
||||
- parent:`M14-04E`,状态页已记录 keymap fixture 的成功证据。
|
||||
- 当前任务:`M14-04F`,任务卡为 `docs/tasks/M14-04F.md`。
|
||||
@@ -145,7 +171,7 @@
|
||||
|
||||
如果只有协议和测试通过,状态应保持 `in_progress`,不得提前领取 M14-04G。
|
||||
|
||||
## 6. M14 后续任务草案
|
||||
## 6. M14 后续任务草案(归档)
|
||||
|
||||
这些是领取前的拆分草案;正式任务仍须由 parent manifest 生成任务卡。
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# 任务上下文模板
|
||||
|
||||
每张任务卡只允许一个主要行为变化或一个证据变化。保持短小;实现细节放在代码和测试中,运行结果
|
||||
放在 `docs/status/<task>.md`,不要在任务卡复制长日志。
|
||||
每张任务卡只允许一个主要行为变化或一个证据变化。卡片上限 8 KiB,最多 12 个输入路径和 8 条命令;实现细节放在代码和测试中,
|
||||
运行结果放在 `docs/status/<task>.md`,不要在任务卡复制长日志。机器生成 gap 也必须有同样的短卡;
|
||||
catalog 只供工具随机读取,不替代任务卡,也不应被执行者通读。
|
||||
|
||||
不要在任务卡引用 `next-task-plan.json`、完整路线图、全量 status 或 `test-results/`;需要背景时只
|
||||
点名一个稳定契约的小节。
|
||||
|
||||
## 任务
|
||||
|
||||
@@ -16,8 +20,8 @@
|
||||
## 输入
|
||||
|
||||
- 上一个 manifest:`tests/golden/<parent>/manifest.json`
|
||||
- 生产入口:`<protocol/worker/server path>`
|
||||
- 最小 fixture:`<fixture path or NOT_APPLICABLE>`
|
||||
- 生产入口:`<single source/test/checker path>`;不要写“相关代码”或整目录。
|
||||
|
||||
## 范围
|
||||
|
||||
@@ -30,6 +34,8 @@
|
||||
<focused command>
|
||||
```
|
||||
|
||||
至少列出一个负例、取消、重复或预算超限场景;不要把全量回归命令复制到卡片。
|
||||
|
||||
适用时补充 Node、Chromium、typecheck、lint;每条命令必须真实运行并记录退出码。
|
||||
|
||||
## 产物和交接
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
更新时间:2026-08-09
|
||||
|
||||
> 长期规划(归档):本文不进入默认上下文;只按任务卡引用的章节读取。
|
||||
|
||||
本计划把当前未声明的 Sculpt、Geometry Nodes/Simulation、任意 Shader Node 和完整
|
||||
NLA 拆成四个可独立验收的连续任务。每个任务都必须满足:Blender Main 是唯一写入
|
||||
权威;SceneIR 只承载通过校验的数据;Three.js 不执行 Blender 语义;不支持或不确定
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
更新时间:2026-08-14
|
||||
|
||||
> 专项背景(归档):本文不进入默认上下文;VDB 任务必须通过最小上下文工具按卡片追加读取。
|
||||
|
||||
## 1. 范围与完成定义
|
||||
|
||||
VDB 重新纳入 N-015/N-019/N-023/N-026。产品链路固定为:桌面工具或受控服务端使用
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M12-07H Status
|
||||
|
||||
status: done
|
||||
task: PLY vertex/face/color/custom property mapping and unknown property loss report
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: PLY vertex/face/color/custom property mapping and unknown property loss report
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M12-07I Status
|
||||
|
||||
status: done
|
||||
task: PLY big-endian, malformed list, and oversized count stable blocking
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: PLY big-endian, malformed list, and oversized count stable blocking
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M12-07J Status
|
||||
|
||||
status: done
|
||||
task: three-format cancellation, OOM, Worker restart, and small-file recovery
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: three-format cancellation, OOM, Worker restart, and small-file recovery
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-01A Status
|
||||
|
||||
status: done
|
||||
task: inventory Text, Python Console, autorun, driver expression, handler, and add-on entry points
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: true
|
||||
status: done
|
||||
task: inventory Text, Python Console, autorun, driver expression, handler, and add-on entry points
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: true
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-01B Status
|
||||
|
||||
status: done
|
||||
task: read script metadata on `.blend` open without executing arbitrary content
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: read script metadata on `.blend` open without executing arbitrary content
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-01C Status
|
||||
|
||||
status: done
|
||||
task: default-deny autorun, register, install, and driver execution policy codes
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: default-deny autorun, register, install, and driver execution policy codes
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-01D Status
|
||||
|
||||
status: done
|
||||
task: UI direct-eval bypass gate
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: UI direct-eval bypass gate
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-01E Status
|
||||
|
||||
status: done
|
||||
task: preserve Text data and unknown script sources through save/reopen
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: preserve Text data and unknown script sources through save/reopen
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-01F Status
|
||||
|
||||
status: done
|
||||
task: malicious Text, driver, handler, and embedded-module fixtures
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: malicious Text, driver, handler, and embedded-module fixtures
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-02A Status
|
||||
|
||||
status: done
|
||||
task: bounded script manifest limits
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: bounded script manifest limits
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-02B Status
|
||||
|
||||
status: done
|
||||
task: canonical script manifest serialization
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: canonical script manifest serialization
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-02C Status
|
||||
|
||||
status: done
|
||||
task: signer identity, key rotation, revocation and timestamp policy
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: signer identity, key rotation, revocation and timestamp policy
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-02D Status
|
||||
|
||||
status: done
|
||||
task: signature verification binds declared content
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: signature verification binds declared content
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-02E Status
|
||||
|
||||
status: done
|
||||
task: permission default-minimization and unknown-permission blocking
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: permission default-minimization and unknown-permission blocking
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-02F Status
|
||||
|
||||
status: done
|
||||
task: signature replay, key-confusion and expiry negative cases
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: signature replay, key-confusion and expiry negative cases
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03A Status
|
||||
|
||||
status: done
|
||||
task: sandbox capability scope
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: sandbox capability scope
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03B Status
|
||||
|
||||
status: done
|
||||
task: sandbox CPU, wall, memory, message and output budgets
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: sandbox CPU, wall, memory, message and output budgets
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03C Status
|
||||
|
||||
status: done
|
||||
task: explicit host-call allowlist and structured parameters
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: explicit host-call allowlist and structured parameters
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03D Status
|
||||
|
||||
status: done
|
||||
task: sandbox crash/timeout isolation
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: sandbox crash/timeout isolation
|
||||
updated: 2026-08-18 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03E Status
|
||||
|
||||
status: done
|
||||
task: sandbox cancellation result gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: sandbox cancellation result gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03F Status
|
||||
|
||||
status: done
|
||||
task: sandbox resource disposal gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: sandbox resource disposal gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-03G Status
|
||||
|
||||
status: done
|
||||
task: same-session sandbox recovery and audit continuity
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: same-session sandbox recovery and audit continuity
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04A Status
|
||||
|
||||
status: done
|
||||
task: server job one-shot directory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: server job one-shot directory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04B Status
|
||||
|
||||
status: done
|
||||
task: server source read-only and output isolation
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: server source read-only and output isolation
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04C Status
|
||||
|
||||
status: done
|
||||
task: server job resource budget gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: server job resource budget gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04F Status
|
||||
|
||||
status: done
|
||||
task: bounded and redacted server stdout/stderr
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: bounded and redacted server stdout/stderr
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04G Status
|
||||
|
||||
status: done
|
||||
task: server process-tree cancellation
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: server process-tree cancellation
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04H Status
|
||||
|
||||
status: done
|
||||
task: stable server process fault codes
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: stable server process fault codes
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04I Status
|
||||
|
||||
status: done
|
||||
task: server result hash binding and atomic OPFS handoff
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: server result hash binding and atomic OPFS handoff
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-04J Status
|
||||
|
||||
status: done
|
||||
task: server request idempotency and conflict isolation
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: server request idempotency and conflict isolation
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05A Status
|
||||
|
||||
status: done
|
||||
task: CSP default-deny policy
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: CSP default-deny policy
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05B Status
|
||||
|
||||
status: done
|
||||
task: resource-specific CSP policy
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: resource-specific CSP policy
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05C Status
|
||||
|
||||
status: done
|
||||
task: production/build/test dependency inventories
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: production/build/test dependency inventories
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Evidence
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05D Status
|
||||
|
||||
status: done
|
||||
task: dependency severity gates and exceptions
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: dependency severity gates and exceptions
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
The severity policy is machine-readable: BLOCKER/HIGH block, MEDIUM requires review and LOW is tracked.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05E Status
|
||||
|
||||
status: done
|
||||
task: SBOM/license/source-offer and archive binding
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: SBOM/license/source-offer and archive binding
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
The supply-chain checker binds SPDX 2.3 to the lockfile and notices hashes, verifies the corresponding
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05F Status
|
||||
|
||||
status: done
|
||||
task: malicious input matrix
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: malicious input matrix
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
The production blend loader rejected five malformed blend cases. Existing production protocol tests
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05G Status
|
||||
|
||||
status: done
|
||||
task: fuzz crash minimization and regression capture
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: fuzz crash minimization and regression capture
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M13-05H Status
|
||||
|
||||
status: done
|
||||
task: script audit record integrity
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: script audit record integrity
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-01A Status
|
||||
|
||||
status: done
|
||||
task: Chromium, engine and archive identity freeze
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium, engine and archive identity freeze
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-01B Status
|
||||
|
||||
status: done
|
||||
task: Firefox capability probe
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Firefox capability probe
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
Firefox `153.0` was probed against the rebuilt production assets with COOP/COEP isolation. WASM, Worker,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-01C Status
|
||||
|
||||
status: done
|
||||
task: WebKit capability probe
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: WebKit capability probe
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
WebKit `26.5` was probed against the rebuilt production assets with COOP/COEP isolation. WASM, Worker,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-01D Status
|
||||
|
||||
status: done
|
||||
task: probe identity and GPU/OS adapter recording
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: probe identity and GPU/OS adapter recording
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-01E Status
|
||||
|
||||
status: done
|
||||
task: Chromium WebGPU fail-closed boundary
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium WebGPU fail-closed boundary
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-04A Status
|
||||
|
||||
status: done
|
||||
task: Chromium GPU/memory budget device tier selection
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium GPU/memory budget device tier selection
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-04B Status
|
||||
|
||||
status: done
|
||||
task: Chromium DPR 1/1.5/2/3 canvas and raycast consistency
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium DPR 1/1.5/2/3 canvas and raycast consistency
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-04C Status
|
||||
|
||||
status: done
|
||||
task: Chromium mouse/touch/pen pointer identity and cancellation contract
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium mouse/touch/pen pointer identity and cancellation contract
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-04D Status
|
||||
|
||||
status: done
|
||||
task: Chromium IME composition guard for incomplete operators
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium IME composition guard for incomplete operators
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# M14-04E Status
|
||||
|
||||
status: done
|
||||
task: Chromium US/non-US/dead-key/modifier keymap fixture
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
status: done
|
||||
task: Chromium US/non-US/dead-key/modifier keymap fixture
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
43
docs/status/M14-04F.md
Normal file
43
docs/status/M14-04F.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# M14-04F Status
|
||||
|
||||
status: done
|
||||
task: Chromium touch modal cancel, two-finger navigation and pen single commit
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
`InputModalState` is now consumed by both production viewport backends. Touch cancellation clears
|
||||
the modal without a Main commit, the transition to two active touch pointers increments
|
||||
`navigationRevision` once, and a pen pointerup increments `mainCommitCount` once. Late pen up/cancel
|
||||
events do not create another commit. The state is exposed through bounded `data-input-modal-*`
|
||||
diagnostic attributes for Chromium evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run build` passed.
|
||||
- `npm --prefix web run test:chromium-input-modal` passed: 3 protocol tests plus real Chromium
|
||||
main-thread and OffscreenCanvas scenarios.
|
||||
- Checker output: `chromium-input-modal-ok backends=main,offscreen touchCancel=0 twoFingerRevision=1 penCommit=1 execution=DISABLED next=M14-04G`.
|
||||
- `npm --prefix web run typecheck`, `npm --prefix web run lint` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `b5fbb86d4a6a610b4aa25f8edb9a232aca9675e25fb47b16de98858a2d7f007f`
|
||||
- checker: `4f813623d9845b73c1a05aeccaf88d8d3b13d48e5fd83c83fa6222e13324e854`
|
||||
- protocol: `271e4f9e86a6aa4ebe92a43f6ce3d9b42b0931a5d12d9b40a8b4c26b2808cb23`
|
||||
- unit: `f8105ebb59f3a369b15282a3923bdc47249f7a727794d3a89c29c1523f1aa989`
|
||||
- main viewport: `e8d97cb59fd4eca3789aeeb35221a70cf47ef048a5665383d809d0efc49f7119`
|
||||
- offscreen viewport: `4a210ae247d0e29972096da6c206f3457c2238e6061c6eb622f0ce55c6bfd439`
|
||||
- report: `dc8c386a705c4cd7335eb5f7ea0ec9d61feaae8b9529fdab423ab00898ecf911`
|
||||
- manifest: `895b460477a8379594ee93043139b9521952638dbd6670b0205eab1896886455`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M14-04G`: Chromium responsive layout no-overlap/no-overflow matrix.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the input-modal reducer integration, viewport diagnostics, tests, checker, report, manifest,
|
||||
package command and this status/task entry; restore `M14-04E` as the queue tail.
|
||||
43
docs/status/M14-04G.md
Normal file
43
docs/status/M14-04G.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# M14-04G Status
|
||||
|
||||
status: done
|
||||
task: Chromium responsive layout no-overlap/no-overflow matrix
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The Chromium layout gate now covers main-thread WebGL and OffscreenCanvas Worker viewports at
|
||||
1440x900, 1280x720, 834x1112 and 390x844 with DPR 1 and 2. It checks root/body horizontal overflow,
|
||||
layout-band containment, text overflow and app bounds. The mobile breakpoint moved to 900px so the
|
||||
834px tablet layout hides the desktop menu before it can widen the document.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run build` passed.
|
||||
- `npm --prefix web run test:chromium-layout` passed: 16 real Chromium combinations (2 backends x
|
||||
2 DPR values x 4 viewports).
|
||||
- Checker output: `chromium-layout-ok backends=main,offscreen viewports=4 dpr=1,2 results=16 execution=DISABLED next=M14-04H`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `895b460477a8379594ee93043139b9521952638dbd6670b0205eab1896886455`
|
||||
- checker: `b211b703309e22810c39f85e4801bc5f0690fa682e33cdcb85157bd28ea042c0`
|
||||
- app: `92d01daecf3f39bc4ac214e4b651ec6feb687bbfbf58c4d3e602a314cdcc664c`
|
||||
- CSS: `5961164f29e25b461c03201534fe56e32020633cac6c0970e149a58ba9f6e9fc`
|
||||
- main viewport: `e8d97cb59fd4eca3789aeeb35221a70cf47ef048a5665383d809d0efc49f7119`
|
||||
- offscreen viewport: `4a210ae247d0e29972096da6c206f3457c2238e6061c6eb622f0ce55c6bfd439`
|
||||
- reference e2e: `f5de57f570880f823224ebdcddb2be4d59ec414a32641effdaa68dc1f4102f28`
|
||||
- report: `65b1050217e2343e656d56c4d7893d13f36b5f07008288ea194a101dafbaa0e2`
|
||||
- manifest: `a5a80cedd824cc4aac27bd2cec39e11560d4cf3207ab947a1abe19c8bb9e053f`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M14-04H`: Chromium keyboard-only, accessible names/roles and focus restoration.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the 900px breakpoint change, layout checker, report, manifest, package command and this status/task
|
||||
entry; restore `M14-04F` as the queue tail.
|
||||
40
docs/status/M14-04H.md
Normal file
40
docs/status/M14-04H.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# M14-04H Status
|
||||
|
||||
status: done
|
||||
task: Chromium keyboard-only, accessible names/roles and focus restoration
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The Chromium keyboard gate runs real main-thread and OffscreenCanvas pages. Tab reaches the File
|
||||
menu, Enter opens it with menuitem focus, Escape restores the trigger, and F3 opens Operator Search
|
||||
with Escape restoring its trigger. The checker also scans visible interactive elements for an
|
||||
accessible name and records the count per backend.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run build` passed.
|
||||
- `npm --prefix web run test:chromium-accessibility` passed for both production backends.
|
||||
- Checker output: `chromium-accessibility-ok backends=main,offscreen menuFocus=RESTORED operatorSearchFocus=RESTORED names=COMPLETE execution=DISABLED next=M15-01A`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `a5a80cedd824cc4aac27bd2cec39e11560d4cf3207ab947a1abe19c8bb9e053f`
|
||||
- checker: `b39cdef61007e5ac1f2e7686ccdffd42f6b9723b2e93a7bd63e46800c4453ced`
|
||||
- app: `5861988f3dfbb8c05d36aee3033a72514de53a0cb4ec6f3d832418ef6b5cc8b2`
|
||||
- CSS: `5961164f29e25b461c03201534fe56e32020633cac6c0970e149a58ba9f6e9fc`
|
||||
- reference e2e: `e74a53a1f9e9bfea73be8da1de486938d0dcc4718e7585b57bee27a5ce78a978`
|
||||
- report: `508adab3c6ced83c95bcced36d610c20f2f2fd456637cb79568b4b824d66ead9`
|
||||
- manifest: `2c4e4323250f3426f610babb42978ba36c48e471729b20b0ce8f3483eb6f899c`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-01A`: generate a Blender 5.2 RNA data-block type inventory.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the accessibility checker, accessible-name fix, report, manifest, package command and this
|
||||
status/task entry; restore `M14-04G` as the queue tail.
|
||||
38
docs/status/M15-01A.md
Normal file
38
docs/status/M15-01A.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# M15-01A Status
|
||||
|
||||
status: done
|
||||
task: Blender 5.2 RNA data-block type inventory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The pinned Blender 5.2 runtime generated a deterministic RNA inventory from the registered subclasses
|
||||
of `bpy.types.ID`. The inventory contains 29 unique sorted data-block types, stable parity IDs, the
|
||||
RNA source anchor and the runtime binary identity. No V1 release or parity status axis changed.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-rna-inventory` passed after regenerating in a fresh temporary
|
||||
directory with `build_blender_5.2.0/bin/blender`.
|
||||
- Checker output: `blender-rna-datablock-inventory-ok count=29 blender=5.2.0 LTS inventory=98e6c2ebc9f62647b43fb06eff178bef02db06516f6ac87048ae81fcf2d8e792 next=M15-01B`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `2c4e4323250f3426f610babb42978ba36c48e471729b20b0ce8f3483eb6f899c`
|
||||
- generator: `2e61a1a8a2e5347d3ee0f8efa5bad74e9823de6e7b0959f505e73c9d96e7037b`
|
||||
- checker: `43b72286964fcfa1f6beebec786c4f96cf12d5d33c6227754e5b98e2dda668ab`
|
||||
- inventory: `98e6c2ebc9f62647b43fb06eff178bef02db06516f6ac87048ae81fcf2d8e792`
|
||||
- runtime binary: `d4483926610484ef9c2ad9241aae1469f934d955ebe791f1920e263e0ba85b82`
|
||||
- manifest: `21f444610edae75b23a26ef9b94892f07fb056344fbd5e92e232c376454d76cd`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-01B`: Blender 5.2 operator idname, poll context and property inventory.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the RNA generator, checker, inventory, report, manifest, package command and this status/task
|
||||
entry; restore `M14-04H` as the queue tail.
|
||||
40
docs/status/M15-01B.md
Normal file
40
docs/status/M15-01B.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# M15-01B Status
|
||||
|
||||
status: done
|
||||
task: Blender 5.2 operator idname/poll/property inventory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The pinned Blender 5.2 runtime generated a deterministic inventory of all registered `bpy.ops`
|
||||
operators. Each entry records the operator idname, RNA identifier, factory-startup poll result/error,
|
||||
and sorted RNA property identifiers/types. This is a machine baseline only; it does not claim that
|
||||
any operator is supported by the web editor.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-operator-inventory` passed after temporary regeneration.
|
||||
- Checker output: `blender-operator-inventory-ok count=2486 registered=2486 pollUnknown=0 inventory=dabb774ea808f417a0085528ecc4538bc78f71d06f912a881a9453804597e49a next=M15-01C`.
|
||||
- Poll distribution: 666 true, 1,820 false, 0 unknown.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `21f444610edae75b23a26ef9b94892f07fb056344fbd5e92e232c376454d76cd`
|
||||
- generator: `5928c2df2074d7b530c173baffc4da2bb0bbb50817ab8b2cdb5f6d43e07b1727`
|
||||
- checker: `dbf4b64c77750809060e6b3a8eaf87cfd67a904f33949ac631b661153b1f6cde`
|
||||
- inventory: `dabb774ea808f417a0085528ecc4538bc78f71d06f912a881a9453804597e49a`
|
||||
- report: `800102c010be59ec519d2e204aec4a97350fe7ba0f6729f52a8788f4a9bcde31`
|
||||
- manifest: `54dec9d2e7a0eacf3b17a06168b0c9c73a1358d0545cbf70d8a8579a9ed6fde5`
|
||||
- runtime binary: `d4483926610484ef9c2ad9241aae1469f934d955ebe791f1920e263e0ba85b82`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-01C`: modifier, constraint, Shader Node, Geometry Node and Compositor Node inventory.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the operator generator, checker, inventory, report, manifest, package command and this status
|
||||
page together. Restore `M15-01A` as the queue tail without changing the data-block inventory.
|
||||
40
docs/status/M15-01C.md
Normal file
40
docs/status/M15-01C.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# M15-01C Status
|
||||
|
||||
status: done
|
||||
task: Blender 5.2 modifier, constraint and node inventory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The pinned Blender 5.2 runtime generated deterministic inventories for the 83 modifier types,
|
||||
29 constraint types, and 451 registered Shader, Geometry, and Compositor node types. Node entries
|
||||
include RNA properties sorted by identifier. The inventory is a machine baseline only and does not
|
||||
claim web parity for any family.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-family-inventory` passed after temporary regeneration.
|
||||
- Checker output: `blender-family-inventory-ok modifiers=83 constraints=29 nodes=451 inventory=bb7bbbf64184f326cd17933960800d7d761db6dd3b5f829e322e5ccdb12b8845 next=M15-01D`.
|
||||
- Node family distribution: Shader 99, Geometry 264, Compositor 88.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `54dec9d2e7a0eacf3b17a06168b0c9c73a1358d0545cbf70d8a8579a9ed6fde5`
|
||||
- generator: `2630357cbe6ca7264499621399f1a010d6eb7af8c002283d9d16e65c23955eda`
|
||||
- checker: `0cf9821bb0f6f691ee1eb5a96d77a78932eeb07565352e65a5ed68844f7c0108`
|
||||
- inventory: `bb7bbbf64184f326cd17933960800d7d761db6dd3b5f829e322e5ccdb12b8845`
|
||||
- report: `0ca03907f828feba02df396d3fb9f0cfab791a5be67bd8d768c175a49088bae1`
|
||||
- manifest: `ae6acf4fa173803fcbd9b4c3cff0a561563e7ddb7abf6985844397d14c8f45dc`
|
||||
- runtime binary: `d4483926610484ef9c2ad9241aae1469f934d955ebe791f1920e263e0ba85b82`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-01D`: sequencer strip/effect, physics family, and import/export inventory.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the family generator, checker, inventory, report, manifest, package command and this status
|
||||
page together. Restore `M15-01B` as the queue tail without changing the operator inventory.
|
||||
39
docs/status/M15-01D.md
Normal file
39
docs/status/M15-01D.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# M15-01D Status
|
||||
|
||||
status: done
|
||||
task: Blender 5.2 sequencer, physics and import/export inventory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The pinned Blender 5.2 runtime generated deterministic inventories for 24 sequencer strip/effect
|
||||
types, 65 registered physics RNA data types, and 33 import/export operators. Operator entries retain
|
||||
poll state and sorted RNA properties. This is a machine baseline only; it does not claim web parity
|
||||
for sequencer, physics, or file formats.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-format-inventory` passed after temporary regeneration.
|
||||
- Checker output: `blender-format-inventory-ok strips=24 physics=65 io=33 inventory=d3892fc6126f2e477db8b7bcb2bc5ac7a77db1049f0165350ccc834d3a151394 next=M15-01E`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `ae6acf4fa173803fcbd9b4c3cff0a561563e7ddb7abf6985844397d14c8f45dc`
|
||||
- generator: `618ceb016bf7ab4251d1c8575bd091ea96aecdd423c1d69eea1082b13a734804`
|
||||
- checker: `3c22b24561a77058115e6ae1a58af7f0aaea782fab9416e2ce15221c4b91f8e4`
|
||||
- inventory: `d3892fc6126f2e477db8b7bcb2bc5ac7a77db1049f0165350ccc834d3a151394`
|
||||
- report: `e345452bda9fa1c054974a34895027c080cf055ced2f24330189edbf9c0d5a5d`
|
||||
- manifest: `7e67b065ac9ed8522eac3c4aa185487c6af1892619864f3760bd4efa860ab278`
|
||||
- runtime binary: `d4483926610484ef9c2ad9241aae1469f934d955ebe791f1920e263e0ba85b82`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-01E`: editor, space, region, workspace and keymap inventory.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the format generator, checker, inventory, report, manifest, package command and this status
|
||||
page together. Restore `M15-01C` as the queue tail without changing the family inventory.
|
||||
39
docs/status/M15-01E.md
Normal file
39
docs/status/M15-01E.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# M15-01E Status
|
||||
|
||||
status: done
|
||||
task: Blender 5.2 editor, space, region, workspace and keymap inventory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The pinned Blender 5.2 runtime generated deterministic editor inventories for 19 Area types, 17
|
||||
Region types, 19 Space types, 16 concrete Space RNA classes, and 13 Workspace modes. The initialized
|
||||
factory keyconfig contributes 280 keymaps and 3,228 keymap items, including modal event items with
|
||||
empty operator ids. This is a machine baseline only and does not claim editor or keymap parity.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-editor-inventory` passed after temporary regeneration.
|
||||
- Checker output: `blender-editor-inventory-ok areas=19 regions=17 keymaps=280 items=3228 inventory=6293b5c5bc23c8a73fdde553a5173ac1da25a08c8158af5ec81f4b0f864a5064 next=M15-01F`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `7e67b065ac9ed8522eac3c4aa185487c6af1892619864f3760bd4efa860ab278`
|
||||
- generator: `287c04d7d11068fc28c8aac3a70f12dc6a0631a894c88e4e8d28752e54214274`
|
||||
- checker: `dd4fe1c82ed6f6d9eff9bb1abd017a1066ec7d95f76867d33a4e76112ed7b754`
|
||||
- inventory: `6293b5c5bc23c8a73fdde553a5173ac1da25a08c8158af5ec81f4b0f864a5064`
|
||||
- report: `cc88dd114f215100e28cefc9180e56204bd7694217047e5c6db1e79059966235`
|
||||
- manifest: `c7e5e5d96c1c36072cbba9de6d30a3c99b03ef341fa376152d961896102e341b`
|
||||
- runtime binary: `d4483926610484ef9c2ad9241aae1469f934d955ebe791f1920e263e0ba85b82`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-01F`: same-level inventory for Main, Scene, Mesh, Depsgraph and existing V1 core slices.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the editor generator, checker, inventory, report, manifest, package command and this status
|
||||
page together. Restore `M15-01D` as the queue tail without changing the format inventory.
|
||||
39
docs/status/M15-01F.md
Normal file
39
docs/status/M15-01F.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# M15-01F Status
|
||||
|
||||
status: done
|
||||
task: Blender 5.2 Main/Scene/Mesh/Depsgraph/core inventory
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The pinned Blender 5.2 runtime generated a same-level RNA inventory of 108 core classes: Main 39,
|
||||
Scene 16, Mesh 30, Depsgraph 3, and the existing V1 core slice 20. Each class includes sorted RNA
|
||||
property metadata. This is a machine inventory and explicitly does not map current web coverage to
|
||||
full Blender parity.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-core-inventory` passed after temporary regeneration.
|
||||
- Checker output: `blender-core-inventory-ok classes=108 main=39 scene=16 mesh=30 depsgraph=3 core=20 inventory=4810abd2f91e580da3f7be70f1583f5cf6b2ecc20a13f0ce09b7484c4393e643 next=M15-02A`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `c7e5e5d96c1c36072cbba9de6d30a3c99b03ef341fa376152d961896102e341b`
|
||||
- generator: `64e6c3590b084ec8906e26f46cab1596211c197251e0c7a81de2f5edbc6dcd43`
|
||||
- checker: `ca13efc97cd4709b103268be95f6fe9fa824f64a04f51ab678c78158c44979d7`
|
||||
- inventory: `4810abd2f91e580da3f7be70f1583f5cf6b2ecc20a13f0ce09b7484c4393e643`
|
||||
- report: `8752644f8956c747c8da14afcd04f73e0a5823713ba98ee08c21cf240ff1f140`
|
||||
- manifest: `d49a6196cc5f35907e450b2c547be31962ae759a7db3c473586f9d8254f7878f`
|
||||
- runtime binary: `d4483926610484ef9c2ad9241aae1469f934d955ebe791f1920e263e0ba85b82`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-02A`: map each inventoried item to owner family, implementation class, tests and evidence.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the core generator, checker, inventory, report, manifest, package command and this status page
|
||||
together. Restore `M15-01E` as the queue tail without changing the editor inventory.
|
||||
37
docs/status/M15-02A.md
Normal file
37
docs/status/M15-02A.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# M15-02A Status
|
||||
|
||||
status: done
|
||||
task: Map inventory entries to owner, implementation class, tests and evidence
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
All 6,900 entries from M15-01A through M15-01F now have unique stable IDs and mappings to one of 20
|
||||
owner families, an `INVENTORY_BASELINE` implementation class, the source checker, and the source
|
||||
manifest. Coverage remains `INVENTORIED_ONLY`; the map does not claim functional implementation.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-parity-map` passed deterministic regeneration and artifact checks.
|
||||
- Checker output: `blender-parity-map-ok mapped=6900 families=20 map=f3e757f26e58a4252b6cc2a7f9275428bbe5bf659cc0f0ff6350a147bdf2809c next=M15-02B`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `d49a6196cc5f35907e450b2c547be31962ae759a7db3c473586f9d8254f7878f`
|
||||
- generator: `2430a0eaa408ebba2fe25a1e873989784f8c50fe6dccc6636a07a76e986eb4ca`
|
||||
- checker: `b5f33d8535c0d72c53979f3a222b0004a48d265706adf5c1f9cad6907c80d092`
|
||||
- map: `f3e757f26e58a4252b6cc2a7f9275428bbe5bf659cc0f0ff6350a147bdf2809c`
|
||||
- report: `650a1c37e459bbaf19f20fa7f2be57bcb2ea8dd6ed472726a9ff399d17109132`
|
||||
- manifest: `9f9e954bd3f00fbc2b18802ed8c7cfce469de8cd0f6bc23e49fa2a89ecb0dcc4`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-02B`: detect unmapped, duplicate, summary-only, proxy-only and route-only entries.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the map generator, checker, map, report, manifest, package command and this status page.
|
||||
Restore `M15-01F` as the queue tail without modifying source inventories.
|
||||
37
docs/status/M15-02B.md
Normal file
37
docs/status/M15-02B.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# M15-02B Status
|
||||
|
||||
status: done
|
||||
task: Parity map gap classification audit
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
## Scope
|
||||
|
||||
The map audit checked all 6,900 M15 inventory mappings for missing owner/implementation/test/evidence
|
||||
bindings and duplicate IDs. It classified every `INVENTORY_BASELINE` entry as `summaryOnly`, while
|
||||
unmapped, duplicate, proxy-only and route-only counts remain zero. No parity claim was promoted.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `npm --prefix web run test:blender-gap-audit` passed deterministic regeneration and artifact checks.
|
||||
- Checker output: `blender-gap-audit-ok inventoried=6900 gaps=6900 summaryOnly=6900 next=M15-02C`.
|
||||
- `npm --prefix web run typecheck` and `git diff --check` passed.
|
||||
|
||||
## Artifact Hashes
|
||||
|
||||
- parent manifest: `9f9e954bd3f00fbc2b18802ed8c7cfce469de8cd0f6bc23e49fa2a89ecb0dcc4`
|
||||
- generator: `f0f44767cd6e2ce8aab4eed391b7e11fe1ff566cd52b80632c02085af0ec0f35`
|
||||
- checker: `ebab966ef3edfd5e093d742950352e5f05b7cf04d82ba817812d7afcedccfe98`
|
||||
- audit: `e976ff40d2f3491a5a57ffcdd0d0c0f0586e57d06984e4a4aa05ba1b36800faa`
|
||||
- report: `445fe3426a42579334707000e87eaff29bd895d888faf4fab30f1f4bb2666269`
|
||||
- manifest: `987c780c60cfaa71a728c675ce2c88688b75cb910528c933f84c38fee1360565`
|
||||
|
||||
## Next Task
|
||||
|
||||
`M15-02C`: fail-closed audit for `LOCAL_EXACT` desktop/WASM same-fixture evidence.
|
||||
|
||||
## Rollback
|
||||
|
||||
Remove the gap audit generator, checker, audit, report, manifest, package command and this status
|
||||
page. Restore `M15-02A` as the queue tail without modifying the parity map.
|
||||
16
docs/status/M15-02C.md
Normal file
16
docs/status/M15-02C.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M15-02C Status
|
||||
|
||||
status: done
|
||||
task: LOCAL_EXACT fail-closed evidence audit
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
`npm --prefix web run test:blender-local-exact-audit` passed: applicable 0, blocked 0, notApplicable
|
||||
6,900. No inventory entry was promoted without desktop/WASM same-fixture evidence.
|
||||
|
||||
Artifacts: audit `ab37f60ff9ea4ad99d0f6041de707d92010de81f22a1594dd6dfa4faf6c471cb`, report
|
||||
`0e5ffaf4fa99e0e58f19fe21ae0d2c7fb465ab487fe84924cda06085a9c6f839`, manifest
|
||||
`3ecd9906fc18ea695bbf8ffbfb9516a3e4f5b6dae204ca2afcb9a2c47dc6aa2a`.
|
||||
|
||||
Next: `M15-02D`.
|
||||
16
docs/status/M15-02D.md
Normal file
16
docs/status/M15-02D.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M15-02D Status
|
||||
|
||||
status: done
|
||||
task: LOCAL_EQUIVALENT fail-closed evidence audit
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
`npm --prefix web run test:blender-local-equivalent-audit` passed: applicable 0, blocked 0, notApplicable
|
||||
6,900. No Main/save-reopen parity claim exists in the inventory-only map.
|
||||
|
||||
Artifacts: audit `6ffe0a7f076720b120a7b6a3f9bed3b5d4afbba583388df6ac7fb94df64998a2`, report
|
||||
`8864c360bcdb7c0a191e17ee209a42d762ab980c643e9fecc409d34453c05a9e`, manifest
|
||||
`f9c2a530dc86563d3c5da71dd28ec6a8009a3549112226ee2cc68d8f49e3c8d0`.
|
||||
|
||||
Next: `M15-02E`.
|
||||
16
docs/status/M15-02E.md
Normal file
16
docs/status/M15-02E.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M15-02E Status
|
||||
|
||||
status: done
|
||||
task: SERVER_EXACT fail-closed evidence audit
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
`npm --prefix web run test:blender-server-exact-audit` passed: applicable 0, blocked 0, notApplicable
|
||||
6,900. No server job/cancel/isolation/result-binding claim exists in the inventory-only map.
|
||||
|
||||
Artifacts: audit `2e77b526a90638160ba176bddb84d1028195a588f465475b3a5616854d90368e`, report
|
||||
`0f641bdf72ad4c97882b0ece84384702f9b83fc23c5b7aca8b555d5fd5206c6c`, manifest
|
||||
`95110d84f47865412d6d42f618c4bb2f05240bd456109bf72953cc0a888e1382`.
|
||||
|
||||
Next: `M15-02F`.
|
||||
16
docs/status/M15-02F.md
Normal file
16
docs/status/M15-02F.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M15-02F Status
|
||||
|
||||
status: done
|
||||
task: Unknown-data preservation fail-closed audit
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: false
|
||||
parityStateChange: false
|
||||
|
||||
`npm --prefix web run test:blender-unknown-data-audit` passed: applicable 0, blocked 0, notApplicable
|
||||
6,900. No unknown-data save/reload preservation claim exists in the inventory-only map.
|
||||
|
||||
Artifacts: audit `bec8d2444ceaeae3db9d35ce6621129c90df2f15bf950667be6e85b096a72e4f`, report
|
||||
`e2733f49fa9bd755164519ca9dd46a99b1f41036b8ae4bdb0552487dcec4ab7a`, manifest
|
||||
`ec3fa17832e5fe335b11bd6c12e873abfd4b19273d8e110de860f04b55e7a7e6`.
|
||||
|
||||
Next: `M15-03A`.
|
||||
17
docs/status/M15-03A.md
Normal file
17
docs/status/M15-03A.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# M15-03A Status
|
||||
|
||||
status: done
|
||||
task: One minimal nextTask per gap
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Generated 6,900 unique tasks from the gap audit. The current plan has ten completed tasks, one active
|
||||
pointer (`M16-GAP-00011`) and 6,889 pending tasks. Per-wave counts are M16 2,667, M17 29, M18 451,
|
||||
M19 20, M20 89, M21 3,625, M22 19.
|
||||
`npm --prefix web run test:blender-next-task-plan` passed; plan SHA-256 is
|
||||
`7c4bf7e384da489d0989d6634576373d961b28f8f64f7dabc649daef198fb2a5`.
|
||||
|
||||
为避免执行者加载 6.8 MiB 的 pretty JSON,已生成 `tests/golden/M15-03A/task-index.json` 和
|
||||
`task-catalog.jsonl`。索引绑定上述 plan SHA-256,catalog 每行只保留任务身份字段;上下文工具按
|
||||
offset 读取单条记录并由任务卡提供真实命令。索引校验:`node tools/web/check-task-index.mjs`。
|
||||
|
||||
Next: `M15-03B`.
|
||||
11
docs/status/M15-03B.md
Normal file
11
docs/status/M15-03B.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# M15-03B Status
|
||||
|
||||
status: done
|
||||
task: nextTask specification audit
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
All 6,900 tasks contain fixture, desktop command, Web command, comparator and exit criteria; missing
|
||||
and malformed counts are zero. `npm --prefix web run test:blender-next-task-spec` passed. Report SHA-256:
|
||||
`1ec2155f7bd4b35811d08dc2d66907f3bb3d2f917f69845cb6d3d3073f6a4417`.
|
||||
|
||||
Next: `M15-03C`.
|
||||
11
docs/status/M15-03C.md
Normal file
11
docs/status/M15-03C.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# M15-03C Status
|
||||
|
||||
status: done
|
||||
task: nextTask dependency graph
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
The graph has 6,900 nodes, one active task, zero missing dependencies and zero cycles. `npm
|
||||
--prefix web run test:blender-task-graph` passed. Report SHA-256:
|
||||
`1d00d33f9780a35110fd200503c4f5b27b7b0b32d076ee8e681465efb70c4c0a`.
|
||||
|
||||
Next: `M15-03D`.
|
||||
11
docs/status/M15-03D.md
Normal file
11
docs/status/M15-03D.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# M15-03D Status
|
||||
|
||||
status: done
|
||||
task: inventoried/completed/blocked/uninventoried statistics
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Machine counts are inventoried=6,900, completed=10, blocked=0, uninventoried=0. `npm --prefix web run
|
||||
test:blender-task-stats` passed. Report SHA-256:
|
||||
`fbf3e68a8cb40a309d0ca931ab77dc30b8e743ce90e83ab93e8ec2f1013662cf`.
|
||||
|
||||
Next: `M15-03E`.
|
||||
12
docs/status/M15-03E.md
Normal file
12
docs/status/M15-03E.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# M15-03E Status
|
||||
|
||||
status: blocked
|
||||
task: owner family zero-gap closure gate
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
The fail-closed closure gate reports `BLOCKED`: 20 owner families still have 6,890 remaining tasks.
|
||||
It preserves the single active pointer `M16-GAP-00011` and does not infer completion from release or
|
||||
inventory evidence. `npm --prefix web run test:blender-zero-gap-gate` passed the blocked-state contract.
|
||||
Report SHA-256: `381ea77d9b884b1bdab58bb60df001a26287db80dd9380edb6ae4d64a0a3d969`.
|
||||
|
||||
Next active task: `M16-GAP-00011`.
|
||||
16
docs/status/M16-GAP-00001.md
Normal file
16
docs/status/M16-GAP-00001.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M16-GAP-00001 Status
|
||||
|
||||
status: done
|
||||
task: Action data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: true
|
||||
parityStateChange: true
|
||||
|
||||
The generated Action fixture was read by Blender 5.2 desktop and the full-Main WASM. Both observed
|
||||
`action:AnimatedObjectAction:object:AnimatedObject` with three location channels and two keyframes per
|
||||
channel. Desktop and WASM save/reopen checks were exact; the active pointer advanced to `M16-GAP-00002`.
|
||||
|
||||
Evidence: `npm --prefix web run test:generated-gap -- --task M16-GAP-00001` passed with
|
||||
`desktop=exact saveReopen=exact`.
|
||||
|
||||
Next task: `M16-GAP-00002` (Armature data-block).
|
||||
16
docs/status/M16-GAP-00002.md
Normal file
16
docs/status/M16-GAP-00002.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M16-GAP-00002 Status
|
||||
|
||||
status: done
|
||||
task: Armature data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: true
|
||||
parityStateChange: true
|
||||
|
||||
The generated Armature fixture was read by Blender 5.2 desktop and full-Main WASM. Both observed
|
||||
`armature:RiggedArmature` with Root and Tip bones, Tip parented to Root, and mesh skin-weight linkage.
|
||||
Desktop and WASM save/reopen checks were exact. The active pointer advanced to `M16-GAP-00003`.
|
||||
|
||||
Evidence: `npm --prefix web run test:generated-gap -- --task M16-GAP-00002` passed with
|
||||
`bones=2 desktop=exact saveReopen=exact`.
|
||||
|
||||
Next task: `M16-GAP-00003` (Brush data-block).
|
||||
16
docs/status/M16-GAP-00003.md
Normal file
16
docs/status/M16-GAP-00003.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# M16-GAP-00003 Status
|
||||
|
||||
status: done
|
||||
task: Brush data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
enablingTask: true
|
||||
parityStateChange: true
|
||||
|
||||
Added bounded `BrushIR` fields to the native Main reader and optional SceneIR parser field. A real
|
||||
Blender 5.2 Brush fixture reports `WebGapBrush` size 42, alpha 0.65, hardness 0.8, spacing 17 and
|
||||
jitter 0.2. Full-Main WASM and desktop match exactly, including save/reopen.
|
||||
|
||||
Evidence: `npm --prefix web run test:generated-gap -- --task M16-GAP-00003` passed with
|
||||
`brush=brush:WebGapBrush size=42 desktop=exact saveReopen=exact`.
|
||||
|
||||
Next task: `M16-GAP-00004` (Camera data-block).
|
||||
10
docs/status/M16-GAP-00004.md
Normal file
10
docs/status/M16-GAP-00004.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# M16-GAP-00004 Status
|
||||
|
||||
status: done
|
||||
task: Camera data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Blender desktop and full-Main WASM read the same `camera:WebGapCamera` fixture with perspective
|
||||
projection, 52 mm lens, 0.1 near plane and 2500 far plane. Save/reopen was exact on both paths.
|
||||
|
||||
Next task: `M16-GAP-00005` (Collection data-block).
|
||||
8
docs/status/M16-GAP-00005.md
Normal file
8
docs/status/M16-GAP-00005.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# M16-GAP-00005 Status
|
||||
|
||||
status: done
|
||||
task: Collection data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Desktop and WASM read nested `WebGapCollection` -> `WebGapChild` hierarchy with the collection object
|
||||
link intact. Save/reopen matched exactly. Next task: `M16-GAP-00006` (Curve data-block).
|
||||
10
docs/status/M16-GAP-00006.md
Normal file
10
docs/status/M16-GAP-00006.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# M16-GAP-00006 Status
|
||||
|
||||
status: done
|
||||
task: Curve data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Desktop and full-Main WASM read the same Bezier Curve fixture: one spline, three points, available
|
||||
geometry and exact spline offsets. Save/reopen matched the complete non-mesh data record.
|
||||
|
||||
Next task: `M16-GAP-00007` (Curves data-block).
|
||||
10
docs/status/M16-GAP-00007.md
Normal file
10
docs/status/M16-GAP-00007.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# M16-GAP-00007 Status
|
||||
|
||||
status: done
|
||||
task: Curves data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Desktop and full-Main WASM read the converted Curves data-block with available geometry, four points
|
||||
and at least one spline. Save/reopen matched the complete nonMeshData record.
|
||||
|
||||
Next task: `M16-GAP-00008` (FreestyleLineStyle data-block).
|
||||
11
docs/status/M16-GAP-00008.md
Normal file
11
docs/status/M16-GAP-00008.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# M16-GAP-00008 Status
|
||||
|
||||
status: done
|
||||
task: FreestyleLineStyle data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Added bounded optional `lineStyles` SceneIR data with name, color, alpha, thickness, chaining/caps,
|
||||
dashed state and modifier counts. Desktop and full-Main WASM matched the real style fixture and save/
|
||||
reopen was exact. This does not claim Freestyle stroke rendering parity.
|
||||
|
||||
Next task: `M16-GAP-00009` (GreasePencil data-block).
|
||||
10
docs/status/M16-GAP-00009.md
Normal file
10
docs/status/M16-GAP-00009.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# M16-GAP-00009 Status
|
||||
|
||||
status: done
|
||||
task: GreasePencil data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
Reused the existing real Grease Pencil Main fixture. Blender desktop and full-Main WASM both observed
|
||||
GreasePencilData layers/frames, and save/reopen matched exactly.
|
||||
|
||||
Next task: `M16-GAP-00010` (Lattice data-block).
|
||||
23
docs/status/M16-GAP-00010.md
Normal file
23
docs/status/M16-GAP-00010.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# M16-GAP-00010 Status
|
||||
|
||||
status: done
|
||||
task: Lattice data-block LOCAL_EXACT slice
|
||||
updated: 2026-08-19 America/New_York
|
||||
|
||||
scope: Blender 5.2 Lattice data-block dimensions, interpolation, outside flag, vertex group, point deformation, weight and selection.
|
||||
|
||||
evidence:
|
||||
|
||||
- Desktop fixture generated by `tools/web/generated/M16-GAP-00010.py`; Blender 5.2 opened, saved to a fresh file, reopened in a new process and matched exactly.
|
||||
- WASM/Main opened the same fixture, produced 3x2x2 / 12-point `lattice:WebGapLattice`, and matched the desktop point report exactly.
|
||||
- WASM save/reopen snapshot matched the pre-save snapshot exactly.
|
||||
- `node tools/web/check-generated-gap.mjs --task M16-GAP-00010` exited 0.
|
||||
- `cmake --build build_web_blender6 --target web_engine -- -j2` exited 0 after `source tools/web/emscripten-env.sh`; generated runtime assets were installed and hash-bound.
|
||||
|
||||
artifacts: `tests/golden/M16-GAP-00010/manifest.json` contains SHA-256 for the parent manifest, fixture, generator, desktop checker, Web checker, reader, protocol, WASM/JS runtime and both reports.
|
||||
|
||||
knownRisk: This closes one `datablock:Lattice` slice only. Lattice edit operators, lattice modifier evaluation, shape keys, vertex-group weights and all other 6,890 generated gaps remain separate tasks and are not implied complete.
|
||||
|
||||
rollback: remove this task's fixture, checker, reports, manifest and runtime/protocol changes; restore parent `M16-GAP-00009` as the queue tail without editing its successful evidence.
|
||||
|
||||
nextTask: `M16-GAP-00011`
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user