|
| 1 | +# VisualBuilderPlan-v6 — UI Wiring + Real Math-Effect for V5 Placeholders |
| 2 | + |
| 3 | +**Status**: planned 2026-05-22 (epic id TBD) |
| 4 | +**Driver**: V5 closure audit found that out of 25 closed tickets, only |
| 5 | +~11 are real math-effect. The remaining 14 split between: |
| 6 | +- **"backend ready + UI not wired"** — 10 gaps where pytest passes but |
| 7 | + pressing nothing through UI can reproduce the effect (G05/G07/G09/G10/ |
| 8 | + G12/G17/G19/G20/G15/G11) |
| 9 | +- **observation-only** — 4 gaps where extras report numbers but UI parity |
| 10 | + / forward effect / lifecycle recovery never asserted (G06/G08/G18/G21) |
| 11 | +- **analytical proxies** — 3 gaps where extras reports `λ×something_norm` |
| 12 | + instead of running actual kernel (G07/G17/G25) |
| 13 | + |
| 14 | +v6 closes the **backend-ready → UI-wired → real-math-effect** triangle. |
| 15 | + |
| 16 | +## 1. Why v6 exists |
| 17 | + |
| 18 | +V5 honest audit produced this taxonomy (25 gaps): |
| 19 | + |
| 20 | +### A. UI wiring of V5 backends (10 gaps) |
| 21 | +Backend contracts shipped, no UI surface or App dispatch route. Through |
| 22 | +UI a user cannot reproduce what pytest covers. |
| 23 | + |
| 24 | +| Gap | V5 origin | UI work needed | |
| 25 | +|------|-----------|-----------------------------------------------------| |
| 26 | +| H01 | G05 | Sharding ShardingTab → axis assignments → train | |
| 27 | +| H02 | G07 | TopBar fp8/mixed_precision toggles → train | |
| 28 | +| H03 | G09 | TopBar Cancel button + WS abort RPC + cancelled status row | |
| 29 | +| H04 | G10 | TopBar train-warm-start checkbox → opts.continue_from_run_id | |
| 30 | +| H05 | G12 | TopBar checkpoint-save/load path inputs → opts | |
| 31 | +| H06 | G15 | UI Train N=100 walk + e2e on real-corpus | |
| 32 | +| H07 | G19 | App dispatches DimensionsTab Apply → re-verify loop | |
| 33 | +| H08 | G20 | TopBar train-probe-text textarea → opts.inference_probe_text | |
| 34 | +| H09 | G11 | Save→Load roundtrip Train → extras parity e2e | |
| 35 | +| H10 | (V4-10) | SideChannelsTab (proper) replacing dropdown checkboxes| |
| 36 | + |
| 37 | +### B. Observation → math-effect upgrade (4 gaps) |
| 38 | +Extras report numbers but no parity / recovery / forward-effect assertion. |
| 39 | + |
| 40 | +| Gap | V5 origin | Math claim to assert | |
| 41 | +|------|-----------|-----------------------------------------------------| |
| 42 | +| H11 | G06 | memory_peak_bytes within 30% of UI MemoryBar estimate| |
| 43 | +| H12 | G08 | mid-train WS drop → reconnect → state preserved e2e | |
| 44 | +| H13 | G21 | UI walk through smoke pipeline asserting each stage extras | |
| 45 | +| H14 | G18 | AblationsTab table shows full extras per row (not just final) | |
| 46 | + |
| 47 | +### C. Real math-effect for V5 analytical proxies (5 gaps) |
| 48 | +V5 returned `λ×proxy_norm` instead of running the kernel. |
| 49 | + |
| 50 | +| Gap | V5 origin | Real-math upgrade | |
| 51 | +|------|-----------|-----------------------------------------------------| |
| 52 | +| H15 | G05 | stage_train simulates per-rank shard (loss parity) | |
| 53 | +| H16 | G07 | mlx dtype switching actually casts params | |
| 54 | +| H17 | G17 | doc_ids → real attention mask in attention forward | |
| 55 | +| H18 | G25 | MoE forward hook → routing entropy + load balance | |
| 56 | +| H19 | G12 | Strict identical-loss-continuation: save→load→losses[0]==saved[-1] within 1e-5 | |
| 57 | + |
| 58 | +### D. Multi-device / advanced (5 gaps) |
| 59 | +| Gap | Description | |
| 60 | +|------|------------------------------------------------------| |
| 61 | +| H20 | Multi-device distributed train smoke (2 fake ranks) | |
| 62 | +| H21 | Inference-after-resume generation drift bounded | |
| 63 | +| H22 | Concurrent Train clicks → second click queued or rejected | |
| 64 | +| H23 | fp16 dtype option alongside bf16/fp8 | |
| 65 | +| H24 | 100+ step UI walk → checkpoint → resume → continuation| |
| 66 | + |
| 67 | +### E. Meta-honesty (1 gap) |
| 68 | +| Gap | Description | |
| 69 | +|------|------------------------------------------------------| |
| 70 | +| H25 | Honest categorisation audit across V3+V4+V5 tests — every test labelled 🟢 math-effect / 🟡 propagation / 🔴 decorative. Target 0 🔴, no propagation in math-claimed surfaces. | |
| 71 | + |
| 72 | +## 2. Goal |
| 73 | + |
| 74 | +After v6: every V5 backend with a math claim has a UI surface that lets |
| 75 | +the user trigger it AND an e2e test that walks UI→backend→numerical |
| 76 | +assertion. Zero "backend pytest works but UI can't reach it" tests. |
| 77 | + |
| 78 | +## 3. Stages — 25 H-gaps × 6-10 sub-tasks ≈ 200 sub-tickets |
| 79 | + |
| 80 | +``` |
| 81 | +cppmega-mlx-v6 (epic) |
| 82 | +├── H01-H10 UI wiring of V5 (10 × 6-8) |
| 83 | +├── H11-H14 obs→math upgrade (4 × 7-9) |
| 84 | +├── H15-H19 real-math for proxies (5 × 8-10) |
| 85 | +├── H20-H24 advanced (5 × 8-10) |
| 86 | +└── H25 meta-honesty (1 × 6) |
| 87 | +
|
| 88 | +Total: ~190 sub-tickets |
| 89 | +``` |
| 90 | + |
| 91 | +## 4. Per-gap acceptance + sub-task breakdown |
| 92 | + |
| 93 | +### H01 — Sharding ShardingTab → train (UI wiring V5-G05, 8) |
| 94 | +- H01.1 ShardingTab accept proposal updates spec.sharding.axis_assignments |
| 95 | +- H01.2 App.handleRunPipeline forwards via stage_options (verify already wired) |
| 96 | +- H01.3 Topology-axis degree mismatch UI warning |
| 97 | +- H01.4 Train button respects sharding-incompatible config (disabled+reason) |
| 98 | +- H01.5 e2e: accept proposal → Train → extras.sharding_applied matches selection |
| 99 | +- H01.6 e2e: change topology mid-canvas → re-verify → new axes shown |
| 100 | +- H01.7 vitest ShardingTab dispatch |
| 101 | +- H01.8 Closure regression: G05 e2e tightened (compile_mode propagation) |
| 102 | + |
| 103 | +### H02 — fp8/mixed_precision UI → train (UI wiring V5-G07, 7) |
| 104 | +- H02.1 TopBar `top-bar-mixed-precision` checkbox dispatches optim mutation |
| 105 | +- H02.2 TopBar `top-bar-fp8-enabled` checkbox dispatches sharding mutation |
| 106 | +- H02.3 App wire to spec.optim.mixed_precision / spec.sharding.fp8_enabled |
| 107 | +- H02.4 e2e: toggle mixed_precision → extras.master_dtype changes |
| 108 | +- H02.5 e2e: toggle fp8 → extras.fp8_active=true |
| 109 | +- H02.6 vitest TopBar checkboxes |
| 110 | +- H02.7 Honest doc: G07 propagation → UI-driven |
| 111 | + |
| 112 | +### H03 — Cancel button + WS abort RPC (UI wiring V5-G09, 8) |
| 113 | +- H03.1 TopBar Cancel button (`run-pipeline-cancel`) visible while train running |
| 114 | +- H03.2 App tracks running run_id; click → rpc.call("pipeline.abort", {run_id}) |
| 115 | +- H03.3 Backend JSON-RPC method `pipeline.abort` → request_abort(token) |
| 116 | +- H03.4 Modal shows "cancelled" status row with partial losses |
| 117 | +- H03.5 e2e: start N=64 → click Cancel → modal shows partial losses |
| 118 | +- H03.6 e2e: Cancel disabled when no train running |
| 119 | +- H03.7 vitest Cancel button |
| 120 | +- H03.8 Closure: G09 backend → UI-driven cancel |
| 121 | + |
| 122 | +### H04 — train-warm-start checkbox (UI wiring V5-G10, 6) |
| 123 | +- H04.1 TopBar `train-warm-start` checkbox + previousRunId state |
| 124 | +- H04.2 App forwards continue_from_run_id when checked |
| 125 | +- H04.3 e2e: enable warm-start, run twice, second extras.opt_state_carried=true |
| 126 | +- H04.4 e2e: second-run losses[0] < first-run losses[0] |
| 127 | +- H04.5 vitest TopBar checkbox |
| 128 | +- H04.6 Honest doc: G10 backend → UI-driven |
| 129 | + |
| 130 | +### H05 — checkpoint save/load path inputs (UI wiring V5-G12, 8) |
| 131 | +- H05.1 TopBar `train-checkpoint-save-path` text input |
| 132 | +- H05.2 TopBar `train-checkpoint-load-path` text input |
| 133 | +- H05.3 App forwards via stage_options.train |
| 134 | +- H05.4 e2e: set save-path → Train → extras.checkpoint.saved_path matches |
| 135 | +- H05.5 e2e: set load-path → Train → extras.checkpoint.loaded_path matches |
| 136 | +- H05.6 e2e: round-trip save → fresh page → load → Train → losses[0] within 1e-3 of saved[-1] |
| 137 | +- H05.7 vitest TopBar inputs |
| 138 | +- H05.8 Closure: G12 + H19 strict continuation |
| 139 | + |
| 140 | +### H06 — UI N=100 real-corpus walk (UI wiring V5-G15, 7) |
| 141 | +- H06.1 e2e: load real parquet+tokenizer, set N=100, Train (90s budget) |
| 142 | +- H06.2 Assert extras.num_steps==100 |
| 143 | +- H06.3 Assert losses_smoothed monotone-window |
| 144 | +- H06.4 Assert weight_delta_norm > 0.01 |
| 145 | +- H06.5 Assert inference_probe.l2_diff > 0.1 (100 steps significant) |
| 146 | +- H06.6 Perf gate: completes within 120s on Apple Silicon |
| 147 | +- H06.7 Mark long-running tag for CI selective run |
| 148 | + |
| 149 | +### H07 — DimensionsTab Apply dispatches spec mutation (UI wiring V5-G19, 7) |
| 150 | +- H07.1 App.tsx onApply handler maps entry → spec action |
| 151 | +- H07.2 Dispatch sets brick param to suggested value |
| 152 | +- H07.3 Re-verify removes the now-fulfilled suggestion |
| 153 | +- H07.4 e2e: load preset → Apply → row disappears |
| 154 | +- H07.5 e2e: applied suggestion reaches Train via extras.model_summary |
| 155 | +- H07.6 vitest App.onApply mapping |
| 156 | +- H07.7 Honest doc: G19 button → full feedback loop |
| 157 | + |
| 158 | +### H08 — train-probe-text textarea (UI wiring V5-G20, 6) |
| 159 | +- H08.1 TopBar `train-probe-text` textarea in train dropdown |
| 160 | +- H08.2 App forwards via stage_options.train.inference_probe_text |
| 161 | +- H08.3 e2e: provide "hello world", Train → extras.inference_probe.real_tokens=true |
| 162 | +- H08.4 e2e: extras.inference_probe.text_len > 0 |
| 163 | +- H08.5 e2e: top1_token_drift >= 0 |
| 164 | +- H08.6 vitest TopBar textarea |
| 165 | + |
| 166 | +### H09 — Save/Load roundtrip extras parity (UI wiring V5-G11, 8) |
| 167 | +- H09.1 e2e: build spec → Save → capture Blob |
| 168 | +- H09.2 Refresh page → Load same Blob |
| 169 | +- H09.3 Train → capture extras_after_load |
| 170 | +- H09.4 Build identical spec from scratch → Train → extras_baseline |
| 171 | +- H09.5 Assert model_summary equal between two |
| 172 | +- H09.6 Assert losses match within 1e-4 |
| 173 | +- H09.7 vitest serialiser + parser |
| 174 | +- H09.8 Closure: G11 → identical-extras round-trip proven |
| 175 | + |
| 176 | +### H10 — Proper SideChannelsTab (UI wiring V4-10/V5-G17, 9) |
| 177 | +- H10.1 New sidebar tab `sidebar-tab-side-channels` |
| 178 | +- H10.2 Per-family toggle + per-family data preview |
| 179 | +- H10.3 Replace train-dropdown checkboxes |
| 180 | +- H10.4 App wires via stage_options.train.side_channels |
| 181 | +- H10.5 e2e: enable doc_ids in SideChannelsTab → Train → forward_effect populated |
| 182 | +- H10.6 e2e: SideChannelsTab persists across tab switches |
| 183 | +- H10.7 vitest SideChannelsTab toggles |
| 184 | +- H10.8 Honest doc: V4-10 minimum-viable → proper tab |
| 185 | +- H10.9 Closure: replace 24_side_channels.spec.ts with tab-driven version |
| 186 | + |
| 187 | +### H11 — Memory peak vs estimate parity (obs→math V5-G06, 8) |
| 188 | +- H11.1 verify RPC returns `estimated_peak_bytes` (separate from per-rank) |
| 189 | +- H11.2 UI MemoryBar shows both estimate + actual after Train |
| 190 | +- H11.3 vitest MemoryBar dual display |
| 191 | +- H11.4 e2e: Train → assert |actual - estimate| / estimate < 0.5 (within 50%) |
| 192 | +- H11.5 pytest: estimate accuracy on llama3_8b (tighter 30%) |
| 193 | +- H11.6 testid `memory-bar-actual`, `memory-bar-estimate` |
| 194 | +- H11.7 honest categorisation |
| 195 | +- H11.8 closure regression |
| 196 | + |
| 197 | +### H12 — WS reconnect mid-train recovery (obs→math V5-G08, 9) |
| 198 | +- H12.1 e2e: start N=32 train |
| 199 | +- H12.2 page.context().setOffline(true) mid-train |
| 200 | +- H12.3 Wait 2s → setOffline(false) |
| 201 | +- H12.4 Assert BottomStrip shows reconnecting then connected |
| 202 | +- H12.5 Assert modal eventually shows completed train |
| 203 | +- H12.6 Assert no spurious error modal |
| 204 | +- H12.7 Backend WS heartbeat per-step |
| 205 | +- H12.8 vitest reconnect UI states |
| 206 | +- H12.9 Closure: G08 testid → recovery e2e |
| 207 | + |
| 208 | +### H13 — Other-stages extras through UI (obs→math V5-G21, 7) |
| 209 | +- H13.1 e2e: run Smoke pipeline (12 stages) |
| 210 | +- H13.2 Expand each stage row in modal |
| 211 | +- H13.3 Assert dry_forward extras present (batch, seq_len, hidden, num_nodes) |
| 212 | +- H13.4 Assert loss_smoke extras (loss_value, loss_finite) |
| 213 | +- H13.5 Assert optimizer_smoke extras (optimizer_kind, num_groups) |
| 214 | +- H13.6 Negative: skipped stages don't crash on expand |
| 215 | +- H13.7 Closure: G21 pytest → UI-walk e2e |
| 216 | + |
| 217 | +### H14 — AblationsTab full extras display (obs→math V5-G18, 8) |
| 218 | +- H14.1 AblationsTab row shows expand for full extras (like RunResultModal) |
| 219 | +- H14.2 vitest expand renders extras subtree |
| 220 | +- H14.3 e2e: run ablation → expand a variant row → full extras visible |
| 221 | +- H14.4 Assert per-row losses array displayed |
| 222 | +- H14.5 Assert per-row model_summary displayed |
| 223 | +- H14.6 Strict parity: sequential UI Train vs ablation variant — same extras shape |
| 224 | +- H14.7 Honest doc: G18 structural → user-visible |
| 225 | +- H14.8 Closure regression |
| 226 | + |
| 227 | +### H15 — Real per-rank shard simulation (real-math V5-G05, 9) |
| 228 | +- H15.1 Backend: when sharding_applied has FSDP axis, simulate per-rank |
| 229 | + param shard for memory accounting |
| 230 | +- H15.2 extras.sharding_applied gets `per_rank_param_bytes` |
| 231 | +- H15.3 pytest: 8-way FSDP halves per-rank vs unsharded |
| 232 | +- H15.4 pytest: loss bit-identical between sharded and unsharded |
| 233 | +- H15.5 Strict tolerance < 1e-6 |
| 234 | +- H15.6 e2e: UI accept fsdp2 → per_rank_param_bytes populated |
| 235 | +- H15.7 e2e: change to fsdp1 → per_rank_param_bytes differs |
| 236 | +- H15.8 Honest doc: G05 propagation → real simulation |
| 237 | +- H15.9 Closure regression |
| 238 | + |
| 239 | +### H16 — Real mlx dtype switching (real-math V5-G07, 10) |
| 240 | +- H16.1 Backend: when master_dtype="fp32", instantiate params in fp32 |
| 241 | +- H16.2 Backend: when train_dtype="fp16", cast forward inputs |
| 242 | +- H16.3 Backend: when fp8_active=true, attempt fp8 (may fallback w/ reason) |
| 243 | +- H16.4 extras.dtype_actual reports what mlx actually used |
| 244 | +- H16.5 pytest: fp32 master + bf16 train produces different param norms vs all-bf16 |
| 245 | +- H16.6 pytest: fp16 train loss within tolerance of bf16 |
| 246 | +- H16.7 e2e: toggle precision → extras.dtype_actual reflects |
| 247 | +- H16.8 Fallback path: fp8 unsupported → graceful + reason |
| 248 | +- H16.9 Honest doc: G07 string-echo → real cast |
| 249 | +- H16.10 Closure regression |
| 250 | + |
| 251 | +### H17 — Real cross-doc attention mask (real-math V5-G17, 10) |
| 252 | +- H17.1 Backend: _build_attention accepts doc_attention_mask param |
| 253 | +- H17.2 stage_train.forward injects mask when doc_ids in side_channels |
| 254 | +- H17.3 Mask: positions with different doc_ids → -inf in attention scores |
| 255 | +- H17.4 extras.side_channels_forward_effect.doc_mask_applied = bool |
| 256 | +- H17.5 pytest: with doc_ids vs without → losses differ > 1e-4 |
| 257 | +- H17.6 pytest: single-doc (all doc_ids equal) reduces to no-mask |
| 258 | +- H17.7 e2e: UI enable doc_ids → losses differ from disabled |
| 259 | +- H17.8 Token_ids: real conditional embed addition |
| 260 | +- H17.9 Honest doc: G17 proxy → real kernel |
| 261 | +- H17.10 Closure regression |
| 262 | + |
| 263 | +### H18 — MoE forward hook (real-math V5-G25, 10) |
| 264 | +- H18.1 Backend: when MoE brick present, wrap forward with routing hook |
| 265 | +- H18.2 Capture routing weights per token (top-k softmax) |
| 266 | +- H18.3 Compute routing_entropy = mean(-Σ p log p) over tokens |
| 267 | +- H18.4 Compute load_balance_loss = Σ (expert_load - 1/num_experts)² |
| 268 | +- H18.5 Compute dropped_token_ratio when capacity factor < 1 |
| 269 | +- H18.6 extras.moe populated with real values (not nulls) |
| 270 | +- H18.7 pytest: gpt_oss_20b → routing_entropy ∈ (0, log(num_experts)) |
| 271 | +- H18.8 pytest: top_k=1 → routing_entropy < top_k=2 |
| 272 | +- H18.9 e2e: change top_k via brick context → routing_entropy changes |
| 273 | +- H18.10 Honest doc: G25 propagation → real measurement |
| 274 | + |
| 275 | +### H19 — Identical-loss-continuation strict (real-math V5-G12, 9) |
| 276 | +- H19.1 pytest: save checkpoint after N=4 → load → run 1 more step |
| 277 | +- H19.2 Assert losses[0] of resumed == losses[3] of original within 1e-5 |
| 278 | +- H19.3 pytest: same with optimizer state carried (Adam moments) |
| 279 | +- H19.4 e2e: full UI walk Train N=4 save → fresh page Load Train N=1 |
| 280 | +- H19.5 Assert losses[0] match (within 1e-3 since UI noise) |
| 281 | +- H19.6 Backend: opt.state also saved separately (state.safetensors) |
| 282 | +- H19.7 extras.checkpoint.opt_state_path |
| 283 | +- H19.8 Negative: missing opt-state file → warning + cold restart |
| 284 | +- H19.9 Closure regression: G12 smoke → strict math |
| 285 | + |
| 286 | +### H20 — Multi-device distributed smoke (advanced, 10) |
| 287 | +- H20.1 Backend: stage_train accepts opts.fake_ranks=N |
| 288 | +- H20.2 Forward + backward simulated on N fake ranks |
| 289 | +- H20.3 Reduce gradients via mean |
| 290 | +- H20.4 extras.fake_ranks + extras.gradient_reduce_ms |
| 291 | +- H20.5 pytest: fake_ranks=2 vs 1 loss within 1e-6 |
| 292 | +- H20.6 pytest: fake_ranks=4 weight_delta similar magnitude |
| 293 | +- H20.7 e2e: UI selects topology with degree=2 → fake_ranks=2 in extras |
| 294 | +- H20.8 Sharding axis assignment respected per fake rank |
| 295 | +- H20.9 Performance gate: fake_ranks=8 within 2× wall-clock vs 1 |
| 296 | +- H20.10 Closure: real distributed proxy |
| 297 | + |
| 298 | +### H21 — Inference-after-resume bounded drift (advanced, 8) |
| 299 | +- H21.1 Backend: extras.inference_probe.post_resume_drift = float |
| 300 | +- H21.2 Save checkpoint after train; load fresh model; resume train 1 step |
| 301 | +- H21.3 Compare inference probe between {train→save→reload} and {train continuous} |
| 302 | +- H21.4 Assert drift < 1e-3 (proves checkpoint round-trip preserves weights bit-exact) |
| 303 | +- H21.5 pytest end-to-end |
| 304 | +- H21.6 e2e: UI save→fresh→resume→probe text → drift bounded |
| 305 | +- H21.7 Negative: corrupt checkpoint → clear error not crash |
| 306 | +- H21.8 Closure regression |
| 307 | + |
| 308 | +### H22 — Concurrent Train clicks (advanced, 8) |
| 309 | +- H22.1 App tracks trainInFlight state (one at a time) |
| 310 | +- H22.2 Second click while running → queued indicator or rejected |
| 311 | +- H22.3 TopBar Train button shows "Training..." while in-flight |
| 312 | +- H22.4 e2e: click Train twice quickly → only one modal opens |
| 313 | +- H22.5 e2e: second click after first completes → fresh run |
| 314 | +- H22.6 vitest Train button state machine |
| 315 | +- H22.7 Honest doc: lifecycle robust |
| 316 | +- H22.8 Closure regression |
| 317 | + |
| 318 | +### H23 — fp16 dtype option (advanced, 8) |
| 319 | +- H23.1 Schema accepts train_dtype="fp16" |
| 320 | +- H23.2 UI TopBar precision dropdown {bf16, fp16, fp32} |
| 321 | +- H23.3 Backend casts forward inputs to fp16 when selected |
| 322 | +- H23.4 extras.train_dtype reports |
| 323 | +- H23.5 pytest: fp16 loss finite + within 1e-3 of bf16 |
| 324 | +- H23.6 pytest: fp16 weight_delta < fp32 weight_delta (less precision) |
| 325 | +- H23.7 e2e: UI select fp16 → extras.train_dtype=="fp16" |
| 326 | +- H23.8 Closure regression |
| 327 | + |
| 328 | +### H24 — 100+ step UI walk with checkpoint (advanced, 9) |
| 329 | +- H24.1 e2e: load preset + real corpus |
| 330 | +- H24.2 Set N=100, set save-path |
| 331 | +- H24.3 Train → modal completes |
| 332 | +- H24.4 Fresh page → set load-path → set N=20 |
| 333 | +- H24.5 Train → assert losses[0] starts where saved[-1] ended |
| 334 | +- H24.6 Assert continuation within 1e-3 |
| 335 | +- H24.7 Closure of G15 + G12 + H19 chain |
| 336 | +- H24.8 Perf gate < 200s wall-clock |
| 337 | +- H24.9 Mark long-running tag |
| 338 | + |
| 339 | +### H25 — Honest categorisation audit (meta, 7) |
| 340 | +- H25.1 Script audit_v3_v4_v5.py walks all tests/v3+v4+v5/ + vbgui/e2e/scenarios/ |
| 341 | +- H25.2 For each test extracts category (math-effect / propagation / |
| 342 | + decorative) from assertion patterns |
| 343 | +- H25.3 Markdown report: per-test label + assertion summary |
| 344 | +- H25.4 Target: 0 🔴 decorative, 🟡 propagation only on genuinely-config |
| 345 | + fields (e.g. project name) |
| 346 | +- H25.5 vbgui-side counterpart for vitest |
| 347 | +- H25.6 Closure report `tests/fixtures/honesty_audit_v6.md` |
| 348 | +- H25.7 v7 follow-up list |
| 349 | + |
| 350 | +## 5. Workflow per gap (same as v5) |
| 351 | + |
| 352 | +1. `bd update <id> --claim` |
| 353 | +2. Implement (each sub-task atomic) |
| 354 | +3. Code review (self if <100 LOC, gsd-code-reviewer otherwise) |
| 355 | +4. Perf check (no >5% regression on affected suite) |
| 356 | +5. Regression (pytest + vitest + e2e affected) |
| 357 | +6. `git add` specific files → commit → push → verify on origin/main |
| 358 | +7. `bd close <id>` only after push verified |
| 359 | + |
| 360 | +## 6. Acceptance counters |
| 361 | + |
| 362 | +| Surface | Before v6 | Target v6 | |
| 363 | +|----------------------------------------|-----------|-----------| |
| 364 | +| pytest | ~2400 | ≥2500 | |
| 365 | +| vitest | 189 | ≥220 | |
| 366 | +| Playwright deep e2e cells | 120+ | ≥200 | |
| 367 | +| extras keys | 30 | ≥38 | |
| 368 | +| backend-without-UI tests | ~10 | 0 | |
| 369 | +| 🟢 math-effect tests | ~25 | ≥55 | |
| 370 | +| 🟡 propagation tests on math claims | ~10 | 0 | |
| 371 | +| 🔴 decorative tests | 0 | 0 | |
| 372 | + |
| 373 | +## 7. Out of scope (defer to v7+) |
| 374 | + |
| 375 | +- Real multi-mac distributed training (network protocol, gradient |
| 376 | + all-reduce, FSDP2 sharded forward) |
| 377 | +- Production-scale (1B+ param) training matrix |
| 378 | +- A/B hyperparameter search UI |
| 379 | +- Anomaly detection on loss curves (NaN traps, gradient explosion) |
| 380 | +- Live inference serving from trained checkpoint |
| 381 | +- Model weight quantisation post-train |
| 382 | +- LoRA / PEFT adapter wiring |
| 383 | + |
| 384 | +## 8. Done definition |
| 385 | + |
| 386 | +All 25 H-gaps closed. Zero "backend pytest but no UI walk" tests. |
| 387 | +Closure report at `tests/fixtures/e2e_matrix_v6_report.md`. Honest |
| 388 | +categorisation audit at `tests/fixtures/honesty_audit_v6.md`. |
0 commit comments