From 3c9ac9992586f4ea99f1e04ac21e7aed0fb4a0f8 Mon Sep 17 00:00:00 2001 From: mes123456 Date: Thu, 3 Sep 2026 11:24:08 +0800 Subject: [PATCH] chore(web): continuous handoff WBV2-P1149-001 --- docs/EXECUTION_QUEUE.md | 6 +- docs/status/WBV2-P1149-001.md | 8 + docs/tasks/WBV2-P1149-001.md | 45 + nextTask.md | 10 +- .../modifier_reader_batch_four_scene.blend | Bin 0 -> 98605 bytes tests/golden/WBV2-P1149-000/manifest.json | 42 + .../WBV2-P1149-000/module-execution-plan.json | 6173 +++++++++++++++++ tests/golden/WBV2-P1149-001/manifest.json | 111 + .../modifier-reader-batch-production.json | 212 + .../golden/WBV2-P1149-001/module-receipt.json | 128 + tests/golden/WBV2-P1149-001/module-run.log | 49 + tests/golden/WBV2-P1149-001/task-context.json | 187 + tests/golden/WBV2/task-catalog.jsonl | 2 + tests/golden/WBV2/task-index.json | 2 +- 14 files changed, 6966 insertions(+), 9 deletions(-) create mode 100644 docs/status/WBV2-P1149-001.md create mode 100644 docs/tasks/WBV2-P1149-001.md create mode 100644 tests/files/web/modifier_reader_batch_four_scene.blend create mode 100644 tests/golden/WBV2-P1149-000/manifest.json create mode 100644 tests/golden/WBV2-P1149-000/module-execution-plan.json create mode 100644 tests/golden/WBV2-P1149-001/manifest.json create mode 100644 tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json create mode 100644 tests/golden/WBV2-P1149-001/module-receipt.json create mode 100644 tests/golden/WBV2-P1149-001/module-run.log create mode 100644 tests/golden/WBV2-P1149-001/task-context.json diff --git a/docs/EXECUTION_QUEUE.md b/docs/EXECUTION_QUEUE.md index bec5274b9..40c1d0e4d 100644 --- a/docs/EXECUTION_QUEUE.md +++ b/docs/EXECUTION_QUEUE.md @@ -15,9 +15,9 @@ | 字段 | 值 | | --- | --- | | 里程碑 | WBV2 capability workflow | -| 当前任务 | `WBV2-P1148-001` | -| parent manifest | `tests/golden/WBV2-P1148-000/manifest.json` | -| 任务卡 | [`tasks/WBV2-P1148-001.md`](tasks/WBV2-P1148-001.md) | +| 当前任务 | `WBV2-P1149-001` | +| parent manifest | `tests/golden/WBV2-P1149-000/manifest.json` | +| 任务卡 | [`tasks/WBV2-P1149-001.md`](tasks/WBV2-P1149-001.md) | | 专项验收 | `node tools/web/check-execution-control-plane.mjs` | | legacy coverage checkpoint | `M16-GAP-00282` | | legacy coverage parent | `tests/golden/M16-GAP-00281/manifest.json` | diff --git a/docs/status/WBV2-P1149-001.md b/docs/status/WBV2-P1149-001.md new file mode 100644 index 000000000..d7ee173b0 --- /dev/null +++ b/docs/status/WBV2-P1149-001.md @@ -0,0 +1,8 @@ +# WBV2-P1149-001 status + +- task: `WBV2-P1149-001`; module: `MODIFIER_READER_BATCH_FOUR`; status: `done` +- source hashes stable: `true`; commands passed: `4` +- positive Main mutation, negative no-mutation, recovery and Chromium gates are recorded in the module receipt +- dynamic source inventory: `3745` units; verified `377`; unverified `3368`; planning estimate `5200` (non-binding) +- historical 6900-entry inventory remains read-only; full-family parity: `false` +- nextTask: `NONE` diff --git a/docs/tasks/WBV2-P1149-001.md b/docs/tasks/WBV2-P1149-001.md new file mode 100644 index 000000000..0ce2c1317 --- /dev/null +++ b/docs/tasks/WBV2-P1149-001.md @@ -0,0 +1,45 @@ +# WBV2-P1149-001: verify modifier reader batch four + +- task: WBV2-P1149-001 +- parent: WBV2-P1149-000 +- status: in_progress +- gap: capability:MODIFIER_READER_BATCH_FOUR +- ownerFamily: MODIFIER +- targetImplementationClass: LOCAL_EXACT +- Implementation entrypoint: `node tools/web/run-wbv2-module-task.mjs --task WBV2-P1149-001 --write` + +## 目标 + +以一个共享 Blender Main reader、WASM build、Worker 路由和 Chromium receipt 批量验证 MOD_uvproject, MOD_uvwarp, MOD_volume_displace, MOD_volume_to_mesh 的真实 modifier/RNA 元数据。 + +## 输入与范围 + +- Blender modifier sources: `blender-5.2.0/source/blender/modifiers/intern/` +- RNA source: `blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc` +- Native reader: `blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp` +- Fixture: `tests/files/web/modifier_reader_batch_four_scene.blend` +- Chromium test: `web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts` +- Selected modifier units: `modifier-source:MOD_uvproject`, `modifier-source:MOD_uvwarp`, `modifier-source:MOD_volume_displace`, `modifier-source:MOD_volume_to_mesh` +- Selected RNA units: `rna-struct:UVProjectModifier`, `rna-struct:UVWarpModifier`, `rna-struct:VolumeDisplaceModifier`, `rna-struct:VolumeToMeshModifier` + +## 验收 + +- one shared Main/WASM/Worker/Chromium chain observes every selected type +- malformed input is rejected without Main mutation +- save/reopen and deterministic second read are exact +- only Chromium is used; JS simulation and per-API duplicate workers are forbidden +- each selected source unit receives an explicit hash-bound coverage binding +- `node tools/web/check-task-context.mjs --task WBV2-P1149-001 --write` + +## 失败边界 + +- any missing source, unsupported type, hash drift, malformed data or non-exact recovery keeps the batch `in_progress`/`blocked` +- partial batch success never claims the omitted family; historical inventory remains read-only + +## 交付与回滚 + +- Receipt: `tests/golden/WBV2-P1149-001/module-receipt.json` +- Aggregate production evidence: `tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json` +- Manifest: `tests/golden/WBV2-P1149-001/manifest.json` +- Status: `docs/status/WBV2-P1149-001.md` +- Rollback: restore WBV2-P1149-000 as queue parent without rewriting prior evidence. diff --git a/nextTask.md b/nextTask.md index bc6b309f0..443304580 100644 --- a/nextTask.md +++ b/nextTask.md @@ -467,12 +467,12 @@ Recorded: 2026-08-29 Asia/Shanghai | Field | Value | | --- | --- | -| Current task when this file was written | `WBV2-P1148-001` | -| Current task state | `in_progress` | -| Parent manifest | `tests/golden/WBV2-P1148-000/manifest.json` | -| Current task card | `docs/tasks/WBV2-P1148-001.md` | +| Current task when this file was written | `WBV2-P1149-001` | +| Current task state | `done` | +| Parent manifest | `tests/golden/WBV2-P1149-001/manifest.json` | +| Current task card | `docs/tasks/WBV2-P1149-001.md` | | Current task-context nextTask | `NONE` | -| Focused command | `node tools/web/run-wbv2-module-task.mjs --task WBV2-P1148-001 --write` | +| Focused command | `node tools/web/check-wbv2-module-execution.mjs` | The snapshot is informational and may become stale. On every resume, the queue, parent manifest, and fresh `print-task-context` output win. Never infer a task diff --git a/tests/files/web/modifier_reader_batch_four_scene.blend b/tests/files/web/modifier_reader_batch_four_scene.blend new file mode 100644 index 0000000000000000000000000000000000000000..ce66ee638a107cd21e4764c5238acdc149f42ae4 GIT binary patch literal 98605 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 cn{S}emSmv?{qI=XZ3hS zBPL1bpuP`2ROE@9HF}{hxwml-x%~B&+0jVSU_u~+PDA6t@h0(((Ro-))_a#Lrs%!}k{*Gypc2+udNwv)bqHJWRJ4c4oH! z_Ldd@I!t^)s*R=>_f!9#2~V8aa2!xcOf?O0ulN9ZZG$zl)$RPmrp4qX|6OX^6EXmkS-}j zf3vTA_!-oHywh%x)8O3_p{qR3-Ujh3`D(jDJ_`Fx13$piIZZgPEKKvD$($NhxZWTM zf1Qt8dn$&s%?y*2i=_|+{txq>oPYk)B}=)XF+#WF!5{SC>SIOP@)BXzxoX+_?t297 zn*Z`{q`U!S;OsM3J*Dl9v!qjzJiFIc1M+FUhCI(y6}Ps2u&c|6>BzOR75`Tt(} zxtQILROd90Gr;beA)F9Hnr@V?Mk`7 zQ)gu60e8td4RGO#%)M-*9ix*f`Ssi>+p=}icsBQX0k}rk`+Ks7|884Z%yRoi#JfKH z!xgP39`nQl4RVtb*w~ zIG9s|lbk1iNp)?3Z3L~nJU=*`n4yc0i9AND6`xf6CEIDguIyy^8aqz-wE@7~fe+uq zpREi%?B~Xid{jB5a zp?`;OD)b*sgs;%=hdM0vU9dSh>q+P>>U?OoNvWeM$+t0O;uy1hE8$)}eZ%wHkhrWbwZ(Jv0W@>t8TQ`` z^8O-!6=%s*s^iVVzU19`_V9r1qCAsef;#MKm;bI%^**Qgn?JrLDC+lj%b&l~Fueso z9YctcSDB1FgI|eSs%O%JmH#wjJ1;3FU8?H8Jyx|26CFRjmLz{JuKBaIxBZ;DK>elQ zqJD=+;0`O*pXS|dp(U2^J{CVR#Jvd-G=_A|$Ey4_`&U0vsY}W4-mq!L->wIqWW1rq z`imt>OHp+>euhIynPnRepzP8J!waeu&Tob9 zTklNPxvD+fJVjVtzT#VHWb6QD(O-l70iqlAHBM+UQ&JcXUgMqylG*Ti(j5hi!P@YbU5kX z3iyd7x~JH@NM(gH?MbZ30tOOkB?kwAaQp$RO_v>kIfJK=yZ;?b+>uAM& zQeXYADOaA`fU)?w4Wf&t{Ug6x=*}IA)c+QPD{KzHKjDU12#~B7vMTvGO+1^?03&`q zg7*Bs{O59R@1=NmAAPux{T%T#B4pD@TKchuZ{tbK`J<1Ne*7{j5xdgDkE7OIGkzuU z26+}?ZBG(-G9B-?*W6I)uGJx{MY@Kd*c0aYD^(z8#}7ngJyYTaE* z?|2L=Cv=#|k{LPvqVGSTJbE9l|L3P^t;+(vn`Too z6+Lg>`e7yL`N*U2lD!PfciX~4N)8}>q@RQRWE435Jxl%sNhTs=Y{Vom_;0CA!}z{@ z0?quE=TGG?j*E4aW;$8o0{jU9fFNFS?68G!Q`vw>(4Suhrt1oH5 zpy%@*{{WG%crdR{WxNts9OH>qnvDtqgoBwiR+MB}^-uk06Z>H%Azk~C8ONR)djl@j z!vfeF$!E1AfB9_9i+@7Dmw`yhieupo;eFv9n8RA3!eW_OqR5UN5B67&ApP(wrDT6w+pY>{rh$r_eyHlL@Ww zc-~2^)JF4kDn9;pAt%?Dv(`x1ZJE0dzo+lCO3I3NF+S8Dox5wMy~V{g^Ws6s>Ba9) z#B=2vYB3!8>fnyAYy_GsO8v{4v*Na;B2YW!jTIiZD2%HJW6xjbpXbGrZ&oZH?jK@v z6O_B6t{Qk0Pud2*{JW=a^miO5y_>i}KpelyW&YAB>eG6Ux^n;5tHsUWghxHwl;>YB zzT3LvK=XKr(m*;=N}k+b2Se3 z_S>9uXi?@UCV^*el=4rWP4}+`tAAw{cqDztMnCcyD|?5)=kXA^^DnnnzV&~T-_!pT z^3V4R$J?NOa|c=b5Dq_S*+>QRQNTBwBr`89hqTKNRS!q1RkSCk{=K6bgaiGYxV$J+3bmx*KD2V$o zF|wIi0ws-~v3&<%*%@x8s^&$`Kv%U(u9tE7U|s zRP6qJyvj;&WLFb!KrLT@Oy82+8glMAgFcrN4I}-lodNCi=RN1{Zj<773jr8ulZMOt5kIVw;T7zlG|JLhhj9!1$MbEa1?*ClfrJ_tf#m< zJK+1}7;4}+w$n%TY!dP!TO{n=)8CyA7k0OIukLj{vMsATXz8}Fyv$zAQ}`@-PyQf~ zZ{lM9#b3%@$;0tYO4H9Ljsce)f}O&j*08JKQ@OUq`uuk`zdxQ7+9(x3-u`&iO#U%J zT_lsaf7UG`DZlxEbYe32e*ir|!oOC*>J&qF)hq&~%|XyS(aV$eOXIiJPlB@C2yliL z1-tdcE8YIWzeMkwjl=79g>`7^2!MX5k^XF~_e6em+7pU%wQL@Yr#Oz!UG(p0aT)Sr zeb1Bsd5tplrssAab@o}&cd7p~&a>7%93{^Hn;yfy55iO%Ec;J zC-31#hR0t!<^PoJT~_7_=Fx6x_xgE5<9-(JfanXI@nLx|7|PMb%z)_1I5Cpf8R8Rl z6sA8drcUe3D}>o%eyZ#=YELX5?#8Bhr^}R%?;yLqjdRfwM|4QGWqTnVODUv>U>tru zpHx@iO%ECx~I3kT~LcLUKnXF>dfh~DEsS>fw|=*=s%#f$qV<~YvU#{DN+Z9d13 zf|tYBG4I;p`W59-W(y&g^>z3Dh34)_hiMc;;x;p;_n1{4&y4kj0eF!kWh}q*AhrVH zig0Fur3^e&;PEdJIv2Cxh~9RqSB8;0IrceBx1Y%6=a2&WpwQd(==~yYW}iwS zBcA6^%cYfCCmEKh$6Zui6O`mXw%koJ{08`ZLc-yI%>GB9Q(^EM7Xb?_A6MVKiaZ8i%-J0E(do;9DmO=b{0;lu+5j_#>D&J! z4kPKOGRPCmXHR$&LEbUIJ+nmCHl*Kq6|2sNTHip90sO!@nRRh+_>k-(BHUBCa zc!F?J3P04~EB08Df#2xc@E613b<_D74VnHxUZZ;i7=D6YN_|Gp(--yZl{dj5cCZp_ zg0a)i&0}RQdhGeS&haWOW0e+xQwh8i&Bz{sddV}4BOW-bdBF&o5!06_(i!{V#;Ao z7qdldgw1paAR7ytU4n5B04aO|Jbs^7I*l?9!PK++xRN^uQj{JsM*eR0e~rhOp>h?h zy)_Dan)&O!kK4JBA)tH6_R?o&35?oOvrFt|6!X(`?2y#{}cc}4umxTT34L-Vybn`cEaz^{1I)(|R zerDybQ$+^HthAfB#xQfuM(}%$<_+)d?htB^(D%~VU8zB7 zGOX?_X(hw7sH`LPy$CA3!k~Me^M)1$KC@<5-n~G!@!;W#9v30?E$Z03k`D}-WEL`G zNcMd{mAuvs=9%8BqU&}#4+=gv@do$$vKzbSa1`vnXsiB~Z~_h-+}w)k!OiP`iQD3G z7Yg=MvNAt;;H~6~!9GU9bEWJXd)JERyBqji6cf|xS<@GZhF5yhZvcv-<0!`JUVKQ- zpHELtMtVo4tl|49^1v@uC!{_FLKl`i^In&o0@b1aP zKdlMB`~W$n#*DZDlZ&_yK%97oPZ`ujyL1))Seaq188JK1mnC~aD}#8xRXgggoE5?gBSy&>CM9Y6IY8pSoi4Na|m@brgvxwtY0&{6z z2UCK3x^nx|pTiJy4+uyMnBlDV%)EUvPUke)Xnl@yf0o!qA*0%lZV}Z_)4$N&KdP;` z06PbLA3OEY&gG4j;TTwiM+Cip0n4_y0m=>>?j~4f$xJkFsk86?UbRMgHnKY^>Q2}w#OiZC>pdK) z!O^DYCLr|O2mi->xEWY0l)GjQ3sMV`Nii=xH&oV z3q5o`B(5XWH5NwnRj7XoekUc&#{+%Jv&)@CjR4>gC5eReTA74v)^90 z@S&!F>bbg_R)caLAT=<@53j3>H-l-JD4CIyc2N_5a<55|{VrpqXV|@;Ay54}b9K0z zwSJPr6t&ps91c;})X8TJDVNEIRL<%EAA8r-`LBA0LQfhQh&8dR$9w%v^k_hz=roIP z9E5tP&kA{6V2O*H_rG{f$^U;`_7MpZ2yJrn|6T}s-=lII$rW(NmGnatvk)M=buAt# zvg+-azo3|EQHW-3E3e+w z+;M4-*OYq*%6*#N;hhzkH#k42bbNM4)GJ%c-7>?s7>x_3>r?cR`ya8=SK%lZ7esgMdH8f ze=gdwQKmHmBoMsL>|aiGLwYDH`B(`%PH-%dv#+8$pO@u$`d9d8YTmimtZnP;&arWy z*wV3kJ-syw=of{~GT(4*h$p(Gc$YzN9uFlc9QmO|j@ohw^oZm4k;dRVn)(+Tpz|

4KZ&bT>PoNL=-oV5jrT@OUIb*wso0|W z>4^Ocl=f+e#6pOYLENLMh+h+&g`DesGf;sX~&Uv^n|D9i`gnHgg z=?Ma>b`Ia-@w`d>K- za()giN=JYA=q%N}YxuzRFi^HCTIy4N%Gs|Jd6u$PN}qNO{>#p+LHSrr zAFo1p+VXy;J2u3=dATh(6XS754H;AvcX>$tU!EDgAF+1VZDzRUp&|5tEB(zVdW8h^ zk03WbB!70y5F!?8n}(Kn=5DW?8v z%B0Jl{N?92kcBZUYr_joP$Q`s7%vOlVv8b4?wfQHX3H9-7xd#zd}GmzmySmz215yC zy@r?hyW(xX|HkE#O&D?1w~8HVFP8)S=r206MqxcJ|LQjrw4LB7vBugwkWqzJFkm_Y9DV6THB{!8b&Mt$!-Jy8D5 z5K`B8$SYH~`Rd%|DCM+bqXqL2Bw1>R|KQ)DI;FR66H>b57ZzsMmz$DM!>oM~gW}`Z z0CYB~*H0ijFJ8$+o7nCweLK_hR%l*j*zZNZYcrnn?#VM_y8hG1q>YDpUX@m#N~ZlG ztlOWS%XVb(ddW7zOh44pus_wA@`~><9ve^biB25=6?`d&-%zo}|G7;G~kff_6m z9e=%NFWd8VIe?-tf+(uf$%ES_jkn7)G8-8Q*atqyHcVP$+&4m~8v}z9>vk^%tj(46 zLUHY&cqL|>vSkNKM=AC1Qu>v#EG>f-Kkh%SfHDI!Cob3Cxnmg{5dJ0X&zPUNf^I?) zRr64^?rC6%EoEaH_?hm~rP5dq0Liqi4 zi>m&n4zy{M!^i!uIrEJ!-KjN;iW~)hoP(vFz>P4!Z}~I82IzmxTi%TXbE5P`|jY+E?Y^inVi5xu<5~aZYH-WwOaVmm`Vnz80lrR1E&}+=P(b z5H=@L6y<*ayKoQ;CkLe`V#C};wu3qUirKrG?@H@1s#L?F2*jgaK5 zf&V{DY;v_CF{T0-#_-3;e~z?0hDxt zF`l|2t%G^TpI*>(HC`7J-?vUwbG6D4Nb(P*$?^49nm6m^$JdBPP8GImaf!#I$W0{( zqT?e6zy8&azXF#kj*!gVx2TQ^FMAkE#4sQ5HDe`042C)2>&hqb_oXj~*TYn&%+%vj zX(f{>_*(Rg!gVx^bh9ZkK>)vql6IAE{?-qK)vR##>#{WEXiVJ9I6?@nuTZX)__U4d zx%V(o%1GhIxQ@@AJ)gjX6;^ZU*iq`jlObcKf!x?M_aR56CSICCY_1};)^3!(b~PtP z1gY^7gWyTJL@uW#w43!eSdF4~3GLR~Ll3P7x7F+2K^>@rmW|SuR-4%aA>kKhV|wk&W%E=aIwGcfg3NuM5lug7Og>RD&A#;6%_D?VWR|s?hnXs zPEPx}Cy(vqo3^`j7VBVz?>a|`GuK$&*bah~7cZr)O) z;Dw&{+JG6_PRNE*&WZnBk6B~FXb>N()Fj+xE9L~Jgo;xMPGsPMoe zB6EvF4Y0mMgX9I&psqqU&@tKbWjD}XB6hOVXx!r$w>Zv}BgxjcvA>TjDY1(1fp|B=pP307i}& z$R4oZL}J&(5$OVb?r@j?b-=1z#yd1SJ(S2DlsGh8H#uF zvX>a^3;n>CluIP7u`RFz!)AVj6XmQI5hq3CBw$r#Zg1}{Sngi&Q&yIFIXp*xM@z-zt$}>4E!2a66q`Q$0 z!}c>}<;Js)=w_md;gN6GF%9^AwvMAx>+?(SK0UQtz{^unXdD#|&;X>YWhAO8cm%Vp zDAlDH6beFQpSF1JT$Z_}`2sVSJ2*TqvWvfk}k}$!rC7lM)FW(f`Hf9K^P;i(t zAXeG;HVZE77;FP zF2@#djzFX*3cgWI*KF_C;&mRPAmX@%I8QUGkv)MdZX#kDxWUT?9S{?-TzTVGZu-eKRqVGIN^FPDUEoPw)EzCADSBP5!B93+ zYQehG71)l{_@>kWxbcU(NqDxA+~yd+v?zf$H=W$Ahn^Jn$BHfnghs>=CYlI9o$*G6 z3f19}1}VtgwX9DS4hI3|xK@N~;klv3^!jtw2d*X4*9Pr}STx2gkZy!+I;3mXO72e- zX=rD^wu)2J1>yc0zsF%In#g-d*_eI5f(1`YgMz1xdEo$-CjFKq7a?}|P@(zN=WtA7 z1_yml1N_f(H)F+TF?nMsXKQCf0GV&yVa+?KZu1s_=4plqyvszybPC}PeW z8;?*y-FG~|y$u0A^(^qJm>Uc?FEzc>;gLCok^B8}h2+4yFerG9GA{P6xq^#Q)f}y%oBsQIv+^m_w-! zm93Uh_AwU~`cT>z3i@B*3o)C+$3SEpi{C<+fyCOr@AAbIoI;5*D&2lHJShBaGMOd3FUWHg5uNW@viRn%9` zmBo#05ee)^Ch=Su-^vbVy4xdw=*tPagO^_3?Rf1)Fgqo)M5))n5-~=AJCrRFG=o)d z5XulA`*O6U31@#(nGMu~1=(J!Swm=YIz~FglPQ+h2ez&ji!YQ&R~hTDbee4>n#o{5 z1Fd^uaU_9PYCPwMtLAGZAY#V6@_wQm&M?$JZcG9bYIhCpunZdAFV8Ce=vs|>UeL80rGEb+@Pb3F?q9kc4jr*k>y^qA9=Z)fh zveWi|1 zkhPpb0%I#*pwnq7ftRBvioMH_9(yxmn32t@r9}reAyV};d%qO}%@rEv;Xqxpk2J2LyP8lVq7%c6%BlLF3zkTqJj)75g8z zZ0^%ZHL>+eJR<1P*SNG|&Cl^b!~x^?r+eK9_A)`*EAlA{(4lKwte~t$*Jgq)mw(yKy?;3Ss?mRPEL=2gr)@!sxfcW3;42y^`CZy%QuEjs76nK z35c(Azz4j((fcR^F#wi+26epJW8`a(^jCK)tcvfs$`wp_DYOAhbJ>POMw$k(7oQnI9xeZOU*4OQTaLm11|IyBWtPzx{E|4r-O2bxy|5t(pZegTz zW;wby5DO_1fuNh2fZ^BF3dHOQ4Xwu#z!mB%g}P&T-cI&m7hXb_OI)ML?mu5qA{s?A z98L!v74yE_QExq0NPJ&rk&3)UbR=SjX=ju3`ckcOL`lT{B(Z&7R<73Md9P%2&Ie3T1ID)g9j|$n~iJcLva2x;B~+sPAC(VP7bE(2CRmTKh`t? zG7_$CGGjQ{S2@&55Z)|n#HbmOd>IgXB5bKUwta)-CD+z^hcQeHoLm#?0`Ysy-P9<% zn|H(v5=_6qe`c+>H>nwA5V=GVW7!8JOswUu*}Odpb^3yI^n06M8Q6RdmR|o+G1%7Z z{BR?}r#x@fC=9w1XOuYPTDUWbh;a}k!~L<=$ky3CS-_8o*lR8^&ImS{EV?4K9wu2x7*=QtP}|2q6tyASz=5n|YDXGk%@>|x_HRWw^ApN?*+mR)_6eM&M{A}2K z)extWtne%DK*h~0di&v-HnaNAzk0-IXYbvgvLs zR;(uGKcjQ6X)ApWhhocbw^|H4HX4*sadcGr7($1A5GIZ6=;Y}N2wAHy>ZL5OKTJ~} zI@c>jZyqAAlCOpIdrTq#?f(q){OGW6nSoJI&rSynk}D>8GEd_q<}S$0)Z~rQNEA*| z$sfE0;8^RGy<5A{&v&4L2lK#QQOe_wT2p!>6WI^8`1%==#&{E)jJWexwN zYYl453=l3;RPWW4vh*ZAk6B;DiczACKkF=9ofF2GZT!R@;7wO8(1zHg*miI0&)z*k zP436jI|G|DU(pp(FBMM1T`;OSI2aA#rRXWkv$ZiM0?h#~u?Q*SxzO}!1&th%e3&oM z^oId!F^}D9i!NIyR3GE;4IVhsvZcKtRKVpD9>t@#l6Yd<{}3}%yC)yHRTW;g@STDO zghVG+omA&ZNL8WXBl8F2C{YX{LOjac_^)*o&SOHu8*mEr-}R#H_&nFRP6G4ht8WH@ znX?MiC8dTR0GhnCy*DTp4u=4xvr8_S*>M$1nx(r}1<3^o7!`v2r^jMRj>_QpM1k2w z*1-k=$TG_pxN`7qo2;OLEjJ&Cwi3;H*AP^b~vFa^I-Vw%EVtK0#kJ07{iJGK61-528#FlT$d`t$Kz{dbwJ+``C1FJu-r#a*l*2-g(?LykYg=Sj86k48W6fG^A1333YGLH(f&c_JJy+aWk$#t;ssXCbqQD$ zuWag$0d%sQ=mY_XJL))P9QEmdC@3*cKl8x%c#_-?hhm+%1h;i?oFx)ac#@vHf9=Gg zQ{?k_0c!G2K=l)NFa)AN1>Gem$tvDG$whncS#J)x+|-lPK2jPmac z0#v5(#Y*nqvM^xyTq)-2fR6b+@-q6fuIbjcdXhoFPE}lqi7iVfbO=BZzj@7Bqkb+O zy>TlGo38@zTFq9Wh)s)VQyxc!$5HBzFqrzpw1@)L5-A7kO;d84WYby^;K4~DbZ)>r z7+-*7k4y_L1J6&q!=M9bfG3d)G@ve(5~SSP80>=3otzeHXpQa2l z+^wTbF6@4T_KMU6#+3aO$LQOg9fjpuC_a`SLVL7{PUVijBaJM&yae_QVT)j#24t2d z++ko2@hRzxYWQ+e)ggTl;6osN5AS$s&YHEf`zBl^tf6=AP<{E%{b{rr7T`Kl!0#Nt z)2ux?lM_kI^Rz~;x(ZAPYxG;$Jt*?ZKkaMkvDs8lNd0T`xn`S0aZ&+vcATmJn zXJkJPzxG0Ru^B`NW6CiZ7}oKKP=pV$@Vd}vug2~{HL4e)MtrvBoz z%U-#qDn1=I3RkeCq_I)yEWvZBDpiv9xkLYJRX7*nTPFhgi z7BI7>Bd_KbrPK#&DfQpcx*LOGea$%j05KmT3e>8IuQEmRD#O6{&wb!zkyX8-RxIR=Veno9SyR(tCt5}j6 z^PlqQdb)EY6iH|@)0PD*BLk@Ou`+i}Xkq8yGJ957j-|P)T zl$K(uTe_I@d6v_`q0oM$*{S%43GpMJtD&~J0l0aJtoqi5ztp71_1Mxvl(#b@uJ1e0 zKp7yxJRo3#4<{P(S`%I8LhQ=C7?16=lJhLe!vc-N$K5tepjAHUyUK}7n)@@{%s?mN zkX~4(Lj4kdf~myZzd2L@`9?@cAXQpZ*Lwz48pGw9^By97G_QO%FhP86w2=E_UEl2j zku?V^IpYIt0RWHcf@H$8y# z+It!7MUG{clE}^QD?XxOFCjv|x!RKHSYljASAY!j*CmGhqpGQCF|1*Sma+Azfgy=PJ@;{TiSyKeBGkP1h$FwCK|K2<|Gdj!px!Fs@6vgFr*W z6#)CRW-S*&%m}(>Xf#Teu+S1GPZIHQp2S0fTM^C8@C|Z-WvOZqpz^00sz<>zr-pFDIB7_OocW#VIss$Gf>f=r-XDX8Xu3bEP;v6Zx9heCCZwK_-_Wua#Y;sV`Aba>ep@vV6pzuU# z0RyNGG;GZ~p}YzwTUwGNfZ%~IyL6&dMNN#v1J@iA{10vt!veDfiO>jr&8$gC*&lwm z?VHH!ZWU}o0dZ(;;n>O?fb<)g)_{s_7L|i8wuS%o5gz^O4rnDb$=#sami)qmQWLhj zm{CIPusNy$SU22AtkC}S&B;Fc7C?O)i@A^Der;kck+^RD@$1Mca*@s{7)dDyx^$b= zUj<)6mW! zqLTo@cGqq#pRh%Lfg@X8W%tF+bouzBbkm zS-gFIQfWgETvWhm`TI5Ek~p$ALlZrTJx}O!83QopZveb--c38X3IJo>;b(M-jlEN7 zj|Mf%C(KLFuyjWB{bhrOx9F|>zib~?MJa?_2k0T;^Npvabyrf%!sjPJQu>8*BS`V4 zN$38ox@LDtqh4%((4Rti&SO9~sbMjPU8G)*HfVj{*%PYaEHP%kw|@D}k-h-0W^66q_GGE;=ya1O@45yGR0mQxJ7 zawg^SvB}umJVfqv6VTqjT(RSShuNWAW05Mq&9Fiin7w~i`kFA&QS*IH8)QuWx~e1U z0PS33*f2@WivE-F--R-eDhFCp{>Is9mMjT?v0<3Spjj>5b)m+)4{ zK}a95gVK@LUJOXH8wa~mhVhyK=+qhjD=%tppoRR1HM`#9HgIbcF@lDgDRa`o`6604 zpoekJfbk6$`nGGT(R-2^#7cV9TG8nP7w~jJI}Z#qe~`^7)mBo;SL_@@Z`$0PtcHpt z-2|t{?+;HBs*ALmQ4Sel@(p6qs7r=GF!_UOqK_R5k0+}o5@o>#Hz4EW*<=(_IB}6h zp!rxt`jsZeqm1!*DyT7Wjtte-KS^y&o5kMaN)uRJrJcYRaw(PJzq~=%55E-J!fE`J zM5|}BRPyM2@P)Sav1(%#hhCMI zOn~>e&e$cS7%M7DQ14afFsQLzlvv0r!zFj`Uf2r)PtR+d@K8~*Y#}F|Q|Imz^6VXm zLyGEX7Fln$qaDQQsI1s1*oXW^lYUA3>FQ`L?gffe8(4ITeEk0QXSvOjWUc19$P5nsmER#C zn!=FJrtYlp4xSM~4x1Q&6!-bs3h8BaVy z*8a`b0Pr2CG)5B}&2ru!=aSh0;ax|pvkrQ$x>I=Iq{R;R>Ly2cu`<%kklK)>Af>xP zBWjwQPd$FM3>=%D5S%bRVF4=90`laze0m%^i1W8$oZa^^EGUirJckchbssdv_mJZU z8&CQztP2$%?gTZc9L07L3h@m)k$$cOprZ? z(S(}rWx*_hyI$4l9e+c!(?EhfPTEecacaejEW-y6Tv;j-!$`nJC1_1n%YsnjJ3@_ecc4@tj_hH3=Y#3=9ys1J2+VQwij9-=;o>|u@ zQb>A`$tdl!JEbcq^7v89esf&)W*Vp5=#}ImVps>h75Zcqat6uXn+M*QdPYXrkD-=t zX@sqKgLfd%G*WCh-?BHnvWI{J(gZLpGDbP%5I^fwex!f)saLgdapH*Kk5j+4bZ{xW z#43$4%Z*&3^an4>jt7WNTLubVQDB(-{YSrZ7R`omNelTVG<|89UYYR8{A1&lF(fIy z%F?BWw&3LmxbBitNuijb@_A5TaFy7@r3eH@uuRS|@|tiXreaT(9D$->9vK}64=&f` zvnGVy1I=2YJ%iB58i#|KAEp_{i$imk_&w)K_aG6MvEoMn{rN4Pqeut=m98ByeX~~D zqUJL%5B`hvC^EcQrDiEL_0TtM6vt7d5U%WOCsclu3MjRd7-RAxm=>sjui(e#+*Q9D zk*UH&>`1P;i73-w_tbCpCVf;_|$qo z3o!>?q^z>RYFCG_s|lNmDH1FM?otL0%95lOHNIpy6hj(}N$}1tZRvjjfcB&I-?p<+H>{wD+gF1V=Cr8-SGBFSTqsz+cX+Z=aNkSc`@ zjB1r?a2CV51ge~B*h!fNXGEM>HI-e#6zvzW1{cAg3wpK7+u-~vQ$-N-0JBD>){hVR z(whqi(XLA$*S5424rSQJ{ihM}zHz`K-ij}zf zqZZ}L{^^ch5RfWIIuO(z>&GOL5dxl1}qTGc&L!SiR72fnC_}-s;y`oK0RK#01F^ zAT~y>PH2G1&qeFqg4G8O4GjmO>!;-XssGS}O{%B`Z+h zT(~;B?-JzrT|ah{L2*?~8TGzxiig@OnPss9PH!*wMs?hZKxcHOz>*pj}qkwc72F^QwFj?Lgzn# z+8v1w%Kv6~%S>=ZuZ^0GLJI<{6uE_GCRr*DEHf-fTvj#w6u#goxNR(yqe=yhn{8E+ z0X9WuPr=jF1{VAlN^otzHd1}tukRsV^4M5IlN^2a^PS<>JdFybLE7B28nY8zi%&<< z*J}^Y7Dza8Ae}XYxooAT*XV`niHeVj$=pKr3yawCYz@reY?l=XQG&KqCZqyH#R6EJ z(GLEt))W`<6dui_tVH`{oSGpu8eaH~MkTj~jOp!jm`zZ~sk9|x8Wk*t6 z#LaRWT4XTk*Zqa6jf8z%%DaLr*dkb@J)xYW`JR&b?<&uNAfM4dvE~O5`J+Ag*ERTD zhq_%EHf?W{fP0zE>0~8A4w{9c9(dw4jA6-r)66{o3oOVl!~o55)6n0aD(Y>OIFrc3 zMuCli;++#(TAfp^K4VcL7EWx@G_N3Cj#=2gM%DSL9AicS;wjHo`W?|h7kG}7rpjYY zf#HjsTl-6}d3-k(AS~W(DsQ1X%lr3h5o}umP=2_kixPYCv|_UG;ygt^b>XJ#YYuij zJ)v59>F}tn38f$ywWbAw-A(lNBT)w&1FQai&9isq0jlcu0fL*YXu(pOp-|@uK~-U* zZyNxWcW4&!?0w%EqUu!M6d?VOxTdV)(Q%lGy$bUT{nGx3k-q(7z3X$ zn4m5Z{uii-|9Fk!<@M4FrZU}L0~YPlwM@fC2tQI;+Ot#PAacgAj@Z(OYJO9=W+Bqe z@4o%$NHl7)l-fjrPa~47!v)YcL75X!e1v!**euX( z!JnEALN`8eu}XqFFySB!S@Ba9G|UDxWm=MD0H(jYl7*_SM0#I9KnTN(bn?ES3qM7# zr=iJ-!%1R0zpTkv0meAW+r?k{oRN0?fLwH=EhazchVP7 zEto>vQmSckQP{ew7wOvF2aFHdGEc}m$g816Is-V^%($ygYN$~STCLZ}J4CJ0U-X?R zl#?wu^r0JI>7pmQO``0Kgw;nq%8cZ)ed2)5!xjL|&*LH3=AttpMA~E2uE!_hf}O#! zn2#O|brDy`3+<63uK@dH7od)od5gxnrN}S*1GN%f=P_AKg*9@L&rzR9K%{^QDIL|m zNQ=RR|3C{%OAC8HEVC3M_>J8{8sRpo@yi%Bvp(pO_q4}El)ve=)OI`(_ zD$GFV`@9?@ACID>WrcMgo5QX@bNHcN;beri5X~OVUR>wuqQk-cSX@Bs$3RC#Fo=m%C@DoJt-QEdLsn_I6N@e|xC`G6|p&vVQf6lsFhYBM3 zz8)BO)_2Vh`-)ay{k)@nRG@^JfyF?3SOV!QpR@NDCOc#D!oi%Bx}2X*lHbi8EOU}AI-n9bYNK`jY*wC!=8Q>4 z5YAX3T=c`#Pm1okqBce*qY)auy-51MaK5`ZKr#clE(f{MzQBI^F5~nPx=T1>d>Yi+ z;)herIJE9*cH`kS9fyaWw83>+8Crn<(IWcvFy4&X$jH@#6hIZN_7w1>O_efZIkS*7E-6_ee0=) z#Ry|?>V+p^y--kIoZ#`^&RQwPf;TuA2=>+%m8TI9Q-1emo5-$$S1eGXA5vS9U*AMy zWqgwl=IX_PvUwqI_QzyFOj2np;5*6{8huSbicxhgDtp#}Pq&ag41O~Eo=Ft|_pan& zKfEI!$zYj*42GNcNu2`5UWVA>d&K9^XfC@4F0Bfx!Q@&V2FY7+R(^4HTHiw>;yYfQ zwRTkU-m^?5+5i5@ot_(kpCH(nrIY%LfFM0X9?A~X0E@FXJpBm<2@RLC@&iToeMLf9fQF9Q9xNH~%zh z)>dH3Cx%60TDqJ5cNdL`Cvpl@p(Gy|R4jS_m|M~DYqGEKsLL64J7qShBPy|0SiDj( zT`+_FynNF$WQN-ER(>iZk>5u8L>R7>0q(2NG%w1z?z}Vt2Qd6|qWQ4&54Z>Hy*vNB(r9lJJdms zI(pV)pxfJ}jbmz^L)OaG^4c-0z+kkM%sZgGtaJm_wgm#YXg8`dSO9>XoU*jrTOuHo zueQb_Srm^GMaSF#uNFq-><3cQuwYy|@%k(Z#JMwxxO}zDkoeP%m_~VD?02ITsV{@3 z*lxbcd6wUB1tn^|YBX1E=1ieu4ciQ~ToAKuT{s@$!HBuUM`La%`@*2>Fq(|+#B(TF zl=zGJM_r4=YQM3LG37=Ft;}r6`{J4Zg!)=`eIAL5 zZdus#NJD@NcAg&g3+s;?0WX`ac7*2Lxeuq>4hC6^gw>qD3Pdbc?ZZy)-1DQq_;vtv zAY|fhTBpS5M8rfyYja_>N-|m8g}9lc+fy+RZ+qV0TO+bAYbjI_;I`4d4P<uhC2d${NX_B$2&2xXN}Tag!p;oAH9!Dc4~S+d(n#ohUYQyzjxQH0aBw6O z(HECRfiWKHpg?KTVCBhjpFP}JM^>J0!g7=X!VryW5wf>`NmaQ|C->A` z8I6Q$^N(krp~QjQ`$R62UxrD|Re5-PLZnX!Y5cBFb}xF4q?U{yhQ0qb9(l8T3_#odLFJ zA2nSu)r|@Ff6mjpioT`Wn6xktmU_UKLg)U<{=JRNmUEI_O{wnmE8-Z8u@A!2|G!WD zZ+n~(MGJ>6+*;2h;}JvX4||{G6j0$|*PT|xYqwP&IWL3zns$9_Bp-m;S=`Iu&|X?D zz-kGeNcm1M^lMV!nO_ACva17ArauXrK^A^=(AqdMPuA9-hHzdFfg=aN`|!vua1NUB z2QNm#+mGh{Q6a4=5}$=0>T`rwL5Tvk24#{GMuV+0Icgv|H=bpMXNIv2w^g%iq7bfE zeE2pT?eU%4oI^r`!BU}QgpLxT9&Causb~fg%}@)>7FaUhrU8=092d+;#l*`_pz}|& zv&xgalYE&G!qxz*OCW4z4}qSvUoDoaJMhDW+2g>3BgxyKxvYo=?~h zp7%?_wPI9%U%7*a;q8-x#aIpkfjRhGxn+pNH)4bV?W&!SUS|8U zEAiDQ7)1F_eM}1&WZ8=Yhyog*XA7j>Jre3VsBpMSt@U$p?u$+GNuQt!6*^9WCkKzeGV@JAUhO9I7{DkoIDgRVjV`20u=s4);dxy3=n2hXL6ziNEC)PG z3`)V78#<5~{RBFfdb)ssO$85DCtIRR^Wx0cMm6@1agKFM&{O5hkq8tc1t7|G-ZnpN zcrMBqlZK0{6lUs+kmW-DqJXPHt@@+u0GEVH1KE@X!ZZoi@Ltt;a2Q85j=?K_D-0v# zI_Z%0Y^NFkiv)b@m{6&1f~9hFzDZ~Qp+44oJbrkp8a@|D%7WP1YsLid2#ssP(^hdD<%oNDB)DR5>PuByxL0w&(!v$@~AT%FlV6U zXv6Dgc7GD*!m0mfzdnEi$Q0+TMF_J(gtKuHXyW@FcNr|A}n3)*~GOM!}oXlbv5K(199%wXGQuo+R*W;lU@ne~? zDn97@?w~6j4=(oDgSZH_tIJUxWbi3w?{TU4?6ZtVNu8giVN-c>au4UE~od-RZ$7B@)6bpcbq z6!b9TshV&za^s|HA8V&0lXlwIj?n8I{~d&R4!a?bh-a5@K#`EBDeV)6MdkurfrZX~ zGZQBr@K~2yxEm4%>yKj!v`iPTOlqXeJhis(Au8VxnttlKPmnsOTAhi;d*sG1yud`~ zv?AV~o{-YO9pLr-hG+SiQtBx%Aj1Ly6$FW)uc?mF{2qnXGBnb)au$OZYoU;;rh_c> zmtNG|0oFw4b{iK%vC$$~Aruk7s25WJY$@brty(TGKd$0pVxITIaEUI)zuzZUF}Kff zsBU~=weGVL_j~xduB@g-GNvf<^4n{qy3M=P@KP1i=lCZUOrL!Da{hgBu|g4&cw2-59J!_2yfiA5UTn-oZiI~M9}R%NreDo7B{j_p9vzWcAZ zrn>h{aX^cmDf>^DU!jq{@a(#yyp;}>Pea_F=j)myT2P49k+@X3me7t2;3$h`r}cR3 z{oyBjR-Z%2i2o|Hiq-rrBbd%Rtj|9;EIzUO$hZ`|v%fTYCRMBn1Txp`z%6&?h75Nq zqQ_ZUDnR=hAxjAl@+fv0*K5)?QmlSyB~bb)sMB$wDT#_qE99!2qrO)>-EARd;z3Ya zXC-q*kfDMLeFRU{fzP=MXozFXYD?2hMV^RLS$6A46Iuzn;G(=uKrNDw9N2J3e9&Ev z#p1AYX%}^Yz#!xk5ZqT5DgMns7IUn1obB17{|HFKxqQ=PNgJ6tGl96=wK_CFT23e< z<8#_XUBo>C974ej`}URug-}Euuo9AlvhJXda zyd93CE8_Do*La4mR$lW_F2%x7*l<9zZw3UCNH^{@=KMg+jqF?TUvfu5nN7BsDi;CO z+xYc#A-PZhd_;jfg}_rQUcqlokOW_7ak&F1r+~CvGE&SjfjsTf@1DHPoo7(4xffnSBT*5eAn{3N%2ppg}0c>|? zC_aJ;L16tx_UVZk1WpdFMgszE@8RPRkBwbCU1rW~v3d(kn6w%|7U(tQz`6($P8uM4 zsCFoT54s}f6m=I}`GMd#=DB-mUIVlSq{5-DE#2e!&qV;$_ero~qqob)K%gO=vx?6>OlZzcqf??= zW@(jkg1{b3Q<11OCk)h0)IBppo^~J{-Vx>Pw#p5~r%jG8Jsagd z;ES*eXtE28?%Ei9R?j#F(P+IIW&hiL3g0h0`{0cQLwQeTJChEqmFnRi6v+wZ`Kvn> zL0Y{vM+42O2JGe2{h@64LRkv#*S97LJj^03{f)+ikqb!PMC)@y3=Iy$>UHzO3d*DI zxaZH*Yw|ta{$D*MVv`!zWTf9dop^>w7~-PQ#}h|p15NbBIWsuvTMG^Cw6f8c(@N|7 zoP+ap(wfV0U?3UyNyV)No~W}d*HeO9Va73gLU-RG_q(jY^-xMAgtykiXp^r>gI1f; z6z}#Gi%$KV7lm}~GYRE|xZ?onFK?(}Fq9dvUkKFuIi+?gF~D~pv?Yuts4b)B(Fm{c z81v>7ZPDR<+*15>3lnj9c12nZpAYjo8n?itg+T@LOvkrtK)dXJDuToBD*Sq3w*#&4 zZRJs!V+NKXWt1{BonUjFVI4(P)L%bp@E&vOT$+ncfAiCsIuD}NtAukydq?=B;rzBe zhh0C?o7+$Wi_laL96*0JUfb@=^FcOdIjVn9ICCq1i}yZkFO#oSV+ zz|4+7AKmE&%#5UL$$6gMGpUd8<5}9uy+fzCrJy3ZPL* z*nHUL0=K;>Kp_*OFi4tWiR5YmBs4UR(}YoWR-cJ?ZlMFLEYLbuARO0Xm~(ar9_HeB979+KMDF2&Q#Ly3R^dCy3tKo7ELb4(%2=R4oB>;hjR zj4cgdyQ!$@z0VwO4q~Vk?NlP{)a!5pih$fe64h$q1|AeyWXob!x?!{m9GiYVz7wI{coh|oNvxZB z{mz0?-4yh^DB-<>!Ga1PDzxl`?qW+6m#qc=XP~~N(P?EhAjV7x?&oiafVFx&S4Wvb z<78PM*S)Fr$hPxH*j>2^6k|jy`pJX7qeXRtKgt*tXd13u?n**pO_R;z4O&VWr`;0@ z;(nh~PvF&r?sQcdbpI>=&^%~*--=Nkmz_Gs#4UMrRt&dEM~rzfYG+(2BTHvZV=o1| zPf*$=J}OxN*$m%^ve%8^bOZ(1aZf;hFI=!SKiXnoC6V^af~||~nc~pT5#G#hTtJ}R zLpC;pvFTk18;q!F=l*qs6rg|7wbe>_oy|YTu0C)JLq{cZF`OFdGafAGy=N z;@{+om4m4qq_$GrCDe|aT}epWfxl?Un7BXIgau$!C*#I-b|XbS-k_`z@zh3w?xetM zEQDC7HiZq$8YI((aka4;T69fd2Zd1yIUGIJh_Ej)z}IO94s{znN}1))zh1sU8dUxb z`3}Nh3KCQ)6gN+I3=B7U+9Hd1A0PzR3MY19kg5gx;EN2 zxsYDqz^ubHM|5t&q`h*BsXZ(}@3|&IP&wj$itg=CYOidvQ*23r3zJD=g_6wUY?n(- z*77PspdZ$34=+Z<0cE_SrGqG=gV|8R;yW@)dTA)J%LHF@O(YezAOFl#3${{M)+_Um zy`H21RH`E*6W1m*hW^O7;L^QE)8bmr-HMOz!I!JRLs}q5<9R>5TnVDM1|PJ675 zz>Q4uNv9U%736#eX>uDji%{eSI|n=Cj*)%D>b|^#j_yPr)ps;`bzQf*l6nv z)ZCd#MzhJslm7f7WW2;pfy3)o1-VVEk^k7uJLFgV>IjEiZT5FU7fXo04V+x*vBt3H zy8)E#F2pMyf;C`Ckfu66_gp%<8m_|uW(Z=l0_8O+hAMe5y=XblqeCY9Le6t!T7ji) zC^9qt&y?n-#CVFZ7W4_>!m)?4!y>InCE|yHekHSTUdaI>ZvY+3J26LYmr#g6G&1_8 z2Co0zUS5OL`mCoh6zU#kJ&NY3BxoXGkI(>NAROQ(ogL>qP#zBlB+eAfE#(eW+&JVl zO4QHr+?cB{_ynu5l>-Qza`0C(v_{*miJPM<)A#^{*cuw5fZf&p21_e?cpYW{6G}#8 zKYoXd*0^peS!mS;qOQ`2kbMjQGgyl&MaL|ODj@kN*euGuWzV+gYC-N|ob_T$6iAQ= zESCeV6UYi7B@R|Dk#rtF>-Y7|V^h+^39OcC&rvE;2?KN}v0RbAnap2#Y2Duai$hES z1z6$H_xCZWMpRz>(tA%CTll|)KyHiAn+3J zm~0ReKNwir*(H|biangm9>HX`>s2z@|IY1kn|S-dKM8(+%m`)?1JE(9Gi05PYow)( z^J6ItO8z+P6}&Z-^10HTmTOS+M|bpv`zf5j)WE%_gMt7;3F;)%P1@>KBQYOV^s{KL z4N>*Da{a>BwQv+DMIFg-xY4TcQiUuL9`G;|P9?gHq}C}~OvJAyfQr$U1K>{I+GKG^ zXgCeBPp?67t(cUchVk?F3!DHaq9?Uf%VX47E-zfrc7C|})s`1gD`;XLm4H4+hPN~b zkJqD(nB1(Y`MGLu^;}I(CWHCw6XSkNUeZSVV@17c*7|JG;B@dI%%+6qbKRg@0Jy@B zqUe|drNN#oxa%_hu8nD6w=b*m9jU)}qA240!l(oX_BExfY8j+#EdVT;df3*teaYn533pQ$$qs4czt z5`B?TGc2}{87@+oBc$}oyBzmc8W~fm%QB^_6&p52!H41jvrp2#o~|)1g{=*O)I&9L zdm5wXR@-+9_$wx2d8gn&@M2l=sdSbUP!pXKw(?tH5ovLlH@_A;+pH3^>`_kymUssS zB!XP{k;bxbe>Z}1@$DH3Wk0(3(yzOm${_eg%k<@<>A53 zCCX>HKI0uf7dL}eoh50+h)iVm`!FfS^YSX}GS{IlGl=e}vy?dXv%fJ&(GB5(al?l_ zE_21*g4CSvyeGCOl#q1ZojN6?Z&(n*tWtD8s!O|_DWJ*B!(7xp2K!ZoPdw~U6D<_= zrGae1*uXWn$+LkKclt0fe%hBI42YYgC7Dz?5v(QUYI_;!ou`xlBBji~7pmo>F+CoMNXr-+%E+!he{P_XAef-t&l83G zTRQ((Yh*dfZKtOH>#$G#cvSlAjlE$*Un zyC*A9)0LPz<%rfG;!t;SCtqWM+NNdmOf*BnFl zl4Ve7dV@^pp!9Y`9s1-p{yUqGJ`7kR%rs1(7~x=-SHEwMqW$%&9X82KX}h3ohDWX; zJNB3qy`N>bS2-p86jTbBj(3a7@|q!7@S4n=h}}q zMrQ!`@tB|Z`h7RO3%Z|>plVmAvQCGH96Fp{4_4f?xEDjI?ghL__l^q)O;5376gtM) zz(w^Rf+`E>m(vRAJ*`!GvESQx|9%c-olX)pfZ((EypS|+&&M7c=9;zMbsz}$Nc zT7e!4Uz9_Dfqld+?*tbV4$d-DK9yRP@SZ4z#smc`#6&be)!S`?%i7Pej9@$1A*^9; zxKB?UC^w+%cG@ckpyvNC6F33nEa^#z5V#Z!)4wjNrx$P7MaHQam&oL;mr*1ktvd~c z`zb&_)J+wTVcztzI?z-IuynNHqzhQSP*G}B5#>=t{s~%XwD(f$HPL`bu+qXP#*u!i zNhM;_jhZ?^q5|Nh}oiI8CzSusB$&p~SkU z#B~&AD16}&4!F|v$0U#AVBT05aF|yU4C3G{V?dy*Nbc)aPQ{hr1G86YP_OHXiDxdm zZ}2iJOn?#%=ClR3m(KnIEPJuup#+p8?rqM3d|V+0QS3_g-uTc*Np_E~9xc#m&Laf; zMThR1j0njFFDy_X=;7HSMFeq46I45QzaH`vXtC`}rtMvm<7tqW=F`Z-nM1@-FRqK)W4pBh%a$N*Fzk{_@dS7%DKoXalAwe#&%@I4jwrm< zD`^1z-#d*0&^OJn%?qsd$@hH*HVJ~v;D#>euM8a{GW#u{>4YHdPhhC@$A z=vJ)75mDE5`O(cU>V{F%{5TD7P!X+ie7@_@vyYw^yc8aaVF++snjKEGEfNbsG9A)&f!3ngcKH@obN=b6i~*xP*4GH2IR%teavw~a*Zy05(&UC;)O-& zq@b%v56|{!)zReHt4N+CVP|o4Fdm%4#l5DB3E&0O>dIr=(3s|?H4I?^GrCdynDB!| zk41|!z8{skcdrVpg_Om2t(Zy3gJUd_5*Af?1nA5d4`D?nF)_@k0c}LOPc-c9=x1h# zAieEhDAupby|^0ELr083A%pNM22)lwFj6^mgyh?WZ>cAw@6p_H=Y6TZ$p;pifH>^v z!D193!xC+M98r6~qsE5)Cl#FXV#KJ$S?}PJ6hq`|QFUjSnMiDZ=X|KnE1mf&MTx$8 zVmylbLfj&WXzpLSnwGF@yT3}O{T|MMqDA0&ci|8?gR$O@)mRk z4e6H%D59yR!-W)LRlG2<^R1o$kbg<}J;~oSwxcx3Bc9KxJD4+YaIt5}|d3@S@ydr`b&Lv169rt^sif zb+|S_jCfgJ%_=NF028T?6SIjc`uUIG!CJIA90(171=JbHf}4%f-h&!nf2>-dytoTC*84I#nmXHSbr- zJ>InFIHIGqJ)y78S4J zQ`O*P&lC9$#^Gr0)YPAep~2dFSnrAw#R>gWh*&Y_3INemJp~UQt>3nfsVPE5Vhtk) z5+F3}!V(BsG(n^&fQm!PHG_sA{grX>wAS1&*uertmnjs$9hMWB-coNON)K_9&K7h? z4E1GD`C`-MFH%e<17I$3q7XxR`YCqR+-9Nc8$)Ps{IM>d2@^se#DQv35p=Na8vWN% z4JI4r1bdMq6;Wp*`l$c7Des2Wd(8DrRMVV5ej4hX0+j1IlwD5+kfB+kJ)k?|u_@vBjV^Z4Yi+#_2{+-fp^tMb69Ti$)?gGL1>3S76J`S!8c> zNRDKTG-F#PQvAab``JQZA19rkTR6C5G<5lFa^~-KMm>L4R z0R4tC2ypVkG6bc1@gIu5QF}!7jdXHLq2fwbGT?m)8~o7PqaR^Ft)=l#H|eBhHIU{b zDnt;(H-@9DEOk&4jEHFc59`+k!wJ)pd<#URjusrrU3fB_U+jj%rd?ar7y;S@k<44F zvql3yX2g^qW^uyv3V)?<;(%<@syDf}a5l4wgK{l;ENG?A3!#fuF7Z(Hm6)U_l4wdW zfS_7{w#qDi!|)l1$2d#5p2kp+Klo}k=3QCJk5gaeBh^mV2E$sNM_vY8;wc&S7EpSo zh7KVw7y~uhfu_c&EY>HOgt~#a<~250d$B5eL)*~0wk8i4xJBW@TZPZ3IB{z^^JJ#h z0AO~_@{ij-zUY@3*|V-RD#v_5O}Y)kPHgiLjIn}s!i5kQQ{ISHzT$a3yzF@sRthtI zEm;t92?m*A2D1Tb7Ma{XN^+m|U{XTcnGo&(KQzol1F%2t>sL2J=)NB;vy4qOO$b0# zm4iT{0S?NDJTn6T%HXzCY~K3ik@?szDlYukeb5X+MLPrNkoZRr1FJ9ozu@tM-smzhsSXB9$96-VJ z%qof?ZvUD{wgkwVLM_hCl9p?8EUbfls<}nH=B%qUX81U^3Y%iCa0Ne4a(n@%r76Q- zjj3L*ZQ`>DsnmW9iv~&J&_P1c_fzH=#tlPJvop!}PEH+{-($7>1i||ee+nn)gb>?a z$AYZ#vvvqjOdG$kFhsrh+b5byI;4ZC8>X-@?m(;nSV_D%%-dmC0pCX3nX=W}34&GY z7eAki+{mOXA7pH@sV( z@u$j?UPG?E(0J*W?n^BZRX{~4{85v!BfUe2RrMlT4uhH;;>por$tvL};NDftU@{egbPi{JPNUE zw#p&h6P&XQ+J!^nhp`lfc2%@D0z2iHYhw)Xw0e8rnvErGpY#zciLc=hL6QteUJ3++ z$yfq;G4YOFzsvcMvbt3nR-cvxd7JKsqw-)-0L%yMg;d=utcnJUOlB7+0v+)9Rgemy zLU!MHXF#}K5z)F=)JiZ0t?x{uwfZTcqb z>D<_m|92y(p$0@`c446N(?WGxxD%bn5AjzN)dr%9xRN*?rIuYXSZ=tctvw zPOr!AV30Kr|E5nX-%%+Q=w;l1Wu>jW29=IK{_(M<0o?p+%w0nJECQD?$>4H0zDJh9 zjn%=0SL^98iGRdTRC+fKjZCR+-KDUCvZ^DGHWaci)v}u5F0lf%wwFCJt|Dr_XyL`$ zJM&45HXQ`kGTI7q6E_|Vd5lj)p~vn>Bi93CmYyq-y{TXIA8te&D+nJ%8A|nBGSa?X zg1={8psGc}(bBN;*-YO7hhW5zAJf7LhBg;=mQtEgIX3i1tyjBKAxe`J2<2^7x4M`H znlNE;?dho?dk7V+Gz}DgPUpSF#nfH!_XteJ^+Mpwp@g@pq10tAaCkFSlu2d7Ocjn9 zs|@27V!X~$w|LjtHwzedZ)Y}ESDg#5`y8{xR|SkFzw7eLO$19TcN zOQy*9!6!n^6>#~?)#&0SE$G!oorp2e(Epu)5-rDWHu(dcMvFJIv3F?j>~~4evBFRsP8W-w&hyWs~iXzPd2p-fIoWZ(68o6&If!xD;^PZYHr8>_=M)DGX=h86ljJm8YSc43_U0dYd|B z)C(1ZZmj#rPE@WD@Sj=LVZYc9UduOnVOOJXiOg9_qu`S*|L1r1H|5p>K5#Cvi1&6E z?jq|A!t^E20Vxw#Hw42-R3n7JunfY%Q&T8NYXEi&H;R+dM=$cYW5tu@Nok!d3m~*f z$}3L%_>CHGy&EwTayy(STl z(olg+5r5dgVB^Q-m=qX7FSZbL#dOPwMs|V@4+EwI18j!d>9hylb)GI~sU!fIl8YvV zm@EGKZ*LeGnn~x8yYE#kRO1)u?Br^=Xs3-TBA=)d0D;mSXqo*F4KeA`#1bA<{nOzk z4*e`ezn;Tp7(oID?4}WoP>1%KjeE;j>ohD{T%Hjp4v@I^yy!*-?q;N%>=Y;0^s_iG zgu!GO*7i$pjHzCY0-_5oJYy6{$Ip5Wln-gQL%_I=Q`he|W_?y65A?H%a@7>nE-am_ ziI_nQ{6a_dpo=;9;@>wdgymza1M@FSXePL=o#5)(oea`tm!ia+_RR$XF|j+M)>E3S zE85@tz=sS%nS_40G2j%BM{dwwRV*LHIzdbQxW%auEnOs~K*O1OqiKh?!X;632mfz4 zovF%!-uznv$4JglgUA~Th%`o3ZY6ltG|$4{f`qQZC_1w~xJM+lr}_F=q#6_$*ci}; z2SvZ+(TeVp&e?K!LCguH6rZBw&js?Uc9rf*5Nxa+DN>%drC9K%;27G=vGO9qwkWJc zi9_RWXlA4v2AOsTdSpIDPwXMn;r}!m_pSl*qH2APRcUS=-j7V1gk1iJG5)GAY}-N9 zq(CtOe38N~h#Ry_0A3D*9T)REQ7Z(>;V6m6SPUSN@}aeiJ0{Z)U7Esc0zjJF)Wu0u3$`At#S9=`?INz|VM1R$#mz)61l!}Hb64?6{%SZh2*!L=>D zh%!Gvu)+pcgm46kpozqiu!o0|cE%f#H((`9^E z3NqHmeP%MHAfZBn2Q!gX1d$7$EKR8Vk}Ce@TrhMcp*_WpSl^sSWC*`x0mEsin~?aN zkyVF<<~7|775xAU6<_YQt0k*C&k-ZRkN#xw9K7(XtYtGPc|e`D124uZ%=MFv1BSNd zU9AX>T7PuHX0P5&VaPt0Et^YKKnW=!`buD?IEPU96Af;Pq;%Ug=)hFDA;mVkydE^;GdYy1s{73ky8sYDOhu?mza z*~xS_ccbj{{RuwklR)Amci7|i@p#bju&%M>|mQ`4xIE1QQIj>$#O|C2NsQtq{|< zstyAtHU5`^>IUzc)I*pZ@7H=MX+gMJ#iQQxer1*11Mc|hFOZgJ?hTS;Kg*e#%47)T zI1n$lAhV=u1(2puO1DpgbhC#IV9n`!uSSI1i-Z869u;wwdBf$PH*oYHyy^b`1={Vk zUV_|%mjDFr_CV?9HdTBYV%E;UwW)~8CLHW>1}D_!Ew~741Vm=CN3y*&Knyi4scepI z7yj9izF3Ng6nF&ZQN@BbF~18UKI;+)jKD5T_Ilb{eOJUIh5+(2;;C|aPYyqC{QPc# z&%MD8JXP?e$rizVR_G%L5;+b}Wd<$)yPn9<-VqrmUhSXY8X1$ggu^gT;RUKS_QAbv z+{kIIBF2=o?E#2wVe{Mj^pnT)cgRbV+U1a_O^47y!pTL+qr$M$Ia+Jiz>V+LGeFOW ziyVa!Izsp}Hudr*-gB7M^QLzTZE*7L{#w?3bm!IXyvEFIy%yyXjOGV&}~*+`Sdsx z;X){(8>WnG&A|GlWZbodMPvhIH{{+J95Ot-kpO`3Jj??$i<@zLP0wa1F@Gb&xBG7s zQ<2E4AhK%wi^k59wm6AxG(0#{stDwAIy-@I!83iloTTI;UEw8ILJFlH%lqtv7X-xr zlttk^({||XReq}AWthfMc@uqi%GumEB@8GZ`ht>3vnAMOnhAm-X<%nQxV~d*G>dBc z13mwz<9!+-;jL|mG*xgmOn=sUh7Gk3mxY4RAK}~}K9*w+Qkz)#1UlFZKw0X}?{U}? z$`g33pc^a}AWVQlK8*1cYB;Q!$!aL*`|YQwRF8enAuN-diHXZuMZ>v&CA%|MJ5FB& zOQr9QSyqqxSu(i1Ot)a+pp*!)y|<3EwRoo@Vw$#oy_$9eL12_1iInElmQL~9(|X92 z6cW)Cjxvc;KVX)FY}PW@Q*pp|De_X^eeZ2<6bA1`k_FIuGSMVAzS?@T-t|~rNeoby z=usZeGf3M#HR7p}o6Q>vnY0L}glxP5{*VvPZaf7D8hj}52s#pghe7Tht)0af)scEB z4YYg@h7~(O56oL^TQw&**%vEqw`Ekm&h-2I^lA6A%fPTppwDlxRUTm=d#T{UnX%3z!V7@T(-*)&&qrcrWRXpdd2Z&w9 zIyzLNV3~Tkkp4n6bWBJRA2U85V!NMuJ~NkTX=@75YOxN|87O>jY)*6H1ZBkxpH|EJ zDZ-V~rjComLrSfe(mkw?!YI$h@&=oBl zdeVHvt~4U!&^6%FJwv}+-1T1?<38Ovn9t7EgRIS|=)}DX(!#D;gXu?yM5Cd!gx%G~ zXJtl#Bgp`j0@>4fP7`v=J_RvDKdjz#>@A)$0^J_0{Yi63%9XZCaDte23;{nGKL=;y ziVn1>;INkgr4n2DJoCDUqE>^21>xi#ye zgQ7LRpkRqjVU-m?setcFhV^D|!92;}rZt@H^&0If5FsO|2ly7;GRCb(p=g1Sv%W!h z2Hj0*E#?mm7JxsgcN(ID>-$V;aT1Y(1%BQ3^GoABv{x4B5K{8-SSy-u5NJ`p0aaI| zM9Ix+WHwL`aF<4X@{c0kFE2$eY zb4X%qxlam$G}|5WF8R*pbP%15Gqb6S0SicDg?PJMQ(vCF#&uY826I? zxOfCoC7xrZ+F~K9tXXc5=F&V-WE{T%0vLO?vFDWsgNZ}b$H|3zGbIVE4K2JCKqIGgyv*N0A?{y$Kaa7p%X z$>WO932i1Q`k)&Tw-2S_)Rw%9*pRyeCU>wubXuEnB}pTfW2|eDfAqswie{0a@%-@I z;N%LL^=q0v9a=gG9|)dxcxnELp-CHT(LD-rgzYZK7wy;%e&f0eW%+$#kWS%07PBR;xmgMvq5;~YfzVZ!K#nO z!YGxPu|pB2FR+tG{%b*^?VTo)AjCUM;C7IH4(X zE#|0=BlcF;=|Tib!jNHFdx!njJ3hM)8ygt+2COu$Y3O?luR5nO-#Q-k#5yfG)1E}W zy;gydK=arq8qjkDcmDaWEa*Scf6_Pkv}Vg_RWsXm5f#OYFAHqtj^u!2ur%u&Bk2zT zwMPKzoa7of5RfTJIsnW7hztM>fJgwq0Ki230ue|2|1bZKY4?-&;GLPdq|D6h0(kRU zusQhZzxVt9-H1&AmI00dp#jD6ZGErIYQU@o%u2wlR%T_*I>6Zc+OO@a0J8=#Yn54} zW(8nYs9B%BPG2gWG8Ruuo4!o5-mKTGY}VCS%B+#{ZIo}K%vva~8Yr*YC*M4owNAcq zGOKMet6iGaEX`_~%xam;YM9Jwm&|IG%xaa)YLv`slgw(8e2Zk(AepsCX3ddrUB1T1 z*A^LDrLie8wnV;0>1&9L?U1h-^0h*~M#$F$nYBQ^0rKsSZ+?91;~O8}_V}6}-|}d9 z%-S8ZX2-16F>7>uZH{kpe2e279N*sf=Ek=+zOnIbjc;mvOXC|F-_H0p>6;nf%J@dc zw=upZ>1$$K1ucv*w{FaLV;UG@Zk?F##C-A1i*H?gY6@y&^EO?+eG!n7r(YD!Gil9;L?F;zQas%FGgHyxNNgM6)sStH^v zTN>iL2+^elF*YE^7U{S^8r!3>{V+Bk#@55wc(^UM!#G9I*mTgcrDuJ-YKy)(`qtB%TAXi*NSfytW=D>GFFPQDS;Il#aJlDJ~0+do%lBKW#YTUSS4mnVpb%^OVam< zuMyuOzC?70uMpn?F*edzNMj$3{b8&RV|y6O!`K~0G}YnG)X|w~qm>wCG&YB^i^k$G z_J*-GjICiT4PzCJonf5InW+p{qQ-D#3PTfpUto1%))r=EVb&F9Rbf^{vnWGmO<^nw zV^0`+Xsn?tQVU&?O6ZDoDVpj6W2&z_)j>yw=|L)JY@o4#xKLe?zU$FepN z113rsFj4w0xDcJxS#TkmT`A1!=T%L3)e>H{&sX_;b5e2oUd}y1 zi)u8x2tFa0O`1boTV;=d*MKM(&RJmP4?ihB(h}yR*s6v z3%uMoIG3dFiI2&NFROeR^(6proYKsCb(NA(D?9o0rPBwiK3`I4lT*G#53;F)GaMw- zcijf7F*h|kHhELGZfd5RdeW&0fXb!GYfLugYP^`frOZmo*imK`W!6x>pnO01dh+e$ z%gH8VFO9V{R+F)*OeV8pGV3L?S~82uGHWHXC`YAa)=9pOZcQbbs*(JKi3Ui%KJqm& zavk|LLgv<#k+F-6t+bL;MaCxbQz@OAA~N=nuZD~*gEjIm&h{o?Dzw~H?q-z~mce6#ps@mCz9QR8M!5;1Er z+@V`{=%zcAL(EDcW*NkoK#Un_Oh})PX8FS`eVAnrv*h9K))o4?Ldj^%9CFbtaTxQ4S!n~ITSsW8Ba}4^x^;uTZcx%NrlK)t7*mEZV;B>L zF%#trpDuj1@X5mG3ZE*BiD=9e{*owso-kTDIeBPILu0lXlhBxhz7#ZOpfLfB`DaW& zW15g9WS=qljJan_JqoPmWS;Yrcn(nBIX_u-fWEVnBz%tWInnuPMknaj3A*V7RY~MR zOI@I}lXX5iU&=XON;$JqgjpG9R)zqm$?4Cn`}1{w#&UjcouBXgEOjQdM6)B9B?zBX z*P~n4qn)ltvu;Q@SEYP2E8ScP`N2<7Xk4G!T$OHJm5#b9Wt%TOn3WwopIgW0DaYp- z_T0KX-|a~be##9_PqH~ZIhAWZ)yy)@EYZvw%jLOsc?RI}PSd2pJ8r<1oP#W zS$g^G^2z0M%cquEfX1i+kwS;%|oN!Jn&Z+h+g$!-w9nkMZJFM*2w8GmEzZ;4?&i#vv~m z@XsDAy^cw#@n()+OGNp~jz>B_T<0lhCz_k;M>UC|h3SU&nQ2$gX6$5HAYb{Db(%(a zU*O**8tEWXo<)W}3^Ci0+&K=&FgA&QyTkiEUnijcL6ll|J6DTsCSFY>uTU593U&#g z$+TtCA#;z>e;JUOsbtn?WXN;0KEs3-2nYlK1{VqKO>&M9P9*&<`p8{tXX8#^Sr>x;HU_6Hv zehD+6e8+S?{C1QbTgXZW8qKv&>iQCRuS6kcnuZC7T!eu(F({VEEv|uLE1$@i716*G59v zIiH!U`Bf-uUcBnNQ+=2#my{q(%X`93N#8VFQ6*lbdQtLzMZNz%KVLY9@eLw5`@Z$u zm8-4bhrf{FHeM=C7$E=v0Q&|206_);0B4K<0QtrR0HW;x02mGe00RI3006P-l8>s_ BjfDUJ literal 0 HcmV?d00001 diff --git a/tests/golden/WBV2-P1149-000/manifest.json b/tests/golden/WBV2-P1149-000/manifest.json new file mode 100644 index 000000000..4503bbf5c --- /dev/null +++ b/tests/golden/WBV2-P1149-000/manifest.json @@ -0,0 +1,42 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P1149-000", + "parentTask": "WBV2-P1148-001", + "operation": "AUTHORIZE_SOURCE_BACKED_MODULE_BATCH", + "status": "done", + "enablingTask": true, + "parityStateChange": false, + "runtime": "MODULE_EXECUTION_QUEUE_BRIDGE", + "artifacts": { + "parentManifest": { + "path": "tests/golden/WBV2-P1148-001/manifest.json", + "sha256": "3602227697c22e05550370215e38b30cdcc4e9fd27a2f8a1fe8842f85cdbed69" + }, + "plan": { + "path": "tests/golden/WBV2-P1149-000/module-execution-plan.json", + "sha256": "c18471cb8d81c310529d509b4acc984dd1c3bb26d36f8a35eac6add2f4b61012" + }, + "report": { + "path": "tests/golden/WBV2-P1149-000/successor-authorization-report.json", + "sha256": "7554d00d95256fe0d9b0e7b54c8a1721a9e0c7817fc949a6086cfb4a69a053d2" + }, + "status": { + "path": "docs/status/WBV2-P1149-000.md", + "sha256": "4df438988a4f3b4114c8e445d09f1b92b8fce3ac5c8523500cbef5fc3984835b" + } + }, + "assertions": { + "sourceBackedSuccessor": true, + "moduleId": "MODIFIER_READER_BATCH_FOUR", + "batchSize": 8, + "inventoryTotal": 6900, + "effectiveCompleted": 290, + "effectivePending": 6609, + "dynamicUnitCount": 3745, + "dynamicVerifiedUnits": 377, + "dynamicUnverifiedUnits": 3368, + "boundUnitDelta": 0, + "fullHistoricalReproduction": false + }, + "nextTask": "WBV2-P1149-001" +} diff --git a/tests/golden/WBV2-P1149-000/module-execution-plan.json b/tests/golden/WBV2-P1149-000/module-execution-plan.json new file mode 100644 index 000000000..a40c3a1e3 --- /dev/null +++ b/tests/golden/WBV2-P1149-000/module-execution-plan.json @@ -0,0 +1,6173 @@ +{ + "schemaVersion": 1, + "planId": "BLENDER_WEB_MODULE_EXECUTION_P1149", + "operation": "FUNCTION_MODULE_MIGRATION_PLAN", + "status": "COMPLETED_MODULE_EXECUTION", + "authority": "blender_main_source_and_existing_hash_bound_receipts", + "executionPointer": "docs/EXECUTION_QUEUE.md", + "inventory": { + "path": "tests/golden/WBV2-P0-002/parity-map.json", + "sha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "total": 6900, + "legacyCompleted": 281, + "legacyPending": 6618, + "effectiveCompleted": 290, + "effectivePending": 6609, + "mutation": "forbidden_by_module_execution" + }, + "reusePolicy": { + "completedReceipts": "reuse_without_rerun", + "continuationEvidence": "excluded", + "duplicateValidation": "forbidden", + "fullFamilyParity": "never_inferred" + }, + "verificationPolicy": { + "browser": "chromium_only", + "required": [ + "sourceHash", + "wasmBuild", + "positiveMainMutation", + "negativeNoMutation", + "undoRedo", + "saveReopen", + "aggregateManifest" + ], + "failure": "keep_module_in_progress_and_do_not_advance" + }, + "modules": [ + { + "id": "RENDER_LIGHT_CAMERA", + "task": "WBV2-P1100-001", + "owner": "RENDER", + "sourceBacked": true, + "capabilities": [ + "CAP-RENDER-LIGHT-TYPE", + "CAP-RENDER-LIGHT-AREA-SHAPE", + "CAP-RENDER-LIGHT-CONTRIBUTION-FACTORS", + "CAP-RENDER-LIGHT-SHADOW-CONTROLS", + "CAP-RENDER-LIGHT-CASCADE-CONTROLS", + "CAP-RENDER-LIGHT-AREA-SIZE-Z", + "CAP-RENDER-LIGHT-CLIP-START", + "CAP-RENDER-WORLD-LIGHTING-CONTROLS", + "CAP-RENDER-WORLD-PROBE-CONTROLS", + "CAP-RENDER-WORLD-ENVIRONMENT-STRENGTH", + "CAP-RENDER-CAMERA-DOF-FOCUS-OBJECT", + "CAP-RENDER-CAMERA-PANORAMA" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P595-002/manifest.json", + "report": "tests/golden/WBV2-P595-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P596-002/manifest.json", + "report": "tests/golden/WBV2-P596-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P597-002/manifest.json", + "report": "tests/golden/WBV2-P597-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P598-002/manifest.json", + "report": "tests/golden/WBV2-P598-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P599-002/manifest.json", + "report": "tests/golden/WBV2-P599-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P600-002/manifest.json", + "report": "tests/golden/WBV2-P600-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P601-002/manifest.json", + "report": "tests/golden/WBV2-P601-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P602-002/manifest.json", + "report": "tests/golden/WBV2-P602-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P603-002/manifest.json", + "report": "tests/golden/WBV2-P603-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P604-002/manifest.json", + "report": "tests/golden/WBV2-P604-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P605-002/manifest.json", + "report": "tests/golden/WBV2-P605-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P606-002/manifest.json", + "report": "tests/golden/WBV2-P606-002/implementation-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "SCENE_OBJECT_MESH", + "task": "WBV2-P1100-002", + "owner": "SCENE_MESH", + "sourceBacked": true, + "capabilities": [ + "CAP-MESH-TOPOLOGY-FAMILY", + "CAP-CORE-SCENE-OBJECT", + "CAP-OBJECT-MOVE-COLLECTION" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P11-001/manifest.json", + "report": "tests/golden/WBV2-P11-001/mesh-topology-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P12-002/manifest.json", + "report": "tests/golden/WBV2-P12-002/scene-object-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P24-002/manifest.json", + "report": "tests/golden/WBV2-P24-002/object-move-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "MATERIAL_ANIMATION", + "task": "WBV2-P1100-003", + "owner": "MATERIAL_ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-MATERIAL-ANIMATION" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P12-003/manifest.json", + "report": "tests/golden/WBV2-P12-003/material-animation-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "NONMESH_GEOMETRY", + "task": "WBV2-P1101-000", + "owner": "GEOMETRY", + "sourceBacked": true, + "capabilities": [ + "CAP-VIEWPORT-NONMESH", + "CAP-NATIVE-DATABLOCK" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P12-004/manifest.json", + "report": "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P29-003/manifest.json", + "report": "tests/golden/WBV2-P29-003/implementation-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "NODES_SIMULATION", + "task": "WBV2-P1101-001", + "owner": "NODES_SIMULATION", + "sourceBacked": true, + "capabilities": [ + "CAP-GEOMETRY-NODES", + "CAP-SIMULATION" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-002/manifest.json", + "report": "tests/golden/WBV2-P13-002/geometry-nodes-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "ASSET_IO", + "task": "WBV2-P1101-002", + "owner": "ASSET", + "sourceBacked": true, + "capabilities": [ + "CAP-ASSET-LINK-OVERRIDE-RELOAD", + "CAP-ASSET-CATALOG-MUTATION" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P11-003/manifest.json", + "report": "tests/golden/WBV2-P11-003/asset-link-override-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P10-003/manifest.json", + "report": "tests/golden/WBV2-P10-003/module-matrix-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "SCULPT_PAINT", + "task": "WBV2-P1101-003", + "owner": "SCULPT_PAINT", + "sourceBacked": true, + "capabilities": [ + "CAP-PAINT-ATTRIBUTES", + "CAP-SCULPT-PAINT" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P16-002/manifest.json", + "report": "tests/golden/WBV2-P16-002/paint-attributes-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "UI_EDITOR", + "task": "WBV2-P1102-000", + "owner": "EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-UI-EDITOR" + ], + "reusedReceipts": [], + "fullFamilyParity": false + }, + { + "id": "INVENTORY_GATE", + "task": "WBV2-P1102-001", + "owner": "RELEASE", + "sourceBacked": true, + "capabilities": [], + "reusedReceipts": [], + "fullFamilyParity": false + }, + { + "id": "OBJECT_OPERATIONS", + "task": "WBV2-P1103-000", + "owner": "OBJECT", + "sourceBacked": true, + "capabilities": [ + "CAP-OBJECT-DUPLICATE", + "CAP-OBJECT-CREATE", + "CAP-OBJECT-PARENT", + "CAP-OBJECT-COLLECTION", + "CAP-OBJECT-RENAME", + "CAP-OBJECT-DELETE", + "CAP-OBJECT-TRANSFORM" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P17-002/manifest.json", + "report": "tests/golden/WBV2-P17-002/object-duplicate-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P18-002/manifest.json", + "report": "tests/golden/WBV2-P18-002/object-create-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P19-002/manifest.json", + "report": "tests/golden/WBV2-P19-002/object-parent-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P20-002/manifest.json", + "report": "tests/golden/WBV2-P20-002/collection-create-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P21-002/manifest.json", + "report": "tests/golden/WBV2-P21-002/object-rename-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P22-002/manifest.json", + "report": "tests/golden/WBV2-P22-002/object-delete-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P23-002/manifest.json", + "report": "tests/golden/WBV2-P23-002/object-transform-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "COMPOSITOR_SEQUENCER", + "task": "WBV2-P1104-000", + "owner": "MEDIA", + "sourceBacked": true, + "capabilities": [ + "CAP-COMPOSITOR-NODE-GRAPH", + "CAP-COMPOSITOR-UNSUPPORTED-GATE", + "CAP-SEQUENCER-MEDIA-RECOVERY" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P29-003/manifest.json", + "report": "tests/golden/WBV2-P29-003/implementation-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "AUDIO_PARTICLE", + "task": "WBV2-P1105-000", + "owner": "AUDIO_PARTICLE", + "sourceBacked": true, + "capabilities": [ + "CAP-SOUND-PROPERTIES", + "CAP-SPEAKER-PROPERTIES", + "CAP-PARTICLE-SETTINGS" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P33-001/manifest.json", + "report": "tests/golden/WBV2-P33-001/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P33-002/manifest.json", + "report": "tests/golden/WBV2-P33-002/implementation-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "RIG_ANIMATION", + "task": "WBV2-P1106-000", + "owner": "RIG", + "sourceBacked": true, + "capabilities": [ + "CAP-RIG-POSE", + "CAP-CONSTRAINTS", + "CAP-NLA-ANIMATION" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-003/manifest.json", + "report": "tests/golden/WBV2-P13-003/rig-pose-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "CORE_SCENE_GRAPH_SETTINGS", + "task": "WBV2-P1129-001", + "owner": "CORE_SCENE", + "sourceBacked": true, + "capabilities": [ + "CAP-SCENE-COMPOSITOR-SETTINGS", + "CAP-SCENE-PERFORMANCE-SETTINGS", + "CAP-SCENE-SAMPLING-SETTINGS" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P65-002/manifest.json", + "report": "tests/golden/WBV2-P65-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P66-002/manifest.json", + "report": "tests/golden/WBV2-P66-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P67-002/manifest.json", + "report": "tests/golden/WBV2-P67-002/implementation-report.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "UI_EDITOR_VIEW2D_STATE", + "task": "WBV2-P1130-001", + "owner": "EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-EDITOR-VIEW2D-CUR", + "CAP-EDITOR-VIEW2D-MASK", + "CAP-EDITOR-VIEW2D-FAIL-CLOSED" + ], + "reusedReceipts": [], + "fullFamilyParity": false + }, + { + "id": "CURVE_TOPOLOGY_EDITOR", + "task": "WBV2-P1131-001", + "owner": "EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-TOPOLOGY-TOGGLE-CYCLIC", + "CAP-CURVE-TOPOLOGY-GATE", + "CAP-CURVE-TOPOLOGY-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/M9-05/manifest.json", + "report": "tests/golden/M9-05/curve-toggle-cyclic.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "CURVE_HANDLE_GIZMO", + "task": "WBV2-P1132-001", + "owner": "EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-HANDLE-MAIN", + "CAP-CURVE-HANDLE-GIZMO-PREVIEW", + "CAP-CURVE-HANDLE-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "CURVE_SPLINES_TRANSACTION", + "task": "WBV2-P1133-001", + "owner": "EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-SPLINES-MAIN", + "CAP-CURVE-SPLINES-RECOVERY", + "CAP-CURVE-SPLINES-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "SURFACE_TOPOLOGY_TRANSACTION", + "task": "WBV2-P1134-001", + "owner": "GEOMETRY", + "sourceBacked": true, + "capabilities": [ + "CAP-SURFACE-TOPOLOGY-MAIN", + "CAP-SURFACE-NURBS-BOUNDS", + "CAP-SURFACE-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "FONT_BODY_TRANSACTION", + "task": "WBV2-P1135-001", + "owner": "GEOMETRY", + "sourceBacked": true, + "capabilities": [ + "CAP-FONT-BODY-MAIN", + "CAP-FONT-BODY-RECOVERY", + "CAP-FONT-BODY-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "FONT_PROPERTIES_TRANSACTION", + "task": "WBV2-P1136-001", + "owner": "GEOMETRY", + "sourceBacked": true, + "capabilities": [ + "CAP-FONT-PROPERTIES-MAIN", + "CAP-FONT-PROPERTIES-RECOVERY", + "CAP-FONT-PROPERTIES-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "METABALL_ELEMENTS_TRANSACTION", + "task": "WBV2-P1137-001", + "owner": "GEOMETRY", + "sourceBacked": true, + "capabilities": [ + "CAP-METABALL-ELEMENTS-MAIN", + "CAP-METABALL-ELEMENTS-RECOVERY", + "CAP-METABALL-ELEMENTS-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "TEXT_SOURCE_TRANSACTION", + "task": "WBV2-P1138-001", + "owner": "SCRIPTING", + "sourceBacked": true, + "capabilities": [ + "CAP-TEXT-SOURCE-MAIN", + "CAP-TEXT-SOURCE-RECOVERY", + "CAP-TEXT-SOURCE-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1137-001/manifest.json", + "report": "tests/golden/WBV2-P1137-001/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "TEXTURE_PROPERTIES_TRANSACTION", + "task": "WBV2-P1139-001", + "owner": "TEXTURE", + "sourceBacked": true, + "capabilities": [ + "CAP-TEXTURE-PROPERTIES-MAIN", + "CAP-TEXTURE-PROPERTIES-RECOVERY", + "CAP-TEXTURE-PROPERTIES-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1138-001/manifest.json", + "report": "tests/golden/WBV2-P1138-001/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "ACTION_GROUP_READER", + "task": "WBV2-P1140-001", + "owner": "ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-ACTION-GROUP-READER", + "CAP-ACTION-GROUP-RECOVERY", + "CAP-ACTION-GROUP-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1112-000/manifest.json", + "report": "tests/golden/WBV2-P1112-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "ACTION_POSE_MARKERS_READER", + "task": "WBV2-P1141-001", + "owner": "ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-ACTION-POSE-MARKERS-READER", + "CAP-ACTION-POSE-MARKERS-RECOVERY", + "CAP-ACTION-POSE-MARKERS-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1140-001/manifest.json", + "report": "tests/golden/WBV2-P1140-001/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "FCURVE_SAMPLE_READER", + "task": "WBV2-P1142-001", + "owner": "ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-FCURVE-SAMPLE-READER", + "CAP-FCURVE-SAMPLE-RECOVERY", + "CAP-FCURVE-SAMPLE-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1141-001/manifest.json", + "report": "tests/golden/WBV2-P1141-001/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "FCURVE_MODIFIER_READER", + "task": "WBV2-P1143-001", + "owner": "ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-FCURVE-MODIFIER-READER", + "CAP-FCURVE-MODIFIER-RECOVERY", + "CAP-FCURVE-MODIFIER-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1142-001/manifest.json", + "report": "tests/golden/WBV2-P1142-001/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "DRIVER_READER", + "task": "WBV2-P1144-001", + "owner": "ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-DRIVER-READER", + "CAP-DRIVER-RECOVERY", + "CAP-DRIVER-FAIL-CLOSED" + ], + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1143-001/manifest.json", + "report": "tests/golden/WBV2-P1143-001/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "CORRECTIVE_SMOOTH_READER", + "task": "WBV2-P1145-001", + "owner": "MODIFIER", + "sourceBacked": true, + "capabilities": [ + "CAP-CORRECTIVE-SMOOTH-READER", + "CAP-CORRECTIVE-SMOOTH-RECOVERY", + "CAP-CORRECTIVE-SMOOTH-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_correctivesmooth.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-corrective-smooth-reader-production.spec.ts", + "tests/files/web/modifier_corrective_smooth_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "MODIFIER_READER_BATCH", + "task": "WBV2-P1146-001", + "owner": "MODIFIER", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH-READER", + "CAP-MODIFIER_READER_BATCH-RECOVERY", + "CAP-MODIFIER_READER_BATCH-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_datatransfer.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_dynamicpaint.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_explode.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_fluid.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_fluid.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-production.spec.ts", + "tests/files/web/modifier_reader_batch_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "MODIFIER_READER_BATCH_TWO", + "task": "WBV2-P1147-001", + "owner": "MODIFIER", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH_TWO-READER", + "CAP-MODIFIER_READER_BATCH_TWO-RECOVERY", + "CAP-MODIFIER_READER_BATCH_TWO-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_laplaciandeform.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_laplaciansmooth.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_mask.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_shrinkwrap.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_two_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "MODIFIER_READER_BATCH_THREE", + "task": "WBV2-P1148-001", + "owner": "MODIFIER", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH_THREE-READER", + "CAP-MODIFIER_READER_BATCH_THREE-RECOVERY", + "CAP-MODIFIER_READER_BATCH_THREE-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_remesh.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_skin.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_weighted_normal.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_warp.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_three_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "fullFamilyParity": false + }, + { + "id": "MODIFIER_READER_BATCH_FOUR", + "task": "WBV2-P1149-001", + "owner": "MODIFIER", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH_FOUR-READER", + "CAP-MODIFIER_READER_BATCH_FOUR-RECOVERY", + "CAP-MODIFIER_READER_BATCH_FOUR-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvproject.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvwarp.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_normal_edit.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_volume_to_mesh.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_four_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "fullFamilyParity": false + } + ], + "tasks": [ + { + "id": "WBV2-P1096-000", + "phase": "1096", + "title": "supersede_generic_continuation_queue", + "kind": "bridge", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1095-003" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "bridge", + "gate": "QUEUE", + "card": "docs/tasks/WBV2-P1096-000.md", + "behavior": "Replace the generic continuation queue with a finite module execution plan without claiming capability parity.", + "outputs": [ + "bridge manifest", + "status" + ], + "acceptance": [ + "no parity claim", + "inventory preserved", + "module plan hash-bound" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1100-000", + "phase": "1100", + "title": "reorganize_module_execution_plan", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1096-000" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1100-000.md", + "behavior": "Reuse completed source-backed work and activate finite module-level implementation and verification.", + "outputs": [ + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "completed receipts reused", + "generic continuation excluded", + "one module active", + "inventory preserved" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1100-001", + "phase": "1100", + "title": "verify_render_light_camera_module", + "kind": "module", + "owner": "RENDER", + "dependsOn": [ + "WBV2-P1100-000" + ], + "parityId": "RENDER_LIGHT_CAMERA", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-render_light_camera", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1100-001.md", + "behavior": "Complete the RENDER_LIGHT_CAMERA module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "RENDER_LIGHT_CAMERA", + "sourceBacked": true, + "capabilities": [ + "CAP-RENDER-LIGHT-TYPE", + "CAP-RENDER-LIGHT-AREA-SHAPE", + "CAP-RENDER-LIGHT-CONTRIBUTION-FACTORS", + "CAP-RENDER-LIGHT-SHADOW-CONTROLS", + "CAP-RENDER-LIGHT-CASCADE-CONTROLS", + "CAP-RENDER-LIGHT-AREA-SIZE-Z", + "CAP-RENDER-LIGHT-CLIP-START", + "CAP-RENDER-WORLD-LIGHTING-CONTROLS", + "CAP-RENDER-WORLD-PROBE-CONTROLS", + "CAP-RENDER-WORLD-ENVIRONMENT-STRENGTH", + "CAP-RENDER-CAMERA-DOF-FOCUS-OBJECT", + "CAP-RENDER-CAMERA-PANORAMA" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P595-002/manifest.json", + "report": "tests/golden/WBV2-P595-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P596-002/manifest.json", + "report": "tests/golden/WBV2-P596-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P597-002/manifest.json", + "report": "tests/golden/WBV2-P597-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P598-002/manifest.json", + "report": "tests/golden/WBV2-P598-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P599-002/manifest.json", + "report": "tests/golden/WBV2-P599-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P600-002/manifest.json", + "report": "tests/golden/WBV2-P600-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P601-002/manifest.json", + "report": "tests/golden/WBV2-P601-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P602-002/manifest.json", + "report": "tests/golden/WBV2-P602-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P603-002/manifest.json", + "report": "tests/golden/WBV2-P603-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P604-002/manifest.json", + "report": "tests/golden/WBV2-P604-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P605-002/manifest.json", + "report": "tests/golden/WBV2-P605-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P606-002/manifest.json", + "report": "tests/golden/WBV2-P606-002/implementation-report.json" + } + ], + "positive": [ + "setLightProperties", + "setWorldProperties", + "setCameraProperties", + "camera panorama", + "world environment", + "light shadow/cascade" + ], + "negative": [ + "invalid enum", + "invalid numeric bounds", + "near/far conflict", + "unknown target", + "stale revision" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker disposal" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run test:lighting-field-roundtrip", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-lighting-fields-production.spec.ts tests/e2e/lighting-field-roundtrip.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1100-002", + "phase": "1100", + "title": "verify_scene_object_mesh_module", + "kind": "module", + "owner": "SCENE_MESH", + "dependsOn": [ + "WBV2-P1100-001" + ], + "parityId": "SCENE_OBJECT_MESH", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-scene_object_mesh", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1100-002.md", + "behavior": "Complete the SCENE_OBJECT_MESH module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SCENE_OBJECT_MESH", + "sourceBacked": true, + "capabilities": [ + "CAP-MESH-TOPOLOGY-FAMILY", + "CAP-CORE-SCENE-OBJECT", + "CAP-OBJECT-MOVE-COLLECTION" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P11-001/manifest.json", + "report": "tests/golden/WBV2-P11-001/mesh-topology-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P12-002/manifest.json", + "report": "tests/golden/WBV2-P12-002/scene-object-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P24-002/manifest.json", + "report": "tests/golden/WBV2-P24-002/object-move-receipt-report.json" + } + ], + "positive": [ + "mesh topology", + "visibility", + "transform", + "collection membership" + ], + "negative": [ + "invalid selection", + "stale revision", + "linked data" + ], + "recovery": [ + "undo", + "redo", + "save/reopen" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-mesh-topology-production.spec.ts tests/e2e/wbv2-scene-object-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1100-003", + "phase": "1100", + "title": "verify_material_animation_module", + "kind": "module", + "owner": "MATERIAL_ANIMATION", + "dependsOn": [ + "WBV2-P1100-002" + ], + "parityId": "MATERIAL_ANIMATION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-material_animation", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1100-003.md", + "behavior": "Complete the MATERIAL_ANIMATION module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "MATERIAL_ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-MATERIAL-ANIMATION" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P12-003/manifest.json", + "report": "tests/golden/WBV2-P12-003/material-animation-receipt-report.json" + } + ], + "positive": [ + "principled material", + "image node", + "keyframe", + "FCurve" + ], + "negative": [ + "unsupported graph", + "stale revision" + ], + "recovery": [ + "undo", + "redo", + "save/reopen" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-material-animation-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1101-000", + "phase": "1101", + "title": "verify_nonmesh_geometry_module", + "kind": "module", + "owner": "GEOMETRY", + "dependsOn": [ + "WBV2-P1100-003" + ], + "parityId": "NONMESH_GEOMETRY", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-nonmesh_geometry", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1101-000.md", + "behavior": "Complete the NONMESH_GEOMETRY module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "NONMESH_GEOMETRY", + "sourceBacked": true, + "capabilities": [ + "CAP-VIEWPORT-NONMESH", + "CAP-NATIVE-DATABLOCK" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P12-004/manifest.json", + "report": "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P29-003/manifest.json", + "report": "tests/golden/WBV2-P29-003/implementation-report.json" + } + ], + "positive": [ + "curve", + "surface", + "font", + "volume", + "metaball", + "grease pencil" + ], + "negative": [ + "unsupported data", + "resource missing", + "malformed geometry" + ], + "recovery": [ + "save/reopen", + "resource disposal" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-viewport-nonmesh-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1101-001", + "phase": "1101", + "title": "verify_nodes_simulation_module", + "kind": "module", + "owner": "NODES_SIMULATION", + "dependsOn": [ + "WBV2-P1101-000" + ], + "parityId": "NODES_SIMULATION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-nodes_simulation", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1101-001.md", + "behavior": "Complete the NODES_SIMULATION module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "NODES_SIMULATION", + "sourceBacked": true, + "capabilities": [ + "CAP-GEOMETRY-NODES", + "CAP-SIMULATION" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-002/manifest.json", + "report": "tests/golden/WBV2-P13-002/geometry-nodes-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "positive": [ + "allowlisted node graph", + "physics manifest", + "stable hash" + ], + "negative": [ + "unsupported node", + "budget exceeded", + "stale revision" + ], + "recovery": [ + "save/reopen", + "cache disposal" + ], + "commands": [ + "npm --prefix web run test:geometry-node-main-reader", + "npm --prefix web run test:physics-main-reader" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1101-002", + "phase": "1101", + "title": "verify_asset_io_module", + "kind": "module", + "owner": "ASSET", + "dependsOn": [ + "WBV2-P1101-001" + ], + "parityId": "ASSET_IO", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-asset_io", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1101-002.md", + "behavior": "Complete the ASSET_IO module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "ASSET_IO", + "sourceBacked": true, + "capabilities": [ + "CAP-ASSET-LINK-OVERRIDE-RELOAD", + "CAP-ASSET-CATALOG-MUTATION" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P11-003/manifest.json", + "report": "tests/golden/WBV2-P11-003/asset-link-override-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P10-003/manifest.json", + "report": "tests/golden/WBV2-P10-003/module-matrix-receipt-report.json" + } + ], + "positive": [ + "append", + "link", + "override", + "reload", + "asset catalog v2" + ], + "negative": [ + "missing source", + "ownership violation", + "hash drift", + "collision" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "IndexedDB restart" + ], + "commands": [ + "npm --prefix web run test:asset-catalog-v2", + "npm --prefix web run test:asset-catalog-migration", + "npm --prefix web run test:asset-catalog-negatives", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-asset-link-override-production.spec.ts tests/e2e/wbv2-asset-catalog-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1101-003", + "phase": "1101", + "title": "verify_sculpt_paint_module", + "kind": "module", + "owner": "SCULPT_PAINT", + "dependsOn": [ + "WBV2-P1101-002" + ], + "parityId": "SCULPT_PAINT", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-sculpt_paint", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1101-003.md", + "behavior": "Complete the SCULPT_PAINT module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SCULPT_PAINT", + "sourceBacked": true, + "capabilities": [ + "CAP-PAINT-ATTRIBUTES", + "CAP-SCULPT-PAINT" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P16-002/manifest.json", + "report": "tests/golden/WBV2-P16-002/paint-attributes-receipt-report.json" + } + ], + "positive": [ + "vertex colors", + "vertex weights", + "bounded sculpt stroke" + ], + "negative": [ + "mirror unverified", + "invalid patch", + "unsupported brush" + ], + "recovery": [ + "undo", + "redo", + "save/reopen" + ], + "commands": [ + "npm --prefix web run test:paint-roundtrip", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-paint-attributes-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1102-000", + "phase": "1102", + "title": "implement_ui_editor_module", + "kind": "module", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1101-003" + ], + "parityId": "UI_EDITOR", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-ui_editor", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1102-000.md", + "behavior": "Complete the UI_EDITOR module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "UI_EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-UI-EDITOR" + ], + "sourcePaths": [ + "web/protocol/editor-workflow.ts", + "web/app/src/app/App.tsx", + "web/app/src/workers/web-engine.worker.ts" + ], + "reuseReceipts": [], + "positive": [ + "editor context", + "workspace", + "area/region" + ], + "negative": [ + "unsupported editor", + "invalid context" + ], + "recovery": [ + "worker restart", + "save/reopen" + ], + "commands": [ + "npm --prefix web run test:editor-main-reader", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/ui-editor-workflow-production.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1102-001", + "phase": "1102", + "title": "close_module_execution_gate", + "kind": "module", + "owner": "RELEASE", + "dependsOn": [ + "WBV2-P1102-000" + ], + "parityId": "INVENTORY_GATE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-inventory_gate", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1102-001.md", + "behavior": "Complete the INVENTORY_GATE module through its shared Blender Main primitives and aggregate case matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "INVENTORY_GATE", + "sourceBacked": true, + "capabilities": [], + "sourcePaths": [ + "tests/golden/WBV2-P0-002/parity-map.json", + "tests/golden/WBV2-P1100-000/module-execution-plan.json" + ], + "reuseReceipts": [], + "positive": [ + "aggregate module receipts", + "catalog hash" + ], + "negative": [ + "missing receipt", + "hash drift", + "false completion" + ], + "recovery": [ + "re-run affected module only" + ], + "commands": [ + "node tools/web/check-wbv2-module-execution.mjs", + "npm --prefix web run build" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1103-000", + "phase": "1103", + "title": "aggregate_object_operations_module", + "kind": "module", + "owner": "OBJECT", + "dependsOn": [ + "WBV2-P1102-001" + ], + "parityId": "OBJECT_OPERATIONS", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-object_operations", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1103-000.md", + "behavior": "Aggregate the existing source-backed Object Main operations into one module and revalidate the Chromium operator matrix.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "OBJECT_OPERATIONS", + "sourceBacked": true, + "capabilities": [ + "CAP-OBJECT-DUPLICATE", + "CAP-OBJECT-CREATE", + "CAP-OBJECT-PARENT", + "CAP-OBJECT-COLLECTION", + "CAP-OBJECT-RENAME", + "CAP-OBJECT-DELETE", + "CAP-OBJECT-TRANSFORM" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P17-002/manifest.json", + "report": "tests/golden/WBV2-P17-002/object-duplicate-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P18-002/manifest.json", + "report": "tests/golden/WBV2-P18-002/object-create-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P19-002/manifest.json", + "report": "tests/golden/WBV2-P19-002/object-parent-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P20-002/manifest.json", + "report": "tests/golden/WBV2-P20-002/collection-create-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P21-002/manifest.json", + "report": "tests/golden/WBV2-P21-002/object-rename-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P22-002/manifest.json", + "report": "tests/golden/WBV2-P22-002/object-delete-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P23-002/manifest.json", + "report": "tests/golden/WBV2-P23-002/object-transform-receipt-report.json" + } + ], + "positive": [ + "duplicate", + "create", + "parent", + "collection", + "rename", + "delete", + "transform apply" + ], + "negative": [ + "unknown object", + "invalid parent cycle", + "malformed transform" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic second run" + ], + "commands": [ + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-object-duplicate-production.spec.ts tests/e2e/wbv2-object-create-production.spec.ts tests/e2e/wbv2-object-parent-production.spec.ts tests/e2e/wbv2-collection-create-production.spec.ts tests/e2e/wbv2-object-rename-production.spec.ts tests/e2e/wbv2-object-delete-production.spec.ts tests/e2e/wbv2-object-transform-production.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1104-000", + "phase": "1104", + "title": "verify_compositor_sequencer_module", + "kind": "module", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P1103-000" + ], + "parityId": "COMPOSITOR_SEQUENCER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-compositor_sequencer", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1104-000.md", + "behavior": "Verify the source-backed compositor and sequencer module through golden, unsupported-gate and media recovery cases.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main or compositor mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "COMPOSITOR_SEQUENCER", + "sourceBacked": true, + "capabilities": [ + "CAP-COMPOSITOR-NODE-GRAPH", + "CAP-COMPOSITOR-UNSUPPORTED-GATE", + "CAP-SEQUENCER-MEDIA-RECOVERY" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/compositor.ts", + "web/protocol/sequencer.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P29-003/manifest.json", + "report": "tests/golden/WBV2-P29-003/implementation-report.json" + } + ], + "positive": [ + "compositor node graph", + "sequencer still-image timeline", + "media cache contract" + ], + "negative": [ + "unsupported compositor node", + "invalid sequencer strip", + "stale media revision" + ], + "recovery": [ + "worker restart", + "save/reopen", + "media cache replay", + "movie codec blocked without READY receipt" + ], + "commands": [ + "npm --prefix web run test:compositor-node-golden", + "npm --prefix web run test:compositor-unsupported-gate", + "npm --prefix web run test:sequencer-main-reader", + "node --test web/tests/unit/sequencer-media-cache.test.mjs", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/smoke.spec.ts -g \"N-021 sequencer|real Blender 5.2 sequencer\"", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1105-000", + "phase": "1105", + "title": "verify_audio_particle_module", + "kind": "module", + "owner": "AUDIO_PARTICLE", + "dependsOn": [ + "WBV2-P1104-000" + ], + "parityId": "AUDIO_PARTICLE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-audio_particle", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1105-000.md", + "behavior": "Verify Sound, Speaker and ParticleSettings mutations against authoritative Blender Main with explicit build capability gates.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven or a typed build capability blocker is recorded", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "AUDIO_PARTICLE", + "sourceBacked": true, + "capabilities": [ + "CAP-SOUND-PROPERTIES", + "CAP-SPEAKER-PROPERTIES", + "CAP-PARTICLE-SETTINGS" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/protocol/io-media-commands.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P33-001/manifest.json", + "report": "tests/golden/WBV2-P33-001/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P33-002/manifest.json", + "report": "tests/golden/WBV2-P33-002/implementation-report.json" + } + ], + "positive": [ + "Sound properties", + "Speaker properties", + "ParticleSettings properties" + ], + "negative": [ + "missing Main datablock", + "unsupported build feature", + "out-of-range property" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker restart" + ], + "commands": [ + "cmake --build build_web_blender6 --target web_engine -- -j8", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-audio-particle-production.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1106-000", + "phase": "1106", + "title": "verify_rig_animation_module", + "kind": "module", + "owner": "RIG", + "dependsOn": [ + "WBV2-P1105-000" + ], + "parityId": "RIG_ANIMATION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-rig_animation", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1106-000.md", + "behavior": "Verify armature pose, constraints and NLA animation through the existing Blender Main primitives.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "RIG_ANIMATION", + "sourceBacked": true, + "capabilities": [ + "CAP-RIG-POSE", + "CAP-CONSTRAINTS", + "CAP-NLA-ANIMATION" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/web-engine.ts", + "web/protocol/nla.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-003/manifest.json", + "report": "tests/golden/WBV2-P13-003/rig-pose-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "positive": [ + "armature pose", + "constraint edit", + "NLA stack" + ], + "negative": [ + "missing bone", + "invalid constraint influence", + "stale NLA revision" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic second run" + ], + "commands": [ + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-rig-pose-production.spec.ts", + "npm --prefix web run test:nla-operator", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1107-000", + "phase": "1107", + "title": "verify_modifier_system_module", + "kind": "module", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P1106-000" + ], + "parityId": "MODIFIER_SYSTEM", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-modifier_system", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1107-000.md", + "behavior": "Verify modifier stack visibility and bounded parameter mutation through authoritative Blender Main.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "MODIFIER_SYSTEM", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER-STATE-MUTATION", + "CAP-MODIFIER-PARAMETER-EDIT", + "CAP-MODIFIER-STACK-READER" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/protocol/modifier-graph.ts", + "web/protocol/depsgraph.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P9-002/manifest.json", + "report": "tests/golden/WBV2-P9-002/modifier-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P11-002/manifest.json", + "report": "tests/golden/WBV2-P11-002/modifier-parameter-receipt-report.json" + } + ], + "positive": [ + "modifier visibility toggle", + "bounded DECIMATE parameter mutation", + "modifier stack evaluation reader" + ], + "negative": [ + "unknown modifier UUID", + "stale mesh revision", + "out-of-range parameter" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic second run" + ], + "commands": [ + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-production.spec.ts tests/e2e/wbv2-modifier-parameter-production.spec.ts", + "npm --prefix web run test:modifier-goldens", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1108-000", + "phase": "1108", + "title": "verify_nodes_graph_module", + "kind": "module", + "owner": "NODES", + "dependsOn": [ + "WBV2-P1107-000" + ], + "parityId": "NODES_GRAPH", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-nodes_graph", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1108-000.md", + "behavior": "Verify Geometry Nodes graph identity, allowlisted evaluation, field budgets and unsupported graph retention.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive graph reader/evaluation evidence is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "NODES_GRAPH", + "sourceBacked": true, + "capabilities": [ + "CAP-GEOMETRY-NODES-GRAPH", + "CAP-GEOMETRY-NODES-ALLOWLIST", + "CAP-GEOMETRY-NODES-FIELD-BUDGET" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/protocol/geometry-nodes.ts", + "web/protocol/geometry-node-commands.ts", + "web/protocol/depsgraph.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-002/manifest.json", + "report": "tests/golden/WBV2-P13-002/geometry-nodes-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "positive": [ + "allowlisted graph identity", + "Blender depsgraph geometry evaluation", + "field materialization with exact domain cardinality" + ], + "negative": [ + "unsupported node graph", + "field budget overflow", + "stale or invalid graph command" + ], + "recovery": [ + "save/reopen", + "worker restart", + "graph retention after rejected command", + "deterministic second run" + ], + "commands": [ + "npm --prefix web run test:geometry-node-evaluator-golden", + "npm --prefix web run test:geometry-node-field-budget", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-geometry-nodes-production.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1109-000", + "phase": "1109", + "title": "verify_io_format_module", + "kind": "module", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P1108-000" + ], + "parityId": "IO_FORMAT", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-io_format", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1109-000.md", + "behavior": "Verify format capability routing, runtime receipts, recovery and fail-closed file UI gates.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive format routing/readiness evidence is proven", + "negative and recovery cases are proven", + "Chromium and deterministic recovery receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "IO_FORMAT", + "sourceBacked": true, + "capabilities": [ + "CAP-IO-FORMAT-CAPABILITY-MATRIX", + "CAP-IO-FORMAT-RUNTIME-RECEIPTS", + "CAP-IO-FORMAT-RECOVERY", + "CAP-IO-FORMAT-UI-GATE" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/asset-library-io.ts", + "web/protocol/io-format-capability-matrix.ts", + "web/protocol/io-format-receipt-binding.ts", + "web/protocol/io-format-runtime-receipt.ts", + "web/protocol/io-format-recovery.ts", + "web/protocol/io-format-ui-gate.ts", + "web/protocol/glb-export.ts", + "web/protocol/glb-import.ts", + "web/protocol/nonmesh-export.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [], + "positive": [ + "GLB export readiness", + "format runtime receipt inventory", + "declared .blend import route" + ], + "negative": [ + "unverified format route", + "cancelled or OOM operation", + "unsupported file extension" + ], + "recovery": [ + "worker restart", + "small operation recovery", + "deterministic receipt replay", + "fail-closed UI route" + ], + "commands": [ + "node tools/web/check-io-format-receipt-bindings.mjs", + "node tools/web/check-io-format-runtime-receipts.mjs", + "node tools/web/check-io-format-recovery.mjs", + "node tools/web/check-io-format-ui-gate.mjs", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/io-format-recovery.spec.ts tests/e2e/io-format-ui-gate.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1110-000", + "phase": "1110", + "title": "verify_render_pipeline_module", + "kind": "module", + "owner": "RENDER", + "dependsOn": [ + "WBV2-P1109-000" + ], + "parityId": "RENDER_PIPELINE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-render_pipeline", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1110-000.md", + "behavior": "Verify render backend routing, explicit resource budgets and Blender reference comparison in Chromium.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive render/reference evidence is proven", + "negative and recovery cases are proven", + "Chromium and deterministic render receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "RENDER_PIPELINE", + "sourceBacked": true, + "capabilities": [ + "CAP-RENDER-BACKEND-ROUTING", + "CAP-RENDER-RESOURCE-BUDGET", + "CAP-RENDER-REFERENCE-COMPARISON" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/render-routing.ts", + "web/protocol/render-budget.ts", + "web/protocol/render-capabilities.ts", + "web/protocol/render-image-comparison.ts", + "web/protocol/server-render-job.ts", + "web/app/src/three-adapter/render-routing.ts", + "web/app/src/three-adapter/render-image-comparison.ts", + "web/app/src/workers/viewport-render.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [], + "positive": [ + "bounded local backend routing", + "reference render metrics", + "resource budget acceptance" + ], + "negative": [ + "unknown or unavailable backend", + "aggregate texture/light budget overflow", + "wrong composition reference" + ], + "recovery": [ + "retain previous texture set", + "offscreen renderer parity", + "worker restart", + "deterministic second render" + ], + "commands": [ + "npm --prefix web run test:render-resource-budget", + "npm --prefix web run test:render-routing", + "npm --prefix web run test:render-reference", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1111-000", + "phase": "1111", + "title": "verify_scripting_security_module", + "kind": "module", + "owner": "SCRIPTING", + "dependsOn": [ + "WBV2-P1110-000" + ], + "parityId": "SCRIPTING_SECURITY", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-scripting_security", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1111-000.md", + "behavior": "Verify script source Main reader, deny-by-default permission policy and sandbox isolation/recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive reader and policy evidence is proven", + "negative and recovery cases are proven", + "Chromium sandbox receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SCRIPTING_SECURITY", + "sourceBacked": true, + "capabilities": [ + "CAP-SCRIPT-MAIN-READER", + "CAP-SCRIPT-PERMISSION-POLICY", + "CAP-SCRIPT-SANDBOX-ISOLATION", + "CAP-SCRIPT-SANDBOX-RECOVERY" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/scene-ir.ts", + "web/protocol/scripting-platform.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/workers/script-permission-policy-test.worker.ts", + "web/app/src/workers/script-sandbox-isolation-test.worker.ts", + "web/app/src/workers/script-sandbox-recovery-test.worker.ts", + "web/app/src/testing/script-sandbox-recovery.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [], + "positive": [ + "script source inventory reader", + "explicit READ_MAIN permission", + "new-generation recovery audit" + ], + "negative": [ + "autorun denied by default", + "undeclared permission", + "sandbox crash/timeout/late result" + ], + "recovery": [ + "worker restart", + "sandbox generation rollover", + "continuous audit chain", + "deterministic second run" + ], + "commands": [ + "npm --prefix web run test:script-main-reader", + "npm --prefix web run test:scripting-isolation", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/script-permission-policy.spec.ts tests/e2e/script-sandbox-isolation.spec.ts tests/e2e/script-sandbox-recovery.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1112-000", + "phase": "1112", + "title": "verify_animation_timeline_module", + "kind": "module", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1111-000" + ], + "parityId": "ANIMATION_TIMELINE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-animation_timeline", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1112-000.md", + "behavior": "Verify frame evaluation and NLA time mapping through the production Worker and Blender Main.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive frame/NLA evaluation is proven", + "negative and recovery cases are proven", + "Chromium and deterministic evaluation receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "ANIMATION_TIMELINE", + "sourceBacked": true, + "capabilities": [ + "CAP-FRAME-EVALUATION", + "CAP-NLA-TIME-MAPPING", + "CAP-ANIMATION-SAVE-REOPEN" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/protocol/nla.ts", + "web/protocol/depsgraph.ts", + "web/protocol/scene-ir.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "positive": [ + "frame 1/5/10 evaluation", + "NLA track and strip mapping", + "Blender depsgraph animation result" + ], + "negative": [ + "stale NLA revision", + "invalid strip topology", + "unsupported animation domain" + ], + "recovery": [ + "save/reopen", + "worker restart", + "deterministic repeated evaluation", + "preserve rejected stack" + ], + "commands": [ + "npm --prefix web run test:frame-evaluation", + "node tools/web/check-nla-evaluation-golden.mjs", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/nla-evaluation-golden.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1113-000", + "phase": "1113", + "title": "verify_shader_material_module", + "kind": "module", + "owner": "MATERIAL", + "dependsOn": [ + "WBV2-P1112-000" + ], + "parityId": "SHADER_MATERIAL", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-shader_material", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1113-000.md", + "behavior": "Verify bounded Shader graph compilation, stable compile keys and fail-closed pipeline recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Shader Main compilation is proven", + "negative and recovery cases are proven", + "Chromium and deterministic compile receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SHADER_MATERIAL", + "sourceBacked": true, + "capabilities": [ + "CAP-SHADER-GRAPH-COMPILER", + "CAP-SHADER-COMPILE-KEY", + "CAP-SHADER-FAIL-CLOSED-RECOVERY" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/protocol/shader-graph.ts", + "web/protocol/shader-graph-commands.ts", + "web/protocol/shader-compiler.ts", + "web/protocol/render-capabilities.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [], + "positive": [ + "Principled/Image/Normal/Math graph compile", + "stable compile key", + "real Main shader material path" + ], + "negative": [ + "unknown shader node", + "graph cycle or duplicate link", + "unsupported renderer backend" + ], + "recovery": [ + "retain previous material after compile failure", + "worker restart", + "deterministic repeated compile", + "save/reopen material graph" + ], + "commands": [ + "npm --prefix web run test:shader-compile", + "npm --prefix web run test:shader-pipeline", + "npm --prefix web run test:shader-capability", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1114-000", + "phase": "1114", + "title": "verify_grease_pencil_module", + "kind": "module", + "owner": "DRAWING", + "dependsOn": [ + "WBV2-P1113-000" + ], + "parityId": "GREASE_PENCIL", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-grease_pencil", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1114-000.md", + "behavior": "Verify Grease Pencil layer/frame Main mutations, stable identity validation and roundtrip recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Grease Pencil Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "GREASE_PENCIL", + "sourceBacked": true, + "capabilities": [ + "CAP-GREASE-PENCIL-LAYER-FRAME", + "CAP-GREASE-PENCIL-STROKE-READER", + "CAP-GREASE-PENCIL-ROUNDTRIP" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/protocol/grease-pencil.ts", + "web/protocol/grease-pencil-reorder.ts", + "web/protocol/grease-pencil-selection.ts", + "web/protocol/grease-pencil-marquee.ts", + "web/app/src/app/App.tsx", + "web/app/src/three-adapter/grease-pencil.ts", + "web/app/src/three-adapter/viewport.ts", + "web/app/src/three-adapter/offscreen-viewport.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [], + "positive": [ + "create and reorder layer", + "insert and move frame", + "stable Grease Pencil drawing reader" + ], + "negative": [ + "forged drawing identity", + "occupied frame target", + "stale layer/frame revision" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic layer/frame replay" + ], + "commands": [ + "npm --prefix web run test:grease-pencil-reorder", + "npm --prefix web run test:grease-pencil", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1115-000", + "phase": "1115", + "title": "verify_curve_surface_editing_module", + "kind": "module", + "owner": "GEOMETRY", + "dependsOn": [ + "WBV2-P1114-000" + ], + "parityId": "CURVE_SURFACE_EDITING", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-curve_surface_editing", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1115-000.md", + "behavior": "Verify Curve topology/handle edits, Surface topology and non-mesh/font roundtrip through Blender Main.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive non-mesh Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "CURVE_SURFACE_EDITING", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-TOPOLOGY-HANDLES", + "CAP-SURFACE-TOPOLOGY", + "CAP-NONMESH-FONT-ROUNDTRIP" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/web-engine.ts", + "web/protocol/nonmesh-geometry-commands.ts", + "web/protocol/curve-topology-editor.ts", + "web/protocol/non-mesh.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P12-004/manifest.json", + "report": "tests/golden/WBV2-P12-004/viewport-nonmesh-receipt-report.json" + } + ], + "positive": [ + "Curve control point and handle edit", + "Curve cyclic/topology operator", + "Surface and Font property mutation" + ], + "negative": [ + "invalid curve selection/domain", + "occupied or stale frame/topology target", + "malformed non-mesh property" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic multispline replay" + ], + "commands": [ + "npm --prefix web run test:curve-topology-operator", + "npm --prefix web run test:nonmesh-roundtrip", + "npm --prefix web run test:nonmesh-desktop-golden", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1116-000", + "phase": "1116", + "title": "verify_storage_recovery_module", + "kind": "module", + "owner": "STORAGE", + "dependsOn": [ + "WBV2-P1115-000" + ], + "parityId": "STORAGE_RECOVERY", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-storage_recovery", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1116-000.md", + "behavior": "Verify IndexedDB catalog migration/restart and OPFS asset preview deduplication, quarantine and reference GC.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive storage commit/recovery evidence is proven", + "negative and quarantine cases are proven", + "Chromium restart receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "STORAGE_RECOVERY", + "sourceBacked": true, + "capabilities": [ + "CAP-INDEXEDDB-CATALOG-MIGRATION", + "CAP-OPFS-PREVIEW-COMMIT", + "CAP-OPFS-QUARANTINE-GC" + ], + "sourcePaths": [ + "web/protocol/storage.ts", + "web/protocol/storage-budget.ts", + "web/protocol/save-transaction.ts", + "web/protocol/recent-projects.ts", + "web/protocol/asset-preview.ts", + "web/protocol/asset-preview-decode.ts", + "web/app/src/storage/asset-catalog-indexeddb.ts", + "web/app/src/storage/asset-preview-opfs-commit.ts", + "web/app/src/storage/asset-preview-quarantine.ts", + "web/app/src/storage/asset-preview-reference-gc.ts", + "web/app/src/storage/opfs-files.ts", + "web/app/src/storage/migrations.ts", + "web/app/src/workers/storage.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [], + "positive": [ + "v1 to v2 catalog migration", + "page/Worker restart identity", + "content-addressed preview deduplication" + ], + "negative": [ + "partial catalog migration", + "corrupt preview quarantine", + "cross-project or non-final reference GC" + ], + "recovery": [ + "IndexedDB restart", + "OPFS commit replay", + "quarantine cleanup", + "deterministic reference reclamation" + ], + "commands": [ + "npm --prefix web run test:asset-catalog-restart", + "npm --prefix web run test:asset-preview-dedup", + "npm --prefix web run test:asset-preview-quarantine", + "npm --prefix web run test:asset-preview-reference-gc", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1117-000", + "phase": "1117", + "title": "verify_simulation_cache_module", + "kind": "module", + "owner": "SIMULATION", + "dependsOn": [ + "WBV2-P1116-000" + ], + "parityId": "SIMULATION_CACHE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-simulation_cache", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1117-000.md", + "behavior": "Verify simulation cache identity, physics-family payload integrity, lifecycle recovery and deterministic LRU pruning.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive cache identity/lifecycle evidence is proven", + "negative integrity and budget cases are proven", + "Chromium restart and quarantine receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SIMULATION_CACHE", + "sourceBacked": true, + "capabilities": [ + "CAP-SIMULATION-CACHE-IDENTITY", + "CAP-PHYSICS-CACHE-INTEGRITY", + "CAP-SIMULATION-CACHE-RECOVERY" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/simulation-cache.ts", + "web/protocol/physics-simulation.ts", + "web/protocol/physics-cache-playback.ts", + "web/protocol/storage.ts", + "web/app/src/workers/storage.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P13-004/manifest.json", + "report": "tests/golden/WBV2-P13-004/advanced-domain-receipt-report.json" + } + ], + "positive": [ + "graph/source/revision cache identity", + "all physics-family frame hashes", + "verified playback lifecycle" + ], + "negative": [ + "source or payload hash drift", + "revision/range mismatch", + "cache byte/frame budget overflow" + ], + "recovery": [ + "cancel and cleanup", + "LRU prune with protected playback", + "corruption quarantine", + "worker restart" + ], + "commands": [ + "npm --prefix web run test:simulation-cache-identity", + "npm --prefix web run test:simulation-cache-lifecycle", + "npm --prefix web run test:physics-cache-family", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1118-000", + "phase": "1118", + "title": "verify_ui_input_interaction_module", + "kind": "module", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1117-000" + ], + "parityId": "UI_INPUT_INTERACTION", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-ui_input_interaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1118-000.md", + "behavior": "Verify keyboard-only user actions, input mutex, IME/pointer state and responsive editor interaction under deployment CSP.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive keyboard Main mutation and save are proven", + "negative mutex/input cases are proven", + "Chromium accessibility and responsive receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "UI_INPUT_INTERACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-KEYBOARD-USER-ACTIONS", + "CAP-INPUT-MODAL-STATE", + "CAP-IME-SHORTCUT-GUARD", + "CAP-RESPONSIVE-CSP-UI" + ], + "sourcePaths": [ + "web/app/index.html", + "web/app/src/app/App.tsx", + "web/app/src/app/app-shell.css", + "web/app/src/workers/web-engine.worker.ts", + "web/protocol/user-action-state.ts", + "web/protocol/project-action-mutex.ts", + "web/protocol/ime-composition.ts", + "web/protocol/input-modal.ts", + "web/protocol/pointer-contract.ts", + "web/protocol/worker-fault.ts", + "web/tests/unit/user-action-state.test.mjs", + "web/tests/unit/project-action-mutex.test.mjs", + "web/tests/unit/ime-composition.test.mjs", + "web/tests/unit/input-modal.test.mjs", + "web/tests/unit/pointer-contract.test.mjs" + ], + "reuseReceipts": [], + "positive": [ + "keyboard-only Add Cube Main mutation", + "keyboard save/reopen and GLB export", + "responsive controls at desktop/mobile viewports" + ], + "negative": [ + "concurrent project action mutex", + "IME shortcut suppression", + "pointer cancel/touch modal cleanup" + ], + "recovery": [ + "worker restart", + "save interruption recovery", + "responsive layout preservation", + "deterministic repeated keyboard loop" + ], + "commands": [ + "node --test web/tests/unit/user-action-state.test.mjs web/tests/unit/project-action-mutex.test.mjs web/tests/unit/ime-composition.test.mjs web/tests/unit/input-modal.test.mjs web/tests/unit/pointer-contract.test.mjs", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/user-action-state.spec.ts tests/e2e/project-action-mutex.spec.ts tests/e2e/keyboard-accessibility.spec.ts tests/e2e/responsive-layout.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1119-000", + "phase": "1119", + "title": "verify_library_workflow_module", + "kind": "module", + "owner": "ASSET", + "dependsOn": [ + "WBV2-P1118-000" + ], + "parityId": "LIBRARY_WORKFLOW", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-library_workflow", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1119-000.md", + "behavior": "Verify append, link, override and reload library flows through authoritative Main with path and dependency safety gates.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive library Main mutation is proven", + "negative and recovery cases are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "LIBRARY_WORKFLOW", + "sourceBacked": true, + "capabilities": [ + "CAP-LIBRARY-APPEND", + "CAP-LIBRARY-LINK", + "CAP-LIBRARY-OVERRIDE", + "CAP-LIBRARY-RELOAD-SAFETY" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/library-main-append.ts", + "web/protocol/library-linked-mutation.ts", + "web/protocol/library-linked-reload.ts", + "web/protocol/library-linked-missing.ts", + "web/protocol/library-override-writer.ts", + "web/protocol/library-override-freshness.ts", + "web/protocol/library-negative-cases.ts", + "web/protocol/library-operation-identity.ts", + "web/protocol/library-source-origin.ts", + "web/protocol/asset-path.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P11-003/manifest.json", + "report": "tests/golden/WBV2-P11-003/asset-link-override-receipt-report.json" + }, + { + "manifest": "tests/golden/WBV2-P9-003/manifest.json", + "report": "tests/golden/WBV2-P9-003/asset-catalog-receipt-report.json" + } + ], + "positive": [ + "append object into Main", + "linked read-only object", + "local override and reload identity" + ], + "negative": [ + "missing library source", + "dependency/cross-library cycle", + "unsafe path or ownership mutation" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic library replay" + ], + "commands": [ + "npm --prefix web run test:library-main-append", + "npm --prefix web run test:library-link-chromium", + "npm --prefix web run test:library-override-chromium", + "npm --prefix web run test:library-negative-cases", + "npm --prefix web run test:library-path-security", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1120-000", + "phase": "1120", + "title": "verify_volume_nanovdb_module", + "kind": "module", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P1119-000" + ], + "parityId": "VOLUME_NANOVDB", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-volume_nanovdb", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1120-000.md", + "behavior": "Verify NanoVDB manifest, paged feedback, OPFS commit/restart and production viewport volume roundtrip.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive volume resource and viewport evidence is proven", + "negative and recovery cases are proven", + "Chromium OPFS/restart receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "VOLUME_NANOVDB", + "sourceBacked": true, + "capabilities": [ + "CAP-NANOVDB-MANIFEST", + "CAP-NANOVDB-PAGED-FEEDBACK", + "CAP-NANOVDB-OPFS-RESTART", + "CAP-NANOVDB-VIEWPORT-ROUNDTRIP" + ], + "sourcePaths": [ + "web/protocol/volume-vdb.ts", + "web/protocol/nanovdb-page-feedback.ts", + "web/protocol/nanovdb-device-recovery.ts", + "web/protocol/storage.ts", + "web/app/src/volume/nanovdb-opfs.ts", + "web/app/src/volume/nanovdb-stream.ts", + "web/app/src/volume/nanovdb-viewport.ts", + "web/app/src/volume/nanovdb-float32.ts", + "web/app/src/render/nanovdb-volume-renderer.ts", + "web/app/src/workers/vdb-opfs-test.worker.ts", + "web/app/src/workers/storage.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [], + "positive": [ + "validated NanoVDB bundle manifest", + "content-addressed OPFS commit", + "main/offscreen production viewport volume" + ], + "negative": [ + "manifest/chunk hash mismatch", + "stale source binding", + "WebGPU/resource availability block" + ], + "recovery": [ + "OPFS Worker restart", + "paged feedback resume", + "quota/device loss cleanup", + "deterministic volume save/reopen" + ], + "commands": [ + "npm --prefix web run test:vdb-availability", + "npm --prefix web run test:vdb-native", + "npm --prefix web run test:nanovdb-page-feedback", + "npm --prefix web run test:nanovdb-opfs-restart", + "npm --prefix web run test:nanovdb-volume-roundtrip", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1121-000", + "phase": "1121", + "title": "verify_paint_stroke_module", + "kind": "module", + "owner": "SCULPT", + "dependsOn": [ + "WBV2-P1120-000" + ], + "parityId": "PAINT_STROKE", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-paint_stroke", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1121-000.md", + "behavior": "Verify paint pointer sessions, depth visibility and PBVH capability gates through the production Worker.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive paint Main transaction is proven", + "negative and recovery cases are proven", + "Chromium pointer/GPU receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "PAINT_STROKE", + "sourceBacked": true, + "capabilities": [ + "CAP-PAINT-POINTER-SESSION", + "CAP-PAINT-DEPTH-VISIBILITY", + "CAP-PAINT-PBVH-GATE" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/web-engine.ts", + "web/protocol/sculpt.ts", + "web/protocol/paint.ts", + "web/protocol/paint-stroke-session.ts", + "web/protocol/paint-depth-visibility.ts", + "web/protocol/paint-pbvh-capability.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/three-adapter/paint-depth-visibility.ts", + "web/app/src/three-adapter/viewport.ts", + "web/app/src/three-adapter/offscreen-viewport.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [], + "positive": [ + "ordered paint pointer chunks", + "main/offscreen depth visibility", + "PBVH inventory capability query" + ], + "negative": [ + "stale/discontinuous pointer chunks", + "forged or over-budget depth samples", + "missing PBVH WASM entrypoint" + ], + "recovery": [ + "pointer cancel without Main mutation", + "undo step after paint commit", + "worker restart", + "deterministic capability replay" + ], + "commands": [ + "npm --prefix web run test:paint-stroke-session", + "npm --prefix web run test:paint-depth-visibility", + "npm --prefix web run test:paint-pbvh-capability", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1122-000", + "phase": "1122", + "title": "verify_engine_runtime_module", + "kind": "module", + "owner": "RUNTIME", + "dependsOn": [ + "WBV2-P1121-000" + ], + "parityId": "ENGINE_RUNTIME", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-engine_runtime", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1122-000.md", + "behavior": "Verify WebEngine variant manifest/selection, compiled WASM Main ABI and Worker crash recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive compiled WASM Main lifecycle is proven", + "negative variant/hash cases are proven", + "Chromium Worker restart receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "ENGINE_RUNTIME", + "sourceBacked": true, + "capabilities": [ + "CAP-ENGINE-VARIANT-MANIFEST", + "CAP-ENGINE-WASM-MAIN-ABI", + "CAP-WORKER-CRASH-RECOVERY" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_api.h", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/CMakeLists.txt", + "web/protocol/engine-variant.ts", + "web/protocol/worker-fault.ts", + "web/protocol/save-transaction.ts", + "web/app/src/engine-client/engine-variant-bootstrap.ts", + "web/app/src/engine-client/browser-engine-variant-session.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/workers/storage.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [], + "positive": [ + "single/pthread manifest binding", + "compiled WASM Main open/save lifecycle", + "engine and storage Worker recovery" + ], + "negative": [ + "malformed variant/resource declaration", + "mixed-version/hash mismatch", + "pthread unavailable fallback" + ], + "recovery": [ + "single-thread fallback", + "Worker crash restart", + "operation-log restore", + "deterministic repeated startup" + ], + "commands": [ + "npm --prefix web run test:engine-manifest-v2", + "npm --prefix web run test:engine-variant-selection", + "npm --prefix web run test:engine-variant-fallback", + "npm --prefix web run test:engine-variant-install", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-native-engine-production.spec.ts tests/e2e/worker-crash-recovery.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1123-000", + "phase": "1123", + "title": "repair_glb_roundtrip_dependency_module", + "kind": "module", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P1122-000" + ], + "parityId": "GLB_ROUNDTRIP_REPAIR", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-glb_roundtrip_repair", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1123-000.md", + "behavior": "Repair the standalone GLB checker dependency chain and verify mesh/non-mesh Blender roundtrip plus Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive GLB and non-mesh roundtrip are proven", + "negative and recovery cases are proven", + "Chromium save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "GLB_ROUNDTRIP_REPAIR", + "sourceBacked": true, + "capabilities": [ + "CAP-GLB-MESH-ROUNDTRIP", + "CAP-GLB-NONMESH-ROUNDTRIP", + "CAP-GLB-CHROMIUM-RECOVERY" + ], + "sourcePaths": [ + "tools/web/check-glb-blender-roundtrip.mjs", + "tools/web/check-nonmesh-glb-blender-roundtrip.mjs", + "tools/web/blender-check-glb-roundtrip.py", + "web/protocol/glb-export.ts", + "web/protocol/glb-import.ts", + "web/protocol/nonmesh-export.ts", + "web/protocol/nonmesh-binary.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx" + ], + "reuseReceipts": [], + "positive": [ + "mesh/material/skin/animation GLB roundtrip", + "Curve/Surface/Font/Metaball non-mesh mapping", + "desktop GLB Main persistence in Chromium" + ], + "negative": [ + "sparse or oversized GLB", + "external URI/extension rejection", + "non-mesh export loss gate" + ], + "recovery": [ + "cancel without publishing output", + "Worker restart", + "OPFS quota retains old asset", + "deterministic Blender roundtrip" + ], + "commands": [ + "npm --prefix web run test:glb-blender-roundtrip", + "npm --prefix web run test:nonmesh-glb-blender-roundtrip", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/glb-negative-cases.spec.ts tests/e2e/glb-recovery.spec.ts tests/e2e/glb-main-persistence.spec.ts", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1124-000", + "phase": "1124", + "title": "record_historical_hash_drift_module", + "kind": "module", + "owner": "PROVENANCE", + "dependsOn": [ + "WBV2-P1123-000" + ], + "parityId": "HISTORICAL_HASH_DRIFT", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-historical_hash_drift", + "gate": "EVIDENCE", + "card": "docs/tasks/WBV2-P1124-000.md", + "behavior": "Record legacy M12 artifact hash drift without re-signing historical manifests or changing the immutable inventory.", + "outputs": [ + "drift report", + "module receipt", + "manifest", + "status" + ], + "acceptance": [ + "original and observed hashes are recorded", + "provenance remains BLOCKED_SOURCE_LOST where bytes cannot be restored", + "historical manifests and inventory remain unchanged", + "deterministic drift evidence is reproducible", + "no full-family parity claim" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "HISTORICAL_HASH_DRIFT", + "sourceBacked": true, + "capabilities": [ + "CAP-HISTORICAL-HASH-AUDIT", + "CAP-PROVENANCE-SOURCE-LOST-GATE" + ], + "sourcePaths": [ + "tools/web/check-m12-manifest-drift.mjs", + "tests/golden/corrective/rehydration/M12-manifest-sha-drift.json", + "tests/golden/WBV2-P0-002/parity-map.json" + ], + "reuseReceipts": [], + "positive": [ + "84 drift entries captured", + "43 affected artifact paths indexed", + "immutable inventory binding preserved" + ], + "negative": [ + "missing original bytes", + "attempted historical re-signing", + "inventory mutation" + ], + "recovery": [ + "deterministic report rerun", + "source cache can restore original bytes later", + "new capability manifests reference drift evidence only" + ], + "commands": [ + "node tools/web/check-m12-manifest-drift.mjs --write", + "node tools/web/check-m12-manifest-drift.mjs", + "node tools/web/check-wbv2-module-execution.mjs" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1125-000", + "phase": "1125", + "title": "repair_geometry_nodes_allowlist_module", + "kind": "module", + "owner": "NODES", + "dependsOn": [ + "WBV2-P1124-000" + ], + "parityId": "GEOMETRY_NODES_ALLOWLIST_REPAIR", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-geometry_nodes_allowlist_repair", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1125-000.md", + "behavior": "Persist Geometry Nodes graph overrides in Web-safe Main storage and align allowlist assertions with real materialization behavior.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "supported graph Main materialization is proven", + "unsupported graph remains rejected without mutation", + "save/reopen graph retention is exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "GEOMETRY_NODES_ALLOWLIST_REPAIR", + "sourceBacked": true, + "capabilities": [ + "CAP-GEOMETRY-NODES-MAIN-PERSISTENCE", + "CAP-GEOMETRY-NODES-ALLOWLIST-CONSISTENCY", + "CAP-GEOMETRY-NODES-SAVE-REOPEN" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/geometry-nodes.ts", + "web/protocol/geometry-node-commands.ts", + "web/protocol/web-engine.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/geometry-node-allowlist.spec.ts", + "web/tests/e2e/wbv2-geometry-nodes-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [], + "positive": [ + "allowlisted graph materializes into Main", + "Scene IDProperty graph override persists", + "save/reopen retains graph identity/hash" + ], + "negative": [ + "unsupported simulation node", + "invalid graph schema", + "missing node/link endpoint" + ], + "recovery": [ + "rejected graph leaves baseline unchanged", + "undo/redo graph override", + "save/reopen", + "deterministic second run" + ], + "commands": [ + "cmake --build build_web_blender6 --target web_engine -- -j8", + "npm --prefix web run test:geometry-node-allowlist", + "npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-geometry-nodes-production.spec.ts", + "npm --prefix web run test:geometry-node-field-budget", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1126-000", + "phase": "1126", + "title": "verify_grease_pencil_viewport_module", + "kind": "module", + "owner": "DRAWING", + "dependsOn": [ + "WBV2-P1125-000" + ], + "parityId": "GREASE_PENCIL_VIEWPORT", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-grease_pencil_viewport", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1126-000.md", + "behavior": "Verify Grease Pencil 2D/3D selection and marquee integration on both viewport backends using an isolated Chromium port.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "2D and 3D selection revisions converge", + "main-thread and Offscreen marquee are exact", + "stale/foreign selection cases remain fail-closed", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "GREASE_PENCIL_VIEWPORT", + "sourceBacked": true, + "capabilities": [ + "CAP-GREASE-PENCIL-SELECTION-REVISION", + "CAP-GREASE-PENCIL-MARQUEE-MAIN", + "CAP-GREASE-PENCIL-MARQUEE-OFFSCREEN" + ], + "sourcePaths": [ + "web/protocol/grease-pencil-selection.ts", + "web/protocol/grease-pencil-marquee.ts", + "web/app/src/app/App.tsx", + "web/app/src/three-adapter/grease-pencil.ts", + "web/app/src/three-adapter/viewport.ts", + "web/app/src/three-adapter/offscreen-viewport.ts", + "web/app/src/workers/viewport-render.worker.ts" + ], + "reuseReceipts": [], + "positive": [ + "2D canvas selection revision", + "main-thread 3D marquee selection", + "OffscreenCanvas 3D marquee selection" + ], + "negative": [ + "stale selection revision", + "foreign drawing identity", + "duplicate or forged point candidate" + ], + "recovery": [ + "selection convergence across backends", + "worker viewport restart", + "deterministic repeated marquee", + "preserve Main revision" + ], + "commands": [ + "WEB_TEST_PORT=5331 npm --prefix web run test:e2e -- --workers=1 tests/e2e/grease-pencil-selection.spec.ts tests/e2e/grease-pencil-marquee.spec.ts", + "node --test web/tests/unit/grease-pencil-selection.test.mjs web/tests/unit/grease-pencil-marquee.test.mjs", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1127-000", + "phase": "1127", + "title": "verify_tracking_mask_module", + "kind": "module", + "owner": "TRACKING", + "dependsOn": [ + "WBV2-P1126-000" + ], + "parityId": "TRACKING_MASK", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-tracking_mask", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1127-000.md", + "behavior": "Verify Mask reader, editable point raycast/marquee and tracking capability gates through Chromium.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Mask reader and interaction evidence is proven", + "negative solve/resource cases are proven", + "Chromium stable IDs and recovery receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "TRACKING_MASK", + "sourceBacked": true, + "capabilities": [ + "CAP-MASK-MAIN-READER", + "CAP-MASK-POINT-RAYCAST", + "CAP-TRACKING-SOLVE-GATE" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/tracking-mask.ts", + "web/protocol/scene-ir.ts", + "web/app/src/tracking/MaskSelection.ts", + "web/app/src/app/App.tsx", + "web/app/src/three-adapter/viewport.ts", + "web/app/src/three-adapter/offscreen-viewport.ts", + "web/tests/e2e/smoke.spec.ts" + ], + "reuseReceipts": [], + "positive": [ + "Mask layers and splines reader", + "editable Mask point raycast", + "N-022 tracking marker/mask gate" + ], + "negative": [ + "foreign mask point identity", + "missing resource binding", + "camera solve unavailable" + ], + "recovery": [ + "main/offscreen marquee parity", + "worker restart", + "deterministic stable IDs", + "preserve source Main on blocked solve" + ], + "commands": [ + "npm --prefix web run test:mask-main-reader", + "WEB_TEST_PORT=5340 npm --prefix web run test:e2e -- --workers=1 tests/e2e/smoke.spec.ts -g \"N-022 tracking|real Blender 5.2 Mask\"", + "npm --prefix web run typecheck" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1128-000", + "phase": "1128", + "title": "verify_ffmpeg_movie_codec_module", + "kind": "module", + "owner": "MEDIA", + "dependsOn": [ + "WBV2-P1127-000" + ], + "parityId": "SEQUENCER_MOVIE_CODEC", + "implementationClass": "LOCAL_BOUNDED", + "parallelGroup": "module-sequencer_movie_codec", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1128-000.md", + "behavior": "Use a local ffmpeg.wasm Worker fallback for movie probing and proxy-frame extraction when Chromium HTML media decoding is unavailable.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and core-resource hashes are bound", + "positive MP4 probe and RGBA frame are proven", + "corrupt and source-identity cases are rejected", + "AbortSignal cancellation leaves no live Worker", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SEQUENCER_MOVIE_CODEC", + "sourceBacked": true, + "capabilities": [ + "CAP-FFMPEG-WASM-MOVIE-PROBE", + "CAP-FFMPEG-WASM-PROXY-FRAME", + "CAP-MOVIE-CODEC-RECOVERY" + ], + "sourcePaths": [ + "web/package.json", + "web/package-lock.json", + "web/protocol/sequencer.ts", + "web/app/src/sequencer/SequencerCodecProbe.ts", + "web/app/src/sequencer/FFmpegMovieProbe.ts", + "web/app/src/sequencer/ffmpeg-movie-probe.worker.ts", + "web/app/src/sequencer/SequencerMediaProxyCache.ts", + "web/app/src/vendor/ffmpeg/ffmpeg-core.js", + "web/app/src/vendor/ffmpeg/ffmpeg-core.wasm", + "web/app/public/vendor/ffmpeg/ffmpeg-core.js", + "web/app/public/vendor/ffmpeg/ffmpeg-core.wasm", + "third_party/ffmpeg.wasm/package.json", + "third_party/ffmpeg.wasm/README.md", + "web/tests/e2e/ffmpeg-movie-probe-production.spec.ts" + ], + "reuseReceipts": [], + "positive": [ + "browser decode fallback to ffmpeg.wasm", + "16x16 MP4 metadata probe", + "8x8 RGBA proxy frame extraction" + ], + "negative": [ + "corrupt movie payload", + "source SHA mismatch", + "ffmpeg runtime unavailable" + ], + "recovery": [ + "AbortSignal cancellation", + "Worker termination after response", + "cache manifest identity binding", + "deterministic repeated probe" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5342 npm --prefix web run test:e2e -- --workers=1 tests/e2e/ffmpeg-movie-probe-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1129-000", + "phase": "1129", + "title": "authorize_scene_settings_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1128-000" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1129", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1129-000.md", + "behavior": "Authorize one source-backed Core Scene Graph settings module after the terminal P1128 module epoch.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1128 evidence remains hash-bound", + "existing receipts are reused", + "inventory remains immutable", + "one source-backed module is active" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ] + }, + { + "id": "WBV2-P1129-001", + "phase": "1129", + "title": "verify_scene_settings_module", + "kind": "module", + "owner": "CORE_SCENE", + "dependsOn": [ + "WBV2-P1129-000" + ], + "parityId": "CORE_SCENE_GRAPH_SETTINGS", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-core_scene_graph_settings", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1129-001.md", + "behavior": "Verify the existing Blender Main scene compositor, performance and sampling setting transactions as one aggregate module.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutations are proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen receipts are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "CORE_SCENE_GRAPH_SETTINGS", + "sourceBacked": true, + "capabilities": [ + "CAP-SCENE-COMPOSITOR-SETTINGS", + "CAP-SCENE-PERFORMANCE-SETTINGS", + "CAP-SCENE-SAMPLING-SETTINGS" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/wbv2-scene-settings-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P65-002/manifest.json", + "report": "tests/golden/WBV2-P65-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P66-002/manifest.json", + "report": "tests/golden/WBV2-P66-002/implementation-report.json" + }, + { + "manifest": "tests/golden/WBV2-P67-002/manifest.json", + "report": "tests/golden/WBV2-P67-002/implementation-report.json" + } + ], + "positive": [ + "compositor device/precision mutation", + "performance thread/persistence mutation", + "sampling filter/dither mutation" + ], + "negative": [ + "invalid sampling range", + "unknown scene target", + "malformed property set" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic scene settings snapshot" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5344 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-scene-settings-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1130-000", + "phase": "1130", + "title": "authorize_editor_view2d_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1129-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1130", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1130-000.md", + "behavior": "Authorize one source-backed UI editor View2D reader/protocol module after the P1129 scene settings module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1129 evidence remains hash-bound", + "P1102 editor workflow source remains unchanged", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1130-001", + "phase": "1130", + "title": "verify_editor_view2d_module", + "kind": "module", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1130-000" + ], + "parityId": "UI_EDITOR_VIEW2D_STATE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-ui_editor_view2d_state", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1130-001.md", + "behavior": "Preserve Blender Graph/Dope Sheet View2D cur and mask state through the Web editor protocol without changing the existing editor workflow parser.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive reader state is proven", + "negative no-publish and recovery are proven", + "Chromium and save/reopen compatibility are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "UI_EDITOR_VIEW2D_STATE", + "sourceBacked": true, + "capabilities": [ + "CAP-EDITOR-VIEW2D-CUR", + "CAP-EDITOR-VIEW2D-MASK", + "CAP-EDITOR-VIEW2D-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/editor-view2d.ts", + "web/app/src/workers/editor-view2d-test.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/ui-editor-view2d-production.spec.ts" + ], + "reuseReceipts": [], + "positive": [ + "Graph main-region View2D cur retention", + "Graph main-region pixel mask retention", + "reader/protocol exact state" + ], + "negative": [ + "inverted View2D bounds", + "malformed mask range", + "missing View2D payload" + ], + "recovery": [ + "immutable base editor workflow", + "worker termination", + "deterministic repeated parse", + "save/reopen reader compatibility" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5346 npm --prefix web run test:e2e -- --workers=1 tests/e2e/ui-editor-view2d-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1131-000", + "phase": "1131", + "title": "authorize_curve_topology_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1130-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1131", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1131-000.md", + "behavior": "Authorize one source-backed Curve topology editor module after the P1130 View2D module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1130 evidence remains hash-bound", + "Curve topology source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1131-001", + "phase": "1131", + "title": "verify_curve_topology_module", + "kind": "module", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1131-000" + ], + "parityId": "CURVE_TOPOLOGY_EDITOR", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-curve_topology_editor", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1131-001.md", + "behavior": "Verify the Blender Curve TOGGLE_CYCLIC topology transaction through the existing Main, protocol, Worker and frontend path.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "CURVE_TOPOLOGY_EDITOR", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-TOPOLOGY-TOGGLE-CYCLIC", + "CAP-CURVE-TOPOLOGY-GATE", + "CAP-CURVE-TOPOLOGY-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/editors/curve/curve_ops.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/curve-topology-editor.ts", + "web/app/src/workers/curve-topology-contract-test.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/curve-topology-contract.spec.ts", + "web/tests/e2e/curve-topology-operator.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "TOGGLE_CYCLIC Main mutation", + "operator gate exposes only verified capability", + "save/reopen preserves cyclic spline state" + ], + "negative": [ + "unknown curve operator", + "stale revision claim", + "selection and payload budget overflow" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker termination and deterministic contract parse" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5347 npm --prefix web run test:e2e -- --workers=1 tests/e2e/curve-topology-contract.spec.ts tests/e2e/curve-topology-operator.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1132-000", + "phase": "1132", + "title": "authorize_curve_handle_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1131-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1132", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1132-000.md", + "behavior": "Authorize one source-backed Curve handle gizmo module after the P1131 topology module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1131 evidence remains hash-bound", + "Curve handle source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1132-001", + "phase": "1132", + "title": "verify_curve_handle_module", + "kind": "module", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1132-000" + ], + "parityId": "CURVE_HANDLE_GIZMO", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-curve_handle_gizmo", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1132-001.md", + "behavior": "Verify Curve handle position edits through Blender Main, protocol, Worker, renderer preview and frontend gizmo.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "CURVE_HANDLE_GIZMO", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-HANDLE-MAIN", + "CAP-CURVE-HANDLE-GIZMO-PREVIEW", + "CAP-CURVE-HANDLE-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/nonmesh-interaction.ts", + "web/app/src/workers/nonmesh-interaction-test.worker.ts", + "web/app/src/app/App.tsx", + "web/app/src/three-adapter/nonmesh.ts", + "web/app/src/three-adapter/viewport.ts", + "web/app/src/three-adapter/offscreen-viewport.ts", + "web/tests/e2e/wbv2-curve-handle-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "Curve handle position Main mutation", + "local handle gizmo preview", + "save/reopen preserves handle state" + ], + "negative": [ + "invalid handle identity", + "stale base revision", + "malformed handle position" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "Worker termination and deterministic preview" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5348 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-curve-handle-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1133-000", + "phase": "1133", + "title": "authorize_curve_splines_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1132-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1133", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1133-000.md", + "behavior": "Authorize one source-backed Curve spline transaction module after the P1132 handle module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1132 evidence remains hash-bound", + "Curve spline source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1133-001", + "phase": "1133", + "title": "verify_curve_splines_module", + "kind": "module", + "owner": "EDITOR", + "dependsOn": [ + "WBV2-P1133-000" + ], + "parityId": "CURVE_SPLINES_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-curve_splines_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1133-001.md", + "behavior": "Verify complete Curve spline replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "CURVE_SPLINES_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-CURVE-SPLINES-MAIN", + "CAP-CURVE-SPLINES-RECOVERY", + "CAP-CURVE-SPLINES-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/tests/e2e/wbv2-curve-splines-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "complete Curve spline Main transaction", + "POLY/BEZIER descriptor retention", + "save/reopen preserves spline state" + ], + "negative": [ + "invalid spline offsets", + "stale base revision", + "mismatched handle payload" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic binary-geometry transaction" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5349 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-curve-splines-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1134-000", + "phase": "1134", + "title": "authorize_surface_topology_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1133-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1134", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1134-000.md", + "behavior": "Authorize one source-backed Surface topology transaction module after the P1133 Curve spline module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1133 evidence remains hash-bound", + "Surface topology source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1134-001", + "phase": "1134", + "title": "verify_surface_topology_module", + "kind": "module", + "owner": "GEOMETRY", + "dependsOn": [ + "WBV2-P1134-000" + ], + "parityId": "SURFACE_TOPOLOGY_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-surface_topology_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1134-001.md", + "behavior": "Verify Surface NURBS topology replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "SURFACE_TOPOLOGY_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-SURFACE-TOPOLOGY-MAIN", + "CAP-SURFACE-NURBS-BOUNDS", + "CAP-SURFACE-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/tests/e2e/wbv2-surface-topology-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "Surface topology Main transaction", + "NURBS dimensions and weights retention", + "save/reopen preserves surface state" + ], + "negative": [ + "invalid surface dimensions", + "stale base revision", + "control grid budget mismatch" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "deterministic surface transaction" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5350 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-surface-topology-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1135-000", + "phase": "1135", + "title": "authorize_font_body_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1134-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1135", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1135-000.md", + "behavior": "Authorize one source-backed Font body transaction module after the P1134 Surface topology module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1134 evidence remains hash-bound", + "Font body source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1135-001", + "phase": "1135", + "title": "verify_font_body_module", + "kind": "module", + "owner": "GEOMETRY", + "dependsOn": [ + "WBV2-P1135-000" + ], + "parityId": "FONT_BODY_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-font_body_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1135-001.md", + "behavior": "Verify Font body replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "FONT_BODY_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-FONT-BODY-MAIN", + "CAP-FONT-BODY-RECOVERY", + "CAP-FONT-BODY-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/wbv2-font-body-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "Font body Main mutation", + "UTF-8 text retention", + "save/reopen preserves text" + ], + "negative": [ + "unknown Font data ID", + "body byte budget overflow", + "malformed body payload" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "Worker termination and deterministic text state" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5351 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-font-body-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1136-000", + "phase": "1136", + "title": "authorize_font_properties_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1135-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1136", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1136-000.md", + "behavior": "Authorize one source-backed Font properties transaction module after the P1135 Font body module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1135 evidence remains hash-bound", + "Font property source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1136-001", + "phase": "1136", + "title": "verify_font_properties_module", + "kind": "module", + "owner": "GEOMETRY", + "dependsOn": [ + "WBV2-P1136-000" + ], + "parityId": "FONT_PROPERTIES_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-font_properties_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1136-001.md", + "behavior": "Verify Font property replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "FONT_PROPERTIES_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-FONT-PROPERTIES-MAIN", + "CAP-FONT-PROPERTIES-RECOVERY", + "CAP-FONT-PROPERTIES-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/wbv2-font-properties-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "Font property Main mutation", + "bounded alignment/extrude fields", + "save/reopen preserves properties" + ], + "negative": [ + "unknown Font data ID", + "invalid alignment enum", + "out-of-range numeric property" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "Worker termination and deterministic property state" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5352 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-font-properties-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1137-000", + "phase": "1137", + "title": "authorize_metaball_elements_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1136-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1137", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1137-000.md", + "behavior": "Authorize one source-backed Metaball element transaction module after the P1136 Font properties module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1136 evidence remains hash-bound", + "Metaball element source and protocol are present", + "inventory remains immutable", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1137-001", + "phase": "1137", + "title": "verify_metaball_elements_module", + "kind": "module", + "owner": "GEOMETRY", + "dependsOn": [ + "WBV2-P1137-000" + ], + "parityId": "METABALL_ELEMENTS_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-metaball_elements_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1137-001.md", + "behavior": "Verify Metaball element replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "METABALL_ELEMENTS_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-METABALL-ELEMENTS-MAIN", + "CAP-METABALL-ELEMENTS-RECOVERY", + "CAP-METABALL-ELEMENTS-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/wbv2-metaball-elements-production.spec.ts" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1101-000/manifest.json", + "report": "tests/golden/WBV2-P1101-000/module-receipt.json" + } + ], + "positive": [ + "Metaball element Main mutation", + "bounded position/radius/scale retention", + "save/reopen preserves elements" + ], + "negative": [ + "unknown Metaball data ID", + "invalid radius", + "element count topology mismatch" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "Worker termination and deterministic element state" + ], + "commands": [ + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5353 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-metaball-elements-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1138-000", + "phase": "1138", + "title": "authorize_text_source_module", + "kind": "enabling", + "owner": "SCRIPTING", + "dependsOn": [ + "WBV2-P1137-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1138", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1138-000.md", + "behavior": "Authorize a source-backed Text datablock mutation after the P1137 Metaball module.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1137 evidence remains hash-bound", + "ID_TXT is registered for WITH_WEB", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1138-001", + "phase": "1138", + "title": "verify_text_source_module", + "kind": "module", + "owner": "SCRIPTING", + "dependsOn": [ + "WBV2-P1138-000" + ], + "parityId": "TEXT_SOURCE_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-text_source_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1138-001.md", + "behavior": "Verify Text source replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "TEXT_SOURCE_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-TEXT-SOURCE-MAIN", + "CAP-TEXT-SOURCE-RECOVERY", + "CAP-TEXT-SOURCE-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/blenkernel/intern/idtype.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/wbv2-text-source-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1137-001/manifest.json", + "report": "tests/golden/WBV2-P1137-001/module-receipt.json" + } + ], + "positive": [ + "Text source Main mutation", + "ID_TXT registration in WITH_WEB", + "save/reopen preserves source" + ], + "negative": [ + "unknown Text data ID", + "source over 1 MiB", + "linked/read-only Text" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "Worker termination and deterministic source state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5353 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-text-source-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1139-000", + "phase": "1139", + "title": "authorize_texture_properties_module", + "kind": "enabling", + "owner": "TEXTURE", + "dependsOn": [ + "WBV2-P1138-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1139", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1139-000.md", + "behavior": "Authorize a source-backed Texture property mutation module after P1138 Text.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1138 evidence remains hash-bound", + "ID_TE is registered for WITH_WEB", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1139-001", + "phase": "1139", + "title": "verify_texture_properties_module", + "kind": "module", + "owner": "TEXTURE", + "dependsOn": [ + "WBV2-P1139-000" + ], + "parityId": "TEXTURE_PROPERTIES_TRANSACTION", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-texture_properties_transaction", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1139-001.md", + "behavior": "Verify Texture property replacement through Blender Main, protocol, Worker and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main mutation is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "TEXTURE_PROPERTIES_TRANSACTION", + "sourceBacked": true, + "capabilities": [ + "CAP-TEXTURE-PROPERTIES-MAIN", + "CAP-TEXTURE-PROPERTIES-RECOVERY", + "CAP-TEXTURE-PROPERTIES-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/blenkernel/intern/idtype.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", + "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", + "web/protocol/web-engine.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/app/App.tsx", + "web/tests/e2e/wbv2-texture-properties-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1138-001/manifest.json", + "report": "tests/golden/WBV2-P1138-001/module-receipt.json" + } + ], + "positive": [ + "Texture property Main mutation", + "ID_TE registration in WITH_WEB", + "save/reopen preserves properties" + ], + "negative": [ + "unknown Texture data ID", + "noise depth outside Blender bounds", + "non-finite numeric property" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "Worker termination and deterministic property state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5353 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-texture-properties-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1140-000", + "phase": "1140", + "title": "authorize_action_group_reader_module", + "kind": "enabling", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1139-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1140", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1140-000.md", + "behavior": "Authorize a source-backed ActionGroup reader and recovery module after P1139 Texture.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1139 evidence remains hash-bound", + "ActionGroup has explicit Blender source mapping", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1140-001", + "phase": "1140", + "title": "verify_action_group_reader_module", + "kind": "module", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1140-000" + ], + "parityId": "ACTION_GROUP_READER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-action_group_reader", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1140-001.md", + "behavior": "Verify ActionGroup metadata through Blender Main reader, protocol and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main reader is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "ACTION_GROUP_READER", + "sourceBacked": true, + "capabilities": [ + "CAP-ACTION-GROUP-READER", + "CAP-ACTION-GROUP-RECOVERY", + "CAP-ACTION-GROUP-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/tests/e2e/wbv2-action-group-reader-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1112-000/manifest.json", + "report": "tests/golden/WBV2-P1112-000/module-receipt.json" + } + ], + "positive": [ + "ActionGroup Main reader exposes group and expanded metadata", + "three grouped location F-Curves remain grouped", + "save/reopen preserves group metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "missing animation target is fail-closed", + "unsupported group payload is not synthesized" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker termination and deterministic group state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5356 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-action-group-reader-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1141-000", + "phase": "1141", + "title": "authorize_action_pose_markers_module", + "kind": "enabling", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1140-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1141", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1141-000.md", + "behavior": "Authorize a source-backed ActionPoseMarkers reader and recovery module after P1140.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1140 evidence remains hash-bound", + "ActionPoseMarkers has explicit Blender source mapping", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1141-001", + "phase": "1141", + "title": "verify_action_pose_markers_reader_module", + "kind": "module", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1141-000" + ], + "parityId": "ACTION_POSE_MARKERS_READER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-action_pose_markers_reader", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1141-001.md", + "behavior": "Verify ActionPoseMarkers metadata through Blender Main reader, protocol and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main reader is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "ACTION_POSE_MARKERS_READER", + "sourceBacked": true, + "capabilities": [ + "CAP-ACTION-POSE-MARKERS-READER", + "CAP-ACTION-POSE-MARKERS-RECOVERY", + "CAP-ACTION-POSE-MARKERS-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/tests/e2e/wbv2-action-pose-markers-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1140-001/manifest.json", + "report": "tests/golden/WBV2-P1140-001/module-receipt.json" + } + ], + "positive": [ + "ActionPoseMarkers Main reader exposes marker names and frames", + "three Blender pose markers remain ordered", + "save/reopen preserves marker metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "missing animation target is fail-closed", + "non-finite marker frame is not synthesized" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker termination and deterministic marker state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5359 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-action-pose-markers-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1142-000", + "phase": "1142", + "title": "authorize_fcurve_sample_reader_module", + "kind": "enabling", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1141-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1142", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1142-000.md", + "behavior": "Authorize a source-backed FCurveSample reader and recovery module after P1141.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1141 evidence remains hash-bound", + "FCurveSample has explicit Blender source mapping", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1142-001", + "phase": "1142", + "title": "verify_fcurve_sample_reader_module", + "kind": "module", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1142-000" + ], + "parityId": "FCURVE_SAMPLE_READER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-fcurve_sample_reader", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1142-001.md", + "behavior": "Verify FCurveSample data through Blender Main reader, protocol and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main reader is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "FCURVE_SAMPLE_READER", + "sourceBacked": true, + "capabilities": [ + "CAP-FCURVE-SAMPLE-READER", + "CAP-FCURVE-SAMPLE-RECOVERY", + "CAP-FCURVE-SAMPLE-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/tests/e2e/wbv2-fcurve-sample-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1141-001/manifest.json", + "report": "tests/golden/WBV2-P1141-001/module-receipt.json" + } + ], + "positive": [ + "FCurveSample Main reader exposes sampled source and values", + "four native FPoint samples remain ordered", + "save/reopen preserves sampled data" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "missing sampled payload is fail-closed", + "non-finite sampled value is not synthesized" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker termination and deterministic sampled state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5365 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-fcurve-sample-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1143-000", + "phase": "1143", + "title": "authorize_fcurve_modifier_reader_module", + "kind": "enabling", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1142-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1143", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1143-000.md", + "behavior": "Authorize a source-backed FCurve modifier reader and recovery module after P1142.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1142 evidence remains hash-bound", + "FCurveModifiers has explicit Blender source mapping", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1143-001", + "phase": "1143", + "title": "verify_fcurve_modifier_reader_module", + "kind": "module", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1143-000" + ], + "parityId": "FCURVE_MODIFIER_READER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-fcurve_modifier_reader", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1143-001.md", + "behavior": "Verify FCurve modifier metadata through Blender Main reader, protocol and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main reader is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "FCURVE_MODIFIER_READER", + "sourceBacked": true, + "capabilities": [ + "CAP-FCURVE-MODIFIER-READER", + "CAP-FCURVE-MODIFIER-RECOVERY", + "CAP-FCURVE-MODIFIER-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/tests/e2e/wbv2-fcurve-modifier-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1142-001/manifest.json", + "report": "tests/golden/WBV2-P1142-001/module-receipt.json" + } + ], + "positive": [ + "FCurveModifiers Main reader exposes native modifier stack", + "FModifierCycles preserves type/name/flags/influence", + "save/reopen preserves modifier metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "missing modifier payload is fail-closed", + "unsupported modifier type is not synthesized" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker termination and deterministic modifier state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5368 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-fcurve-modifier-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1144-000", + "phase": "1144", + "title": "authorize_driver_reader_module", + "kind": "enabling", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1143-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1144", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1144-000.md", + "behavior": "Authorize a source-backed Driver reader and recovery module after P1143.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "P1143 evidence remains hash-bound", + "Driver has explicit Blender source mapping", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1144-001", + "phase": "1144", + "title": "verify_driver_reader_module", + "kind": "module", + "owner": "ANIMATION", + "dependsOn": [ + "WBV2-P1144-000" + ], + "parityId": "DRIVER_READER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-driver_reader", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1144-001.md", + "behavior": "Verify Driver metadata through Blender Main reader, protocol and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main reader is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "DRIVER_READER", + "sourceBacked": true, + "capabilities": [ + "CAP-DRIVER-READER", + "CAP-DRIVER-RECOVERY", + "CAP-DRIVER-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/protocol/scene-ir.ts", + "web/app/src/workers/web-engine.worker.ts", + "web/app/src/engine-client/WebEngineClient.ts", + "web/tests/e2e/wbv2-driver-reader-production.spec.ts", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1143-001/manifest.json", + "report": "tests/golden/WBV2-P1143-001/module-receipt.json" + } + ], + "positive": [ + "AnimData driver list is read from Blender Main", + "Driver preserves scripted expression and variables", + "save/reopen preserves driver metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "missing driver target is fail-closed", + "non-finite driver influence is not synthesized" + ], + "recovery": [ + "undo", + "redo", + "save/reopen", + "worker termination and deterministic driver state" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-driver-reader-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1145-000", + "phase": "1145", + "title": "authorize_corrective_smooth_reader_module", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1144-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1145", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1145-000.md", + "behavior": "Authorize a source-backed Corrective Smooth reader/recovery module after the Driver reader.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "prior evidence remains hash-bound", + "Corrective Smooth has explicit Blender source mapping", + "inventory remains source-derived", + "one source-backed module is active" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1145-001", + "phase": "1145", + "title": "verify_corrective_smooth_reader_module", + "kind": "module", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P1145-000" + ], + "parityId": "CORRECTIVE_SMOOTH_READER", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-corrective_smooth_reader", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1145-001.md", + "behavior": "Verify Corrective Smooth modifier type and RNA metadata through Blender Main reader, protocol and Chromium recovery.", + "outputs": [ + "module receipt", + "negative matrix", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "positive Main reader is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact", + "full-family parity remains explicit" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "CORRECTIVE_SMOOTH_READER", + "sourceBacked": true, + "capabilities": [ + "CAP-CORRECTIVE-SMOOTH-READER", + "CAP-CORRECTIVE-SMOOTH-RECOVERY", + "CAP-CORRECTIVE-SMOOTH-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_correctivesmooth.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-corrective-smooth-reader-production.spec.ts", + "tests/files/web/modifier_corrective_smooth_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "positive": [ + "Corrective Smooth type is read from Blender Main", + "RNA metadata is preserved", + "save/reopen preserves modifier metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "unsupported modifier data fails closed", + "non-finite metadata is not synthesized" + ], + "recovery": [ + "save/reopen", + "worker termination", + "deterministic second read" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-corrective-smooth-reader-production.spec.ts" + ], + "fullFamilyParity": false + } + }, + { + "id": "WBV2-P1146-000", + "phase": "1146", + "title": "authorize_modifier_reader_batch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1145-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1146", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1146-000.md", + "behavior": "Authorize one shared source-backed modifier reader batch.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "prior evidence remains hash-bound", + "batch source mapping is explicit", + "inventory remains source-derived" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1146-001", + "phase": "1146", + "title": "verify modifier reader batch", + "kind": "module", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P1146-000" + ], + "parityId": "MODIFIER_READER_BATCH", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-modifier_reader_batch", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1146-001.md", + "behavior": "Verify the MODIFIER_READER_BATCH batch through Blender Main, WASM and Chromium recovery.", + "outputs": [ + "aggregate module receipt", + "coverage bindings", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "every selected Main reader type is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "MODIFIER_READER_BATCH", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH-READER", + "CAP-MODIFIER_READER_BATCH-RECOVERY", + "CAP-MODIFIER_READER_BATCH-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_datatransfer.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_dynamicpaint.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_explode.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_fluid.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_fluid.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-production.spec.ts", + "tests/files/web/modifier_reader_batch_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "positive": [ + "MOD_datatransfer type is read from Blender Main", + "MOD_dynamicpaint type is read from Blender Main", + "MOD_explode type is read from Blender Main", + "MOD_fluid type is read from Blender Main", + "shared RNA metadata is preserved", + "save/reopen preserves the batch metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "unsupported batch data fails closed", + "non-finite metadata is not synthesized" + ], + "recovery": [ + "save/reopen", + "worker termination", + "deterministic second read" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-reader-batch-production.spec.ts" + ], + "fullFamilyParity": false, + "evidencePaths": [ + "tests/golden/WBV2-P1146-001/modifier-reader-batch-production.json" + ], + "coverageBindings": [ + "modifier-source:MOD_datatransfer", + "modifier-source:MOD_dynamicpaint", + "modifier-source:MOD_explode", + "modifier-source:MOD_fluid", + "rna-struct:DataTransferModifier", + "rna-struct:DynamicPaintModifier", + "rna-struct:ExplodeModifier", + "rna-struct:FluidModifier", + "rna-struct:FluidDomainSettings" + ] + } + }, + { + "id": "WBV2-P1147-000", + "phase": "1147", + "title": "authorize_modifier_reader_batch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1146-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1147", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1147-000.md", + "behavior": "Authorize one shared source-backed modifier reader batch.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "prior evidence remains hash-bound", + "batch source mapping is explicit", + "inventory remains source-derived" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1147-001", + "phase": "1147", + "title": "verify modifier reader batch two", + "kind": "module", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P1147-000" + ], + "parityId": "MODIFIER_READER_BATCH_TWO", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-modifier_reader_batch_two", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1147-001.md", + "behavior": "Verify the MODIFIER_READER_BATCH_TWO batch through Blender Main, WASM and Chromium recovery.", + "outputs": [ + "aggregate module receipt", + "coverage bindings", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "every selected Main reader type is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "MODIFIER_READER_BATCH_TWO", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH_TWO-READER", + "CAP-MODIFIER_READER_BATCH_TWO-RECOVERY", + "CAP-MODIFIER_READER_BATCH_TWO-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_laplaciandeform.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_laplaciansmooth.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_mask.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_shrinkwrap.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_two_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "positive": [ + "MOD_laplaciandeform type is read from Blender Main", + "MOD_laplaciansmooth type is read from Blender Main", + "MOD_mask type is read from Blender Main", + "MOD_mesh_to_volume type is read from Blender Main", + "shared RNA metadata is preserved", + "save/reopen preserves the batch metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "unsupported batch data fails closed", + "non-finite metadata is not synthesized" + ], + "recovery": [ + "save/reopen", + "worker termination", + "deterministic second read" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts" + ], + "fullFamilyParity": false, + "evidencePaths": [ + "tests/golden/WBV2-P1147-001/modifier-reader-batch-production.json" + ], + "coverageBindings": [ + "modifier-source:MOD_laplaciandeform", + "modifier-source:MOD_laplaciansmooth", + "modifier-source:MOD_mask", + "modifier-source:MOD_shrinkwrap", + "rna-struct:LaplacianDeformModifier", + "rna-struct:LaplacianSmoothModifier", + "rna-struct:MaskModifier", + "rna-struct:ShrinkwrapModifier" + ] + } + }, + { + "id": "WBV2-P1148-000", + "phase": "1148", + "title": "authorize_modifier_reader_batch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1147-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1148", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1148-000.md", + "behavior": "Authorize one shared source-backed modifier reader batch.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "prior evidence remains hash-bound", + "batch source mapping is explicit", + "inventory remains source-derived" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1148-001", + "phase": "1148", + "title": "verify modifier reader batch three", + "kind": "module", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P1148-000" + ], + "parityId": "MODIFIER_READER_BATCH_THREE", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-modifier_reader_batch_three", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1148-001.md", + "behavior": "Verify the MODIFIER_READER_BATCH_THREE batch through Blender Main, WASM and Chromium recovery.", + "outputs": [ + "aggregate module receipt", + "coverage bindings", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "every selected Main reader type is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "MODIFIER_READER_BATCH_THREE", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH_THREE-READER", + "CAP-MODIFIER_READER_BATCH_THREE-RECOVERY", + "CAP-MODIFIER_READER_BATCH_THREE-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_remesh.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_skin.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_weighted_normal.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_warp.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_three_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "positive": [ + "MOD_remesh type is read from Blender Main", + "MOD_skin type is read from Blender Main", + "MOD_weighted_normal type is read from Blender Main", + "MOD_warp type is read from Blender Main", + "shared RNA metadata is preserved", + "save/reopen preserves the batch metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "unsupported batch data fails closed", + "non-finite metadata is not synthesized" + ], + "recovery": [ + "save/reopen", + "worker termination", + "deterministic second read" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WBV2_BATCH_TASK=WBV2-P1148-001 WBV2_BATCH_FIXTURE=tests/files/web/modifier_reader_batch_three_scene.blend WBV2_BATCH_TYPES='[\"REMESH\",\"SKIN\",\"WEIGHTED_NORMAL\",\"WARP\"]' WBV2_BATCH_UNITS='[\"modifier-source:MOD_remesh\",\"modifier-source:MOD_skin\",\"modifier-source:MOD_weighted_normal\",\"modifier-source:MOD_warp\",\"rna-struct:RemeshModifier\",\"rna-struct:SkinModifier\",\"rna-struct:WeightedNormalModifier\",\"rna-struct:WarpModifier\"]' WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts" + ], + "fullFamilyParity": false, + "evidencePaths": [ + "tests/golden/WBV2-P1148-001/modifier-reader-batch-production.json" + ], + "coverageBindings": [ + "modifier-source:MOD_remesh", + "modifier-source:MOD_skin", + "modifier-source:MOD_weighted_normal", + "modifier-source:MOD_warp", + "rna-struct:RemeshModifier", + "rna-struct:SkinModifier", + "rna-struct:WeightedNormalModifier", + "rna-struct:WarpModifier" + ] + } + }, + { + "id": "WBV2-P1149-000", + "phase": "1149", + "title": "authorize_modifier_reader_batch", + "kind": "enabling", + "owner": "PROGRAM", + "dependsOn": [ + "WBV2-P1148-001" + ], + "parityId": null, + "implementationClass": "QUEUE_ONLY", + "parallelGroup": "module-root-1149", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1149-000.md", + "behavior": "Authorize one shared source-backed modifier reader batch.", + "outputs": [ + "successor authorization", + "module plan", + "manifest", + "status" + ], + "acceptance": [ + "prior evidence remains hash-bound", + "batch source mapping is explicit", + "inventory remains source-derived" + ], + "commands": [ + "node tools/web/check-execution-control-plane.mjs" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true + }, + { + "id": "WBV2-P1149-001", + "phase": "1149", + "title": "verify modifier reader batch four", + "kind": "module", + "owner": "MODIFIER", + "dependsOn": [ + "WBV2-P1149-000" + ], + "parityId": "MODIFIER_READER_BATCH_FOUR", + "implementationClass": "LOCAL_EXACT", + "parallelGroup": "module-modifier_reader_batch_four", + "gate": "MODULE", + "card": "docs/tasks/WBV2-P1149-001.md", + "behavior": "Verify the MODIFIER_READER_BATCH_FOUR batch through Blender Main, WASM and Chromium recovery.", + "outputs": [ + "aggregate module receipt", + "coverage bindings", + "manifest", + "status" + ], + "acceptance": [ + "source and protocol hashes are bound", + "every selected Main reader type is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact" + ], + "status": "done", + "ready": false, + "queueMutationAllowed": true, + "module": { + "moduleId": "MODIFIER_READER_BATCH_FOUR", + "sourceBacked": true, + "capabilities": [ + "CAP-MODIFIER_READER_BATCH_FOUR-READER", + "CAP-MODIFIER_READER_BATCH_FOUR-RECOVERY", + "CAP-MODIFIER_READER_BATCH_FOUR-FAIL-CLOSED" + ], + "sourcePaths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvproject.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvwarp.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_normal_edit.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_volume_to_mesh.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_four_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "reuseReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json" + } + ], + "positive": [ + "MOD_uvproject type is read from Blender Main", + "MOD_uvwarp type is read from Blender Main", + "MOD_volume_displace type is read from Blender Main", + "MOD_volume_to_mesh type is read from Blender Main", + "shared RNA metadata is preserved", + "save/reopen preserves the batch metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "unsupported batch data fails closed", + "non-finite metadata is not synthesized" + ], + "recovery": [ + "save/reopen", + "worker termination", + "deterministic second read" + ], + "commands": [ + "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "npm --prefix web run typecheck", + "npm --prefix web run build", + "WBV2_BATCH_TASK=WBV2-P1149-001 WBV2_BATCH_FIXTURE=tests/files/web/modifier_reader_batch_four_scene.blend WBV2_BATCH_TYPES='[\"UV_PROJECT\",\"UV_WARP\",\"NORMAL_EDIT\",\"VOLUME_TO_MESH\"]' WBV2_BATCH_UNITS='[\"modifier-source:MOD_uvproject\",\"modifier-source:MOD_uvwarp\",\"modifier-source:MOD_normal_edit\",\"modifier-source:MOD_volume_to_mesh\",\"rna-struct:UVProjectModifier\",\"rna-struct:UVWarpModifier\",\"rna-struct:NormalEditModifier\",\"rna-struct:VolumeToMeshModifier\"]' WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts" + ], + "fullFamilyParity": false, + "evidencePaths": [ + "tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json" + ], + "coverageBindings": [ + "modifier-source:MOD_uvproject", + "modifier-source:MOD_uvwarp", + "modifier-source:MOD_normal_edit", + "modifier-source:MOD_volume_to_mesh", + "rna-struct:UVProjectModifier", + "rna-struct:UVWarpModifier", + "rna-struct:NormalEditModifier", + "rna-struct:VolumeToMeshModifier" + ] + } + } + ] +} diff --git a/tests/golden/WBV2-P1149-001/manifest.json b/tests/golden/WBV2-P1149-001/manifest.json new file mode 100644 index 000000000..a06ee8e58 --- /dev/null +++ b/tests/golden/WBV2-P1149-001/manifest.json @@ -0,0 +1,111 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P1149-001", + "parentTask": "WBV2-P1149-000", + "operation": "MODULE_FUNCTION_EXECUTION", + "taskClass": "MODULE", + "status": "done", + "enablingTask": true, + "parityStateChange": false, + "runtime": "BLENDER_WEB_FUNCTION_MODULE", + "artifacts": { + "parentManifest": { + "path": "tests/golden/WBV2-P1149-000/manifest.json", + "sha256": "ca2332b719e579803fa71005f052c3e3fd4c347108ef747b47641a2d5805c720" + }, + "source1": { + "path": "blender-5.2.0/source/blender/modifiers/intern/MOD_uvproject.cc", + "sha256": "cbb4b95a7f9fdffcf78a78ae3acfae8f02c6c75e02950e0f24280e6ce1e20fac" + }, + "source2": { + "path": "blender-5.2.0/source/blender/modifiers/intern/MOD_uvwarp.cc", + "sha256": "a496feb74d7d081647a94ce7334110801be6b7f02ba864dff740be3e16ba760a" + }, + "source3": { + "path": "blender-5.2.0/source/blender/modifiers/intern/MOD_normal_edit.cc", + "sha256": "c53e19deda11152fb2cfd5cf9e1b69f8238c65b9cb1a54c0e16fa6acc10fbdb1" + }, + "source4": { + "path": "blender-5.2.0/source/blender/modifiers/intern/MOD_volume_to_mesh.cc", + "sha256": "90310043a84ae47299e0f3e8b45fa6804398db5a594b1b7281660c3f95eb93b9" + }, + "source5": { + "path": "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "sha256": "1292112c20eaa113084a2a7093c349e7787db818950d80a6e11b75b287e4287b" + }, + "source6": { + "path": "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "sha256": "1292112c20eaa113084a2a7093c349e7787db818950d80a6e11b75b287e4287b" + }, + "source7": { + "path": "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "sha256": "1292112c20eaa113084a2a7093c349e7787db818950d80a6e11b75b287e4287b" + }, + "source8": { + "path": "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "sha256": "1292112c20eaa113084a2a7093c349e7787db818950d80a6e11b75b287e4287b" + }, + "source9": { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "sha256": "f6fbd04315c48ad4dfbf109b91e5b350550d23c227e5c11a71a58f09e923c990" + }, + "source10": { + "path": "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "sha256": "3520b2d03d803d923062c58fdd60530cc8540040bfb35a00c439cfe50167aa03" + }, + "source11": { + "path": "tests/files/web/modifier_reader_batch_four_scene.blend", + "sha256": "374454404bc762072489997b264c9ab4e556d3c3567040efb45df783bee1db96" + }, + "source12": { + "path": "web/app/src/vendor/blender/web_engine.wasm", + "sha256": "32bc36aba563fe1ed0fb5d0292ca8a3ada1eecd6d45e38d9dcde565f02a312fe" + }, + "evidence1": { + "path": "tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json", + "sha256": "0f3675f85939e421658e324c39e43954371d9d740dd3ca78e713fca38d452e4c" + }, + "moduleReceipt": { + "path": "tests/golden/WBV2-P1149-001/module-receipt.json", + "sha256": "8c0c1ac15c67dcf8896731b7b4c1ed1661b0ccb9fe6718af83c35e9cc04b8ee9" + }, + "status": { + "path": "docs/status/WBV2-P1149-001.md", + "sha256": "e112ea060c91b500fff02d6d7c35e87518e9a00c2c8ad7bc670bd1794a19a900" + }, + "log": { + "path": "tests/golden/WBV2-P1149-001/module-run.log", + "sha256": "87963cac522da0f84b806194e20cd82886b84d112f04d6959ab5ac9a83053acf" + }, + "plan": { + "path": "tests/golden/WBV2-P1149-000/module-execution-plan.json", + "sha256": "4420220b364b1b66d96a1547b8cec2e7e11df047657fbdbe0c9c59e052febd0f" + }, + "taskContext": { + "path": "tests/golden/WBV2-P1149-001/task-context.json", + "sha256": "116b358e5ece9ab420baf74d714823b38bcc0fce3f531288c1458e419bb50642" + } + }, + "assertions": { + "moduleId": "MODIFIER_READER_BATCH_FOUR", + "sourceBacked": true, + "positiveCases": 6, + "negativeCases": 3, + "recoveryCases": 3, + "commandCount": 4, + "reusedReceiptCount": 1, + "sourceUnchanged": true, + "fullFamilyParity": false, + "dynamicInventoryPath": "tests/golden/WBV2/dynamic-inventory.json", + "dynamicSourceTreeSha256": "600cb3dd441f09d9655b740735fbf8fa49ad6c14d308c68d59a29f9c338e4202", + "dynamicUnitCount": 3745, + "dynamicVerifiedUnits": 377, + "dynamicUnverifiedUnits": 3368, + "planningEstimate": 5200, + "historicalInventoryTotal": 6900, + "historicalEffectiveCompleted": 290, + "historicalEffectivePending": 6609, + "historicalReproduction": false + }, + "nextTask": null +} diff --git a/tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json b/tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json new file mode 100644 index 000000000..532cfcaef --- /dev/null +++ b/tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json @@ -0,0 +1,212 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P1149-001", + "operation": "MODIFIER_READER_BATCH_TWO_CHROMIUM_SAVE_REOPEN", + "browser": "chromium", + "queueMutation": false, + "fixture": "tests/files/web/modifier_reader_batch_four_scene.blend", + "fixtureSha256": "374454404bc762072489997b264c9ab4e556d3c3567040efb45df783bee1db96", + "expectedTypes": [ + "UV_PROJECT", + "UV_WARP", + "NORMAL_EDIT", + "VOLUME_TO_MESH" + ], + "sourceUnits": [ + "modifier-source:MOD_uvproject", + "modifier-source:MOD_uvwarp", + "modifier-source:MOD_normal_edit", + "modifier-source:MOD_volume_to_mesh", + "rna-struct:UVProjectModifier", + "rna-struct:UVWarpModifier", + "rna-struct:NormalEditModifier", + "rna-struct:VolumeToMeshModifier" + ], + "before": [ + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:986394667", + "name": "Uv Project", + "type": "UV_PROJECT", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 986394667, + "typeCode": 15 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:2036523567", + "name": "Uv Warp", + "type": "UV_WARP", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 2036523567, + "typeCode": 45 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:63296176", + "name": "Normal Edit", + "type": "NORMAL_EDIT", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 63296176, + "typeCode": 50 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:662944674", + "name": "Volume To Mesh", + "type": "VOLUME_TO_MESH", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 5, + "mode": 3, + "persistentUid": 662944674, + "typeCode": 60 + } + } + ], + "types": [ + "UV_PROJECT", + "UV_WARP", + "NORMAL_EDIT", + "VOLUME_TO_MESH" + ], + "after": [ + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:986394667", + "name": "Uv Project", + "type": "UV_PROJECT", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 986394667, + "typeCode": 15 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:2036523567", + "name": "Uv Warp", + "type": "UV_WARP", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 2036523567, + "typeCode": 45 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:63296176", + "name": "Normal Edit", + "type": "NORMAL_EDIT", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 63296176, + "typeCode": 50 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:662944674", + "name": "Volume To Mesh", + "type": "VOLUME_TO_MESH", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 5, + "mode": 3, + "persistentUid": 662944674, + "typeCode": 60 + } + } + ], + "second": [ + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:986394667", + "name": "Uv Project", + "type": "UV_PROJECT", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 986394667, + "typeCode": 15 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:2036523567", + "name": "Uv Warp", + "type": "UV_WARP", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 2036523567, + "typeCode": 45 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:63296176", + "name": "Normal Edit", + "type": "NORMAL_EDIT", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 1, + "mode": 7, + "persistentUid": 63296176, + "typeCode": 50 + } + }, + { + "meshId": "mesh:Grid", + "uuid": "modifier:object:ModifierBatchFourFixture:662944674", + "name": "Volume To Mesh", + "type": "VOLUME_TO_MESH", + "enabled": true, + "evaluationStatus": "BLOCKED", + "parameters": { + "flag": 5, + "mode": 3, + "persistentUid": 662944674, + "typeCode": 60 + } + } + ], + "saveReopenExact": true, + "deterministicExact": true, + "savedSha256": "374454404bc762072489997b264c9ab4e556d3c3567040efb45df783bee1db96", + "malformed": { + "code": "BLEND_READ_FAILED", + "message": "Input is not an uncompressed, gzip, or zstd Blender file" + } +} diff --git a/tests/golden/WBV2-P1149-001/module-receipt.json b/tests/golden/WBV2-P1149-001/module-receipt.json new file mode 100644 index 000000000..fab8470aa --- /dev/null +++ b/tests/golden/WBV2-P1149-001/module-receipt.json @@ -0,0 +1,128 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P1149-001", + "operation": "MODULE_FUNCTION_EXECUTION", + "moduleId": "MODIFIER_READER_BATCH_FOUR", + "status": "PASS", + "source": { + "paths": [ + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvproject.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvwarp.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_normal_edit.cc", + "blender-5.2.0/source/blender/modifiers/intern/MOD_volume_to_mesh.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "tests/files/web/modifier_reader_batch_four_scene.blend", + "web/app/src/vendor/blender/web_engine.wasm" + ], + "before": { + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvproject.cc": "cbb4b95a7f9fdffcf78a78ae3acfae8f02c6c75e02950e0f24280e6ce1e20fac", + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvwarp.cc": "a496feb74d7d081647a94ce7334110801be6b7f02ba864dff740be3e16ba760a", + "blender-5.2.0/source/blender/modifiers/intern/MOD_normal_edit.cc": "c53e19deda11152fb2cfd5cf9e1b69f8238c65b9cb1a54c0e16fa6acc10fbdb1", + "blender-5.2.0/source/blender/modifiers/intern/MOD_volume_to_mesh.cc": "90310043a84ae47299e0f3e8b45fa6804398db5a594b1b7281660c3f95eb93b9", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc": "1292112c20eaa113084a2a7093c349e7787db818950d80a6e11b75b287e4287b", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp": "f6fbd04315c48ad4dfbf109b91e5b350550d23c227e5c11a71a58f09e923c990", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts": "3520b2d03d803d923062c58fdd60530cc8540040bfb35a00c439cfe50167aa03", + "tests/files/web/modifier_reader_batch_four_scene.blend": "374454404bc762072489997b264c9ab4e556d3c3567040efb45df783bee1db96", + "web/app/src/vendor/blender/web_engine.wasm": "32bc36aba563fe1ed0fb5d0292ca8a3ada1eecd6d45e38d9dcde565f02a312fe" + }, + "after": { + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvproject.cc": "cbb4b95a7f9fdffcf78a78ae3acfae8f02c6c75e02950e0f24280e6ce1e20fac", + "blender-5.2.0/source/blender/modifiers/intern/MOD_uvwarp.cc": "a496feb74d7d081647a94ce7334110801be6b7f02ba864dff740be3e16ba760a", + "blender-5.2.0/source/blender/modifiers/intern/MOD_normal_edit.cc": "c53e19deda11152fb2cfd5cf9e1b69f8238c65b9cb1a54c0e16fa6acc10fbdb1", + "blender-5.2.0/source/blender/modifiers/intern/MOD_volume_to_mesh.cc": "90310043a84ae47299e0f3e8b45fa6804398db5a594b1b7281660c3f95eb93b9", + "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc": "1292112c20eaa113084a2a7093c349e7787db818950d80a6e11b75b287e4287b", + "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp": "f6fbd04315c48ad4dfbf109b91e5b350550d23c227e5c11a71a58f09e923c990", + "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts": "3520b2d03d803d923062c58fdd60530cc8540040bfb35a00c439cfe50167aa03", + "tests/files/web/modifier_reader_batch_four_scene.blend": "374454404bc762072489997b264c9ab4e556d3c3567040efb45df783bee1db96", + "web/app/src/vendor/blender/web_engine.wasm": "32bc36aba563fe1ed0fb5d0292ca8a3ada1eecd6d45e38d9dcde565f02a312fe" + }, + "unchanged": true + }, + "reusedReceipts": [ + { + "manifest": "tests/golden/WBV2-P1107-000/manifest.json", + "report": "tests/golden/WBV2-P1107-000/module-receipt.json", + "manifestSha256": "a53ebdc52db5dcf27d44e938e5551f1ee2adae8e46c3fe8661604ee6b1000f8c", + "reportSha256": "6dd419799e1a4b9251328d9496f2459d148cd89118740a06b0ee6ffb78e0b1d2" + } + ], + "cases": { + "positive": [ + "MOD_uvproject type is read from Blender Main", + "MOD_uvwarp type is read from Blender Main", + "MOD_volume_displace type is read from Blender Main", + "MOD_volume_to_mesh type is read from Blender Main", + "shared RNA metadata is preserved", + "save/reopen preserves the batch metadata" + ], + "negative": [ + "malformed blend is rejected without Main mutation", + "unsupported batch data fails closed", + "non-finite metadata is not synthesized" + ], + "recovery": [ + "save/reopen", + "worker termination", + "deterministic second read" + ] + }, + "commands": [ + { + "command": "source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm", + "exitCode": 0 + }, + { + "command": "npm --prefix web run typecheck", + "exitCode": 0 + }, + { + "command": "npm --prefix web run build", + "exitCode": 0 + }, + { + "command": "WBV2_BATCH_TASK=WBV2-P1149-001 WBV2_BATCH_FIXTURE=tests/files/web/modifier_reader_batch_four_scene.blend WBV2_BATCH_TYPES='[\"UV_PROJECT\",\"UV_WARP\",\"NORMAL_EDIT\",\"VOLUME_TO_MESH\"]' WBV2_BATCH_UNITS='[\"modifier-source:MOD_uvproject\",\"modifier-source:MOD_uvwarp\",\"modifier-source:MOD_normal_edit\",\"modifier-source:MOD_volume_to_mesh\",\"rna-struct:UVProjectModifier\",\"rna-struct:UVWarpModifier\",\"rna-struct:NormalEditModifier\",\"rna-struct:VolumeToMeshModifier\"]' WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "exitCode": 0 + } + ], + "verification": { + "required": [ + "sourceHash", + "wasmBuild", + "positiveMainMutation", + "negativeNoMutation", + "undoRedo", + "saveReopen", + "aggregateManifest" + ], + "chromiumOnly": true, + "fullFamilyParity": false + }, + "inventory": { + "historical": { + "path": "tests/golden/WBV2-P0-002/parity-map.json", + "sha256": "a60a77cae000941a953d55adbf93d8f6e275533891713d6eae993f60faed94e8", + "total": 6900, + "legacyCompleted": 281, + "legacyPending": 6618, + "effectiveCompleted": 290, + "effectivePending": 6609, + "mutation": "forbidden_by_module_execution" + }, + "dynamic": { + "path": "tests/golden/WBV2/dynamic-inventory.json", + "sha256": "6ccf20cd15cf065e6432c209afa7e32557e619837f7880f0f38a2bc01ccaa02d", + "sourceTreeSha256": "600cb3dd441f09d9655b740735fbf8fa49ad6c14d308c68d59a29f9c338e4202", + "unitCount": 3745, + "planningEstimate": 5200, + "hardTarget": false, + "verifiedUnits": 377, + "unverifiedUnits": 3368 + } + }, + "nextTask": null +} diff --git a/tests/golden/WBV2-P1149-001/module-run.log b/tests/golden/WBV2-P1149-001/module-run.log new file mode 100644 index 000000000..1afe390e1 --- /dev/null +++ b/tests/golden/WBV2-P1149-001/module-run.log @@ -0,0 +1,49 @@ +> source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine -- -j8 && cp build_web_blender6/bin/web_engine.wasm web/app/src/vendor/blender/web_engine.wasm && cp build_web_blender6/bin/web_engine.wasm web/app/public/vendor/blender/web_engine.wasm +ninja: no work to do. + +> npm --prefix web run typecheck + +> blender-web-editor@0.1.0-rc.1 typecheck +> tsc -p tsconfig.json --noEmit + + +> npm --prefix web run build + +> blender-web-editor@0.1.0-rc.1 build +> tsc -p tsconfig.json && vite build --config app/vite.config.ts + +vite v8.2.0 building client environment for production... + transforming...✓ 102 modules transformed. +rendering chunks... +computing gzip size... +dist/index.html 0.46 kB │ gzip: 0.30 kB +dist/assets/storage.worker-D9TqXsGS.js 66.59 kB +dist/assets/web-engine.worker-BfTMiTY1.js 362.11 kB +dist/assets/viewport-render.worker-BKnJyAEz.js 634.08 kB +dist/assets/web_engine-CjnzAIfx.wasm 16,238.37 kB │ gzip: 3,856.73 kB +dist/assets/index-BgTbQCE2.css 15.35 kB │ gzip: 3.91 kB +dist/assets/index-C3AJuKSc.js 1,190.30 kB │ gzip: 316.69 kB + +✓ built in 489ms +[plugin rolldown:vite-resolve] Module "module" has been externalized for browser compatibility, imported by "/home/mes123456/workinf_Blender_Wasm/web/app/src/vendor/blender/web_engine.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details. +[plugin builtin:vite-reporter] +(!) Some chunks are larger than 500 kB after minification. Consider: +- Using dynamic import() to code-split the application +- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting +- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. + +> WBV2_BATCH_TASK=WBV2-P1149-001 WBV2_BATCH_FIXTURE=tests/files/web/modifier_reader_batch_four_scene.blend WBV2_BATCH_TYPES='["UV_PROJECT","UV_WARP","NORMAL_EDIT","VOLUME_TO_MESH"]' WBV2_BATCH_UNITS='["modifier-source:MOD_uvproject","modifier-source:MOD_uvwarp","modifier-source:MOD_normal_edit","modifier-source:MOD_volume_to_mesh","rna-struct:UVProjectModifier","rna-struct:UVWarpModifier","rna-struct:NormalEditModifier","rna-struct:VolumeToMeshModifier"]' WEB_TEST_PORT=5371 npm --prefix web run test:e2e -- --workers=1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts + +> blender-web-editor@0.1.0-rc.1 test:e2e +> playwright test --config playwright.config.ts --workers=1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts + + +Running 1 test using 1 worker + + ✓ 1 tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts:15:1 › second modifier reader batch preserves concrete Blender Main metadata (2.0s) + + 1 passed (2.7s) +[WebServer] (node:138534) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +[WebServer] (Use `node --trace-warnings ...` to show where the warning was created) +(node:138588) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) diff --git a/tests/golden/WBV2-P1149-001/task-context.json b/tests/golden/WBV2-P1149-001/task-context.json new file mode 100644 index 000000000..3e33f76bd --- /dev/null +++ b/tests/golden/WBV2-P1149-001/task-context.json @@ -0,0 +1,187 @@ +{ + "schemaVersion": 1, + "task": "WBV2-P1149-001", + "parentTask": "WBV2-P1149-000", + "status": "in_progress", + "goal": "以一个共享 Blender Main reader、WASM build、Worker 路由和 Chromium receipt 批量验证 MOD_uvproject, MOD_uvwarp, MOD_volume_displace, MOD_volume_to_mesh 的真实 modifier/RNA 元数据。", + "scope": { + "gap": "capability:MODIFIER_READER_BATCH_FOUR", + "ownerFamily": "MODIFIER", + "implementationClass": "LOCAL_EXACT" + }, + "commands": [ + "node tools/web/check-task-context.mjs --task WBV2-P1149-001 --write" + ], + "inputPaths": [], + "inputSelection": { + "schemaVersion": 1, + "limits": { + "maxFiles": 12, + "evidenceBytes": 8192, + "contextRemainingBytes": 2022, + "contextRemainingTokens": 503 + }, + "source": { + "bytes": 7882, + "tokens": 1973 + }, + "selected": [], + "excluded": [ + { + "path": "blender-5.2.0/source/blender/modifiers/intern/", + "bytes": 10155, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/makesrna/intern/rna_modifier.cc", + "bytes": 521651, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", + "bytes": 313993, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "tests/files/web/modifier_reader_batch_four_scene.blend", + "bytes": 98605, + "reason": "EVIDENCE_BYTE_BUDGET" + }, + { + "path": "web/tests/e2e/wbv2-modifier-reader-batch-two-production.spec.ts", + "bytes": 4082, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "tests/golden/WBV2-P1149-001/module-receipt.json", + "bytes": 6822, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "tests/golden/WBV2-P1149-001/modifier-reader-batch-production.json", + "bytes": 5409, + "reason": "CONTEXT_REMAINING_SPACE" + }, + { + "path": "tests/golden/WBV2-P1149-001/manifest.json", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + }, + { + "path": "docs/status/WBV2-P1149-001.md", + "bytes": null, + "reason": "GENERATED_EVIDENCE_OUTPUT" + } + ], + "totals": { + "files": 0, + "bytes": 0, + "tokens": 0 + } + }, + "exitCriteria": [ + "source and protocol hashes are bound", + "every selected Main reader type is proven", + "negative no-mutation and recovery are proven", + "Chromium and save/reopen evidence are exact" + ], + "nextTask": null, + "sourceDocuments": { + "queue": "docs/EXECUTION_QUEUE.md", + "taskCard": "docs/tasks/WBV2-P1149-001.md", + "taskIndex": "tests/golden/WBV2/task-index.json", + "parentManifest": "tests/golden/WBV2-P1149-000/manifest.json", + "parentStatus": "docs/status/WBV2-P1149-000.md" + }, + "readPolicy": { + "required": [ + "docs/EXECUTION_QUEUE.md", + "docs/tasks/WBV2-P1149-001.md", + "tests/golden/WBV2-P1149-000/manifest.json", + "docs/status/WBV2-P1149-000.md" + ], + "machineOnly": [ + "tests/golden/WBV2/task-index.json", + "tests/golden/M15-03A/task-catalog.jsonl" + ], + "optionalByNeed": [ + "docs/WEB_BLENDER_MODELER_V1_SCOPE.md", + "任务卡列出的精确协议/生产路径", + "任务卡明确命名的长期计划小节" + ], + "forbiddenByDefault": [ + "完整 CURRENT_EXECUTION_PLAN.md", + "完整 PROJECT_STATUS_AND_NEXT_WORK.md", + "全部 docs/status/*.md", + "完整 parity/WBS 计划", + "README 历史和 test-results/" + ] + }, + "parent": { + "manifest": { + "schemaVersion": 1, + "task": "WBV2-P1149-000", + "parentTask": "WBV2-P1148-001", + "status": "done", + "nextTask": "WBV2-P1149-001", + "artifactCount": 4 + }, + "statusSummary": [ + "# WBV2-P1149-000 status", + "- task: `WBV2-P1149-000`; parent: `WBV2-P1148-001`; status: `done`", + "- taskClass: `QUEUE_ENABLEMENT`; no modifier-family parity completion claimed", + "- source-backed batch authorized: `MODIFIER_READER_BATCH_FOUR` (8 units)", + "- dynamic inventory: `3745` units; verified `377`; unverified `3368`; bound delta `0`", + "- nextTask: `WBV2-P1149-001`" + ] + }, + "budgets": { + "queueBytes": 4096, + "taskBytes": 2313, + "parentManifestBytes": 24576, + "parentStatusBytes": 6144, + "evidenceFiles": 12, + "evidenceBytes": 8192, + "contextTokens": 3500, + "contextEnvelopeTokens": 1024, + "taskLines": 46, + "taskTokens": 579 + }, + "size": { + "documents": [ + { + "path": "docs/EXECUTION_QUEUE.md", + "bytes": 3830, + "lines": 56, + "tokens": 958 + }, + { + "path": "docs/tasks/WBV2-P1149-001.md", + "bytes": 2313, + "lines": 46, + "tokens": 579 + }, + { + "path": "tests/golden/WBV2-P1149-000/manifest.json", + "bytes": 1381, + "lines": 43, + "tokens": 346 + }, + { + "path": "docs/status/WBV2-P1149-000.md", + "bytes": 358, + "lines": 8, + "tokens": 90 + } + ], + "sourceTokens": 1973, + "evidenceFiles": 0, + "evidenceBytes": 0, + "evidenceTokens": 0, + "totalTokens": 1973, + "reservedEnvelopeTokens": 1024, + "estimatedContextTokens": 2997, + "serializedContextTokens": 658, + "withinBudget": true + } +} diff --git a/tests/golden/WBV2/task-catalog.jsonl b/tests/golden/WBV2/task-catalog.jsonl index 69258590e..d36e925bd 100644 --- a/tests/golden/WBV2/task-catalog.jsonl +++ b/tests/golden/WBV2/task-catalog.jsonl @@ -75,3 +75,5 @@ {"id":"WBV2-P1147-001","gapId":"MODIFIER_READER_BATCH_TWO","ownerFamily":"MODIFIER","sourceTask":"1147","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["source and protocol hashes are bound","every selected Main reader type is proven","negative no-mutation and recovery are proven","Chromium and save/reopen evidence are exact"]} {"id":"WBV2-P1148-000","gapId":"workflow:authorize_modifier_reader_batch","ownerFamily":"PROGRAM","sourceTask":"1148","state":"completed","targetImplementationClass":"QUEUE_ONLY","exitCriteria":["prior evidence remains hash-bound","batch source mapping is explicit","inventory remains source-derived"]} {"id":"WBV2-P1148-001","gapId":"MODIFIER_READER_BATCH_THREE","ownerFamily":"MODIFIER","sourceTask":"1148","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["source and protocol hashes are bound","every selected Main reader type is proven","negative no-mutation and recovery are proven","Chromium and save/reopen evidence are exact"]} +{"id":"WBV2-P1149-000","gapId":"workflow:authorize_modifier_reader_batch","ownerFamily":"PROGRAM","sourceTask":"1149","state":"completed","targetImplementationClass":"QUEUE_ONLY","exitCriteria":["prior evidence remains hash-bound","batch source mapping is explicit","inventory remains source-derived"]} +{"id":"WBV2-P1149-001","gapId":"MODIFIER_READER_BATCH_FOUR","ownerFamily":"MODIFIER","sourceTask":"1149","state":"completed","targetImplementationClass":"LOCAL_EXACT","exitCriteria":["source and protocol hashes are bound","every selected Main reader type is proven","negative no-mutation and recovery are proven","Chromium and save/reopen evidence are exact"]} diff --git a/tests/golden/WBV2/task-index.json b/tests/golden/WBV2/task-index.json index 58a06636c..55216f2c9 100644 --- a/tests/golden/WBV2/task-index.json +++ b/tests/golden/WBV2/task-index.json @@ -1 +1 @@ -{"schemaVersion":1,"operation":"BLENDER_WEB_CAPABILITY_TASK_INDEX","source":{"path":"tests/golden/WBV2-P1148-000/module-execution-plan.json","sha256":"ddef158adc3211d9cf86d38c288dd9c2ce47c32abae400d2b5929838044e139f"},"catalog":{"path":"tests/golden/WBV2/task-catalog.jsonl","sha256":"347fc73617a2505e938fce540ba64cf98b250d30a9415c9fcffde7bb86bba1ea"},"taskCount":77,"activeTask":null,"entries":{"WBV2-P1096-000":{"line":0,"offset":0,"length":267,"previous":"WBV2-P1095-003","next":"WBV2-P1100-000"},"WBV2-P1100-000":{"line":1,"offset":267,"length":300,"previous":"WBV2-P1096-000","next":"WBV2-P1100-001"},"WBV2-P1100-001":{"line":2,"offset":567,"length":375,"previous":"WBV2-P1100-000","next":"WBV2-P1100-002"},"WBV2-P1100-002":{"line":3,"offset":942,"length":377,"previous":"WBV2-P1100-001","next":"WBV2-P1100-003"},"WBV2-P1100-003":{"line":4,"offset":1319,"length":386,"previous":"WBV2-P1100-002","next":"WBV2-P1101-000"},"WBV2-P1101-000":{"line":5,"offset":1705,"length":374,"previous":"WBV2-P1100-003","next":"WBV2-P1101-001"},"WBV2-P1101-001":{"line":6,"offset":2079,"length":382,"previous":"WBV2-P1101-000","next":"WBV2-P1101-002"},"WBV2-P1101-002":{"line":7,"offset":2461,"length":363,"previous":"WBV2-P1101-001","next":"WBV2-P1101-003"},"WBV2-P1101-003":{"line":8,"offset":2824,"length":374,"previous":"WBV2-P1101-002","next":"WBV2-P1102-000"},"WBV2-P1102-000":{"line":9,"offset":3198,"length":365,"previous":"WBV2-P1101-003","next":"WBV2-P1102-001"},"WBV2-P1102-001":{"line":10,"offset":3563,"length":371,"previous":"WBV2-P1102-000","next":"WBV2-P1103-000"},"WBV2-P1103-000":{"line":11,"offset":3934,"length":373,"previous":"WBV2-P1102-001","next":"WBV2-P1104-000"},"WBV2-P1104-000":{"line":12,"offset":4307,"length":389,"previous":"WBV2-P1103-000","next":"WBV2-P1105-000"},"WBV2-P1105-000":{"line":13,"offset":4696,"length":426,"previous":"WBV2-P1104-000","next":"WBV2-P1106-000"},"WBV2-P1106-000":{"line":14,"offset":5122,"length":366,"previous":"WBV2-P1105-000","next":"WBV2-P1107-000"},"WBV2-P1107-000":{"line":15,"offset":5488,"length":373,"previous":"WBV2-P1106-000","next":"WBV2-P1108-000"},"WBV2-P1108-000":{"line":16,"offset":5861,"length":385,"previous":"WBV2-P1107-000","next":"WBV2-P1109-000"},"WBV2-P1109-000":{"line":17,"offset":6246,"length":397,"previous":"WBV2-P1108-000","next":"WBV2-P1110-000"},"WBV2-P1110-000":{"line":18,"offset":6643,"length":394,"previous":"WBV2-P1109-000","next":"WBV2-P1111-000"},"WBV2-P1111-000":{"line":19,"offset":7037,"length":384,"previous":"WBV2-P1110-000","next":"WBV2-P1112-000"},"WBV2-P1112-000":{"line":20,"offset":7421,"length":397,"previous":"WBV2-P1111-000","next":"WBV2-P1113-000"},"WBV2-P1113-000":{"line":21,"offset":7818,"length":393,"previous":"WBV2-P1112-000","next":"WBV2-P1114-000"},"WBV2-P1114-000":{"line":22,"offset":8211,"length":384,"previous":"WBV2-P1113-000","next":"WBV2-P1115-000"},"WBV2-P1115-000":{"line":23,"offset":8595,"length":388,"previous":"WBV2-P1114-000","next":"WBV2-P1116-000"},"WBV2-P1116-000":{"line":24,"offset":8983,"length":388,"previous":"WBV2-P1115-000","next":"WBV2-P1117-000"},"WBV2-P1117-000":{"line":25,"offset":9371,"length":413,"previous":"WBV2-P1116-000","next":"WBV2-P1118-000"},"WBV2-P1118-000":{"line":26,"offset":9784,"length":409,"previous":"WBV2-P1117-000","next":"WBV2-P1119-000"},"WBV2-P1119-000":{"line":27,"offset":10193,"length":379,"previous":"WBV2-P1118-000","next":"WBV2-P1120-000"},"WBV2-P1120-000":{"line":28,"offset":10572,"length":392,"previous":"WBV2-P1119-000","next":"WBV2-P1121-000"},"WBV2-P1121-000":{"line":29,"offset":10964,"length":375,"previous":"WBV2-P1120-000","next":"WBV2-P1122-000"},"WBV2-P1122-000":{"line":30,"offset":11339,"length":385,"previous":"WBV2-P1121-000","next":"WBV2-P1123-000"},"WBV2-P1123-000":{"line":31,"offset":11724,"length":385,"previous":"WBV2-P1122-000","next":"WBV2-P1124-000"},"WBV2-P1124-000":{"line":32,"offset":12109,"length":431,"previous":"WBV2-P1123-000","next":"WBV2-P1125-000"},"WBV2-P1125-000":{"line":33,"offset":12540,"length":406,"previous":"WBV2-P1124-000","next":"WBV2-P1126-000"},"WBV2-P1126-000":{"line":34,"offset":12946,"length":397,"previous":"WBV2-P1125-000","next":"WBV2-P1127-000"},"WBV2-P1127-000":{"line":35,"offset":13343,"length":406,"previous":"WBV2-P1126-000","next":"WBV2-P1128-000"},"WBV2-P1128-000":{"line":36,"offset":13749,"length":406,"previous":"WBV2-P1127-000","next":"WBV2-P1129-000"},"WBV2-P1129-000":{"line":37,"offset":14155,"length":331,"previous":"WBV2-P1128-000","next":"WBV2-P1129-001"},"WBV2-P1129-001":{"line":38,"offset":14486,"length":393,"previous":"WBV2-P1129-000","next":"WBV2-P1130-000"},"WBV2-P1130-000":{"line":39,"offset":14879,"length":348,"previous":"WBV2-P1129-001","next":"WBV2-P1130-001"},"WBV2-P1130-001":{"line":40,"offset":15227,"length":387,"previous":"WBV2-P1130-000","next":"WBV2-P1131-000"},"WBV2-P1131-000":{"line":41,"offset":15614,"length":349,"previous":"WBV2-P1130-001","next":"WBV2-P1131-001"},"WBV2-P1131-001":{"line":42,"offset":15963,"length":383,"previous":"WBV2-P1131-000","next":"WBV2-P1132-000"},"WBV2-P1132-000":{"line":43,"offset":16346,"length":345,"previous":"WBV2-P1131-001","next":"WBV2-P1132-001"},"WBV2-P1132-001":{"line":44,"offset":16691,"length":380,"previous":"WBV2-P1132-000","next":"WBV2-P1133-000"},"WBV2-P1133-000":{"line":45,"offset":17071,"length":346,"previous":"WBV2-P1132-001","next":"WBV2-P1133-001"},"WBV2-P1133-001":{"line":46,"offset":17417,"length":387,"previous":"WBV2-P1133-000","next":"WBV2-P1134-000"},"WBV2-P1134-000":{"line":47,"offset":17804,"length":353,"previous":"WBV2-P1133-001","next":"WBV2-P1134-001"},"WBV2-P1134-001":{"line":48,"offset":18157,"length":392,"previous":"WBV2-P1134-000","next":"WBV2-P1135-000"},"WBV2-P1135-000":{"line":49,"offset":18549,"length":339,"previous":"WBV2-P1134-001","next":"WBV2-P1135-001"},"WBV2-P1135-001":{"line":50,"offset":18888,"length":385,"previous":"WBV2-P1135-000","next":"WBV2-P1136-000"},"WBV2-P1136-000":{"line":51,"offset":19273,"length":349,"previous":"WBV2-P1135-001","next":"WBV2-P1136-001"},"WBV2-P1136-001":{"line":52,"offset":19622,"length":391,"previous":"WBV2-P1136-000","next":"WBV2-P1137-000"},"WBV2-P1137-000":{"line":53,"offset":20013,"length":354,"previous":"WBV2-P1136-001","next":"WBV2-P1137-001"},"WBV2-P1137-001":{"line":54,"offset":20367,"length":393,"previous":"WBV2-P1137-000","next":"WBV2-P1138-000"},"WBV2-P1138-000":{"line":55,"offset":20760,"length":340,"previous":"WBV2-P1137-001","next":"WBV2-P1138-001"},"WBV2-P1138-001":{"line":56,"offset":21100,"length":388,"previous":"WBV2-P1138-000","next":"WBV2-P1139-000"},"WBV2-P1139-000":{"line":57,"offset":21488,"length":344,"previous":"WBV2-P1138-001","next":"WBV2-P1139-001"},"WBV2-P1139-001":{"line":58,"offset":21832,"length":393,"previous":"WBV2-P1139-000","next":"WBV2-P1140-000"},"WBV2-P1140-000":{"line":59,"offset":22225,"length":362,"previous":"WBV2-P1139-001","next":"WBV2-P1140-001"},"WBV2-P1140-001":{"line":60,"offset":22587,"length":382,"previous":"WBV2-P1140-000","next":"WBV2-P1141-000"},"WBV2-P1141-000":{"line":61,"offset":22969,"length":368,"previous":"WBV2-P1140-001","next":"WBV2-P1141-001"},"WBV2-P1141-001":{"line":62,"offset":23337,"length":389,"previous":"WBV2-P1141-000","next":"WBV2-P1142-000"},"WBV2-P1142-000":{"line":63,"offset":23726,"length":364,"previous":"WBV2-P1141-001","next":"WBV2-P1142-001"},"WBV2-P1142-001":{"line":64,"offset":24090,"length":383,"previous":"WBV2-P1142-000","next":"WBV2-P1143-000"},"WBV2-P1143-000":{"line":65,"offset":24473,"length":369,"previous":"WBV2-P1142-001","next":"WBV2-P1143-001"},"WBV2-P1143-001":{"line":66,"offset":24842,"length":385,"previous":"WBV2-P1143-000","next":"WBV2-P1144-000"},"WBV2-P1144-000":{"line":67,"offset":25227,"length":351,"previous":"WBV2-P1143-001","next":"WBV2-P1144-001"},"WBV2-P1144-001":{"line":68,"offset":25578,"length":376,"previous":"WBV2-P1144-000","next":"WBV2-P1145-000"},"WBV2-P1145-000":{"line":69,"offset":25954,"length":371,"previous":"WBV2-P1144-001","next":"WBV2-P1145-001"},"WBV2-P1145-001":{"line":70,"offset":26325,"length":386,"previous":"WBV2-P1145-000","next":"WBV2-P1146-000"},"WBV2-P1146-000":{"line":71,"offset":26711,"length":303,"previous":"WBV2-P1145-001","next":"WBV2-P1146-001"},"WBV2-P1146-001":{"line":72,"offset":27014,"length":356,"previous":"WBV2-P1146-000","next":"WBV2-P1147-000"},"WBV2-P1147-000":{"line":73,"offset":27370,"length":303,"previous":"WBV2-P1146-001","next":"WBV2-P1147-001"},"WBV2-P1147-001":{"line":74,"offset":27673,"length":360,"previous":"WBV2-P1147-000","next":"WBV2-P1148-000"},"WBV2-P1148-000":{"line":75,"offset":28033,"length":303,"previous":"WBV2-P1147-001","next":"WBV2-P1148-001"},"WBV2-P1148-001":{"line":76,"offset":28336,"length":362,"previous":"WBV2-P1148-000","next":null}}} +{"schemaVersion":1,"operation":"BLENDER_WEB_CAPABILITY_TASK_INDEX","source":{"path":"tests/golden/WBV2-P1149-000/module-execution-plan.json","sha256":"4420220b364b1b66d96a1547b8cec2e7e11df047657fbdbe0c9c59e052febd0f"},"catalog":{"path":"tests/golden/WBV2/task-catalog.jsonl","sha256":"b11a289f8be05699c71928d0bcf5e9ec1855b00b6fdc12c061eefe5b3b523ead"},"taskCount":79,"activeTask":null,"entries":{"WBV2-P1096-000":{"line":0,"offset":0,"length":267,"previous":"WBV2-P1095-003","next":"WBV2-P1100-000"},"WBV2-P1100-000":{"line":1,"offset":267,"length":300,"previous":"WBV2-P1096-000","next":"WBV2-P1100-001"},"WBV2-P1100-001":{"line":2,"offset":567,"length":375,"previous":"WBV2-P1100-000","next":"WBV2-P1100-002"},"WBV2-P1100-002":{"line":3,"offset":942,"length":377,"previous":"WBV2-P1100-001","next":"WBV2-P1100-003"},"WBV2-P1100-003":{"line":4,"offset":1319,"length":386,"previous":"WBV2-P1100-002","next":"WBV2-P1101-000"},"WBV2-P1101-000":{"line":5,"offset":1705,"length":374,"previous":"WBV2-P1100-003","next":"WBV2-P1101-001"},"WBV2-P1101-001":{"line":6,"offset":2079,"length":382,"previous":"WBV2-P1101-000","next":"WBV2-P1101-002"},"WBV2-P1101-002":{"line":7,"offset":2461,"length":363,"previous":"WBV2-P1101-001","next":"WBV2-P1101-003"},"WBV2-P1101-003":{"line":8,"offset":2824,"length":374,"previous":"WBV2-P1101-002","next":"WBV2-P1102-000"},"WBV2-P1102-000":{"line":9,"offset":3198,"length":365,"previous":"WBV2-P1101-003","next":"WBV2-P1102-001"},"WBV2-P1102-001":{"line":10,"offset":3563,"length":371,"previous":"WBV2-P1102-000","next":"WBV2-P1103-000"},"WBV2-P1103-000":{"line":11,"offset":3934,"length":373,"previous":"WBV2-P1102-001","next":"WBV2-P1104-000"},"WBV2-P1104-000":{"line":12,"offset":4307,"length":389,"previous":"WBV2-P1103-000","next":"WBV2-P1105-000"},"WBV2-P1105-000":{"line":13,"offset":4696,"length":426,"previous":"WBV2-P1104-000","next":"WBV2-P1106-000"},"WBV2-P1106-000":{"line":14,"offset":5122,"length":366,"previous":"WBV2-P1105-000","next":"WBV2-P1107-000"},"WBV2-P1107-000":{"line":15,"offset":5488,"length":373,"previous":"WBV2-P1106-000","next":"WBV2-P1108-000"},"WBV2-P1108-000":{"line":16,"offset":5861,"length":385,"previous":"WBV2-P1107-000","next":"WBV2-P1109-000"},"WBV2-P1109-000":{"line":17,"offset":6246,"length":397,"previous":"WBV2-P1108-000","next":"WBV2-P1110-000"},"WBV2-P1110-000":{"line":18,"offset":6643,"length":394,"previous":"WBV2-P1109-000","next":"WBV2-P1111-000"},"WBV2-P1111-000":{"line":19,"offset":7037,"length":384,"previous":"WBV2-P1110-000","next":"WBV2-P1112-000"},"WBV2-P1112-000":{"line":20,"offset":7421,"length":397,"previous":"WBV2-P1111-000","next":"WBV2-P1113-000"},"WBV2-P1113-000":{"line":21,"offset":7818,"length":393,"previous":"WBV2-P1112-000","next":"WBV2-P1114-000"},"WBV2-P1114-000":{"line":22,"offset":8211,"length":384,"previous":"WBV2-P1113-000","next":"WBV2-P1115-000"},"WBV2-P1115-000":{"line":23,"offset":8595,"length":388,"previous":"WBV2-P1114-000","next":"WBV2-P1116-000"},"WBV2-P1116-000":{"line":24,"offset":8983,"length":388,"previous":"WBV2-P1115-000","next":"WBV2-P1117-000"},"WBV2-P1117-000":{"line":25,"offset":9371,"length":413,"previous":"WBV2-P1116-000","next":"WBV2-P1118-000"},"WBV2-P1118-000":{"line":26,"offset":9784,"length":409,"previous":"WBV2-P1117-000","next":"WBV2-P1119-000"},"WBV2-P1119-000":{"line":27,"offset":10193,"length":379,"previous":"WBV2-P1118-000","next":"WBV2-P1120-000"},"WBV2-P1120-000":{"line":28,"offset":10572,"length":392,"previous":"WBV2-P1119-000","next":"WBV2-P1121-000"},"WBV2-P1121-000":{"line":29,"offset":10964,"length":375,"previous":"WBV2-P1120-000","next":"WBV2-P1122-000"},"WBV2-P1122-000":{"line":30,"offset":11339,"length":385,"previous":"WBV2-P1121-000","next":"WBV2-P1123-000"},"WBV2-P1123-000":{"line":31,"offset":11724,"length":385,"previous":"WBV2-P1122-000","next":"WBV2-P1124-000"},"WBV2-P1124-000":{"line":32,"offset":12109,"length":431,"previous":"WBV2-P1123-000","next":"WBV2-P1125-000"},"WBV2-P1125-000":{"line":33,"offset":12540,"length":406,"previous":"WBV2-P1124-000","next":"WBV2-P1126-000"},"WBV2-P1126-000":{"line":34,"offset":12946,"length":397,"previous":"WBV2-P1125-000","next":"WBV2-P1127-000"},"WBV2-P1127-000":{"line":35,"offset":13343,"length":406,"previous":"WBV2-P1126-000","next":"WBV2-P1128-000"},"WBV2-P1128-000":{"line":36,"offset":13749,"length":406,"previous":"WBV2-P1127-000","next":"WBV2-P1129-000"},"WBV2-P1129-000":{"line":37,"offset":14155,"length":331,"previous":"WBV2-P1128-000","next":"WBV2-P1129-001"},"WBV2-P1129-001":{"line":38,"offset":14486,"length":393,"previous":"WBV2-P1129-000","next":"WBV2-P1130-000"},"WBV2-P1130-000":{"line":39,"offset":14879,"length":348,"previous":"WBV2-P1129-001","next":"WBV2-P1130-001"},"WBV2-P1130-001":{"line":40,"offset":15227,"length":387,"previous":"WBV2-P1130-000","next":"WBV2-P1131-000"},"WBV2-P1131-000":{"line":41,"offset":15614,"length":349,"previous":"WBV2-P1130-001","next":"WBV2-P1131-001"},"WBV2-P1131-001":{"line":42,"offset":15963,"length":383,"previous":"WBV2-P1131-000","next":"WBV2-P1132-000"},"WBV2-P1132-000":{"line":43,"offset":16346,"length":345,"previous":"WBV2-P1131-001","next":"WBV2-P1132-001"},"WBV2-P1132-001":{"line":44,"offset":16691,"length":380,"previous":"WBV2-P1132-000","next":"WBV2-P1133-000"},"WBV2-P1133-000":{"line":45,"offset":17071,"length":346,"previous":"WBV2-P1132-001","next":"WBV2-P1133-001"},"WBV2-P1133-001":{"line":46,"offset":17417,"length":387,"previous":"WBV2-P1133-000","next":"WBV2-P1134-000"},"WBV2-P1134-000":{"line":47,"offset":17804,"length":353,"previous":"WBV2-P1133-001","next":"WBV2-P1134-001"},"WBV2-P1134-001":{"line":48,"offset":18157,"length":392,"previous":"WBV2-P1134-000","next":"WBV2-P1135-000"},"WBV2-P1135-000":{"line":49,"offset":18549,"length":339,"previous":"WBV2-P1134-001","next":"WBV2-P1135-001"},"WBV2-P1135-001":{"line":50,"offset":18888,"length":385,"previous":"WBV2-P1135-000","next":"WBV2-P1136-000"},"WBV2-P1136-000":{"line":51,"offset":19273,"length":349,"previous":"WBV2-P1135-001","next":"WBV2-P1136-001"},"WBV2-P1136-001":{"line":52,"offset":19622,"length":391,"previous":"WBV2-P1136-000","next":"WBV2-P1137-000"},"WBV2-P1137-000":{"line":53,"offset":20013,"length":354,"previous":"WBV2-P1136-001","next":"WBV2-P1137-001"},"WBV2-P1137-001":{"line":54,"offset":20367,"length":393,"previous":"WBV2-P1137-000","next":"WBV2-P1138-000"},"WBV2-P1138-000":{"line":55,"offset":20760,"length":340,"previous":"WBV2-P1137-001","next":"WBV2-P1138-001"},"WBV2-P1138-001":{"line":56,"offset":21100,"length":388,"previous":"WBV2-P1138-000","next":"WBV2-P1139-000"},"WBV2-P1139-000":{"line":57,"offset":21488,"length":344,"previous":"WBV2-P1138-001","next":"WBV2-P1139-001"},"WBV2-P1139-001":{"line":58,"offset":21832,"length":393,"previous":"WBV2-P1139-000","next":"WBV2-P1140-000"},"WBV2-P1140-000":{"line":59,"offset":22225,"length":362,"previous":"WBV2-P1139-001","next":"WBV2-P1140-001"},"WBV2-P1140-001":{"line":60,"offset":22587,"length":382,"previous":"WBV2-P1140-000","next":"WBV2-P1141-000"},"WBV2-P1141-000":{"line":61,"offset":22969,"length":368,"previous":"WBV2-P1140-001","next":"WBV2-P1141-001"},"WBV2-P1141-001":{"line":62,"offset":23337,"length":389,"previous":"WBV2-P1141-000","next":"WBV2-P1142-000"},"WBV2-P1142-000":{"line":63,"offset":23726,"length":364,"previous":"WBV2-P1141-001","next":"WBV2-P1142-001"},"WBV2-P1142-001":{"line":64,"offset":24090,"length":383,"previous":"WBV2-P1142-000","next":"WBV2-P1143-000"},"WBV2-P1143-000":{"line":65,"offset":24473,"length":369,"previous":"WBV2-P1142-001","next":"WBV2-P1143-001"},"WBV2-P1143-001":{"line":66,"offset":24842,"length":385,"previous":"WBV2-P1143-000","next":"WBV2-P1144-000"},"WBV2-P1144-000":{"line":67,"offset":25227,"length":351,"previous":"WBV2-P1143-001","next":"WBV2-P1144-001"},"WBV2-P1144-001":{"line":68,"offset":25578,"length":376,"previous":"WBV2-P1144-000","next":"WBV2-P1145-000"},"WBV2-P1145-000":{"line":69,"offset":25954,"length":371,"previous":"WBV2-P1144-001","next":"WBV2-P1145-001"},"WBV2-P1145-001":{"line":70,"offset":26325,"length":386,"previous":"WBV2-P1145-000","next":"WBV2-P1146-000"},"WBV2-P1146-000":{"line":71,"offset":26711,"length":303,"previous":"WBV2-P1145-001","next":"WBV2-P1146-001"},"WBV2-P1146-001":{"line":72,"offset":27014,"length":356,"previous":"WBV2-P1146-000","next":"WBV2-P1147-000"},"WBV2-P1147-000":{"line":73,"offset":27370,"length":303,"previous":"WBV2-P1146-001","next":"WBV2-P1147-001"},"WBV2-P1147-001":{"line":74,"offset":27673,"length":360,"previous":"WBV2-P1147-000","next":"WBV2-P1148-000"},"WBV2-P1148-000":{"line":75,"offset":28033,"length":303,"previous":"WBV2-P1147-001","next":"WBV2-P1148-001"},"WBV2-P1148-001":{"line":76,"offset":28336,"length":362,"previous":"WBV2-P1148-000","next":"WBV2-P1149-000"},"WBV2-P1149-000":{"line":77,"offset":28698,"length":303,"previous":"WBV2-P1148-001","next":"WBV2-P1149-001"},"WBV2-P1149-001":{"line":78,"offset":29001,"length":361,"previous":"WBV2-P1149-000","next":null}}}