Skip to content

Commit 9c74521

Browse files
committed
docs(v8): Raschka full-loop closure plan + spec + 12 R-epic bd tickets
Companion docs for the v8 epic (cppmega-mlx-yz6n) opened from the post-v7 audit dialogue with the operator. Scope: close the gallery-to-train round trip in one continuous flow: preset drag → paper hyperparam defaults → scale-down to devbox → memory matrix (precision × topology) → compile-trace panel → z3 sync-necessity advice → mid-canvas feature injection (MTP / MHC / IFIM / Engram / n-gram) → HF nanochat-style data OR tree-sitter+clang GitHub corpus side-stream → N-step real train. R-epics (all bd tickets created under cppmega-mlx-yz6n): R01 paper-defaults table (P1, yz6n.1) R02 scale_down + slider (P1, yz6n.2) R03 memory matrix UI (P1, yz6n.3) R04 auto-fit to host (P1, yz6n.4) R05 MXFP4 on Apple Metal (e2m1) (P2, yz6n.5) R06 compile-trace panel (P2, yz6n.6) R07 z3 sync-necessity checker (P2, yz6n.7) R08 feature-injection bar (P1, yz6n.8) R09 HF nanochat-style quickstart (P1, yz6n.9) R10 tree-sitter / clang GitHub data (P2, yz6n.10) R11 N-step e2e integration (P0, yz6n.11) R12 Playwright full-loop suite (P0, yz6n.12) Spec details: - 7 new RPCs: architectures.scale_down, architectures.auto_fit, memory.matrix, compile.trace, sync.check, data.hf_quickstart, data.github_corpus. - 1 new WS: /ws/data/{job_id}. - 9 new backend files; 7 new UI components. - extras.train carries preset_origin / scale_down_factor / memory_matrix_cell_used / compile_trace / sync_check / feature_injections / data_source markers — every v8 step leaves a verifiable trace. - Spec includes the canonical Playwright full-loop test source (v8_raschka_full_loop.spec.ts) walking R01..R11 with console capture into test.info annotations. Out of scope: NVFP4 (Hopper/Blackwell only), multi-host launcher UI, cross-preset NAS.
1 parent 19cb7a8 commit 9c74521

2 files changed

Lines changed: 637 additions & 0 deletions

File tree

VisualBuilderPlan-v8.md

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
# VisualBuilderPlan-v8 — Raschka-Gallery Full-Loop Closure
2+
3+
**Status**: planned 2026-05-23 (epic `cppmega-mlx-v8`)
4+
5+
**Driver**: post-v7 audit. v7 wired the operator UX (file picker, edge
6+
validation, checkpoint history, smoke_zero1). v8 closes the *gallery-
7+
to-train round trip* the user actually asks for:
8+
9+
> "Из панели вытащить любую модель из galler.html, увидеть её
10+
> архитектурный спек и оригинальные training hyperparams, скейл-даунить
11+
> под мой devbox, увидеть memory matrix × precision × parallelism,
12+
> мутировать (residual / norm / MTP / MHC / Engram / n-gram side-channel),
13+
> увидеть что зафьюзится / материализуется / синхронизируется, поднять
14+
> данные с HF в стиле nanochat ИЛИ с GitHub через tree-sitter+clang,
15+
> прогнать N шагов трейна — и всё это покрыто Playwright e2e."
16+
17+
## bd ticket ID mapping (post-creation)
18+
19+
| R# | scope | bd parent | priority |
20+
|------|----------------------------------------------------|----------------------|----------|
21+
| R01 | Per-preset training defaults (lr/bs/sched from paper) | new epic | P1 |
22+
| R02 | scale_down(preset, target_bytes) helper + UI slider | new epic | P1 |
23+
| R03 | Memory matrix UI (precision × parallelism) | new epic | P1 |
24+
| R04 | Auto-fit to detected devbox | new epic | P1 |
25+
| R05 | MXFP4 on Apple Metal (e2m1 block-scaled) | new epic | P2 |
26+
| R06 | Compile-trace panel (inductor / dlpack / fused) | new epic | P2 |
27+
| R07 | Z3 sync-necessity checker + advice | new epic | P2 |
28+
| R08 | Mid-canvas feature injection (MTP/MHC/Engram/n-gram) | new epic | P1 |
29+
| R09 | HF nanochat-style data quick-start | new epic | P1 |
30+
| R10 | Tree-sitter / clang GitHub-corpus side-stream | new epit | P2 |
31+
| R11 | N-step train end-to-end (full closure) | new epic | P0 |
32+
| R12 | Playwright e2e harness for the full loop | new epic | P0 |
33+
34+
## 1. Why v8 exists
35+
36+
The audit dialogue with the operator confirmed the gap is no longer
37+
"can we wire X" but "given any of the 57 presets, can you complete the
38+
*single-pane* journey: drag → see paper defaults → scale-down → see
39+
memory matrix → mutate (feature injection) → see compile/fuse trace →
40+
attach data → run N steps → see live loss". v7-Q delivered the UX
41+
plumbing; v8 delivers the journey *as one e2e flow*.
42+
43+
We have:
44+
- 57 presets in `cppmega_v4/architectures/presets.py` (Raschka coverage)
45+
- `verify_and_estimate` per-brick memory at every mutation
46+
- 17 gotcha rules + `suggest_sharding` + 8 topology factories
47+
- `mx.distributed` real DP/TP/PP (V7-B-real)
48+
- bf16 / fp16 / fp32 / fp8 (e4m3, e8m0 blockscaled) precision toggles
49+
- Plasticity (FIRE/DASH/ReDo), 8-bit Adam/Muon, LossScaler
50+
- Live WS streaming (`/ws/train/{run_id}`, `/ws/gen/{job_id}`,
51+
`/ws/verify/{spec_hash}`) with sparkline + dead-man-switch
52+
- 62 existing Playwright e2e specs
53+
54+
We *don't* have:
55+
- Per-preset paper hyperparameter table
56+
- Auto scale-down API
57+
- MXFP4 (Metal e2m1 path)
58+
- Compile-trace visualization
59+
- Z3 sync-necessity check
60+
- Tree-sitter/clang GitHub side-stream
61+
- HF nanochat-style quick-attach
62+
- The single integrated end-to-end e2e test
63+
64+
## 2. Goal
65+
66+
After v8 lands, an operator opens vbgui, picks any preset from the
67+
gallery, and reaches a finished N-step train in one continuous flow
68+
where every intermediate decision is informed by real backend data
69+
(paper defaults, memory matrix, fuse-trace, z3 advice).
70+
71+
## 3. Stages — 12 R-epics × 2-5 sub-tasks ≈ 36 sub-tickets
72+
73+
Workflow per epic stays identical to v5/v6/v7:
74+
discuss → plan → execute → verify, atomic commits per sub-task,
75+
real backend changes never silently degraded to mocks.
76+
77+
## 4. Per-epic acceptance + sub-task breakdown
78+
79+
### R01 — Per-preset training defaults (P1, 3 subs)
80+
81+
**Why**: dragging llama3_8b currently inherits INITIAL_SPEC's
82+
generic `lr=1e-3 / adamw / constant`, not the paper's
83+
`lr=3e-4, wsd schedule, β=(0.9, 0.95)`. The operator must
84+
re-discover paper hyperparams from scratch.
85+
86+
**Subs**:
87+
- R01.1 `cppmega_v4/architectures/preset_training_defaults.py`:
88+
table keyed by preset → {lr, batch, schedule, betas, gradient_clip,
89+
warmup_steps, mixed_precision, source_paper_url}. ≥ 30 presets covered.
90+
- R01.2 `build_preset_specs` RPC grows `defaults: TrainingDefaults`
91+
alongside `specs`; UI auto-fills LossTab / OptimTab / ScheduleEditor.
92+
- R01.3 Vitest + pytest parity check that defaults round-trip.
93+
94+
**AC**: pick `llama3_8b` → OptimTab shows `lr=3e-4` automatically; pick
95+
`gpt_oss_120b` → schedule pre-populates with `cosine warmup=2000`.
96+
97+
### R02 — scale_down(preset, target_bytes) helper + UI slider (P1, 4 subs)
98+
99+
**Subs**:
100+
- R02.1 `cppmega_v4/architectures/scale_down.py:scale_down_preset(preset, target_bytes, *, min_dim=64) -> dict`:
101+
binary-search `hidden_size`, fall back to `num_layers` halving when
102+
hidden_size hits min_dim. Returns the resolved
103+
`(hidden_size, num_layers, est_bytes)`.
104+
- R02.2 New RPC `architectures.scale_down` (registry + dispatcher).
105+
- R02.3 UI: target-memory slider in GalleryTab → live `est_bytes`
106+
preview before drag-to-canvas.
107+
- R02.4 pytest: scale_down(llama3_8b, 1GB) ≤ 1GB and ≥ 0.5GB.
108+
109+
### R03 — Memory matrix UI (P1, 3 subs)
110+
111+
**Subs**:
112+
- R03.1 RPC `memory.matrix(spec, topologies, precisions) -> Matrix`
113+
returns 4 topologies × 4 precisions (fp32, bf16, fp16, fp8) per-rank
114+
worst-case bytes, plus a `fits` boolean per cell.
115+
- R03.2 UI: new `MemoryMatrix.tsx` (16 cells, color-coded fit/no-fit,
116+
hover for breakdown). Lives in sidebar/MemoryMatrixTab.
117+
- R03.3 Playwright: pick preset → matrix renders 16 cells → at least
118+
one cell green on `m3_ultra_solo`.
119+
120+
### R04 — Auto-fit to detected devbox (P1, 2 subs)
121+
122+
**Subs**:
123+
- R04.1 `platform.get_info` already returns the host's RAM/Metal info.
124+
New RPC `architectures.auto_fit(preset, host_info)` chains scale_down
125+
+ suggest_sharding to pick the smallest valid (hidden, layers, axes)
126+
that fits.
127+
- R04.2 UI: "Auto-fit to this Mac" button next to GalleryTab preset →
128+
one-click drop to canvas with scaled spec.
129+
130+
### R05 — MXFP4 on Apple Metal (e2m1 block-scaled) (P2, 4 subs)
131+
132+
**Why**: user explicitly asked. NVIDIA NVFP4 is Hopper/Blackwell-only
133+
but Apple MLX 0.16+ exposes a `mx.metal` block-scaled e2m1 quant
134+
path the user nicknamed mx4. This is a real opportunity.
135+
136+
**Subs**:
137+
- R05.1 `cppmega_mlx/quant/mxfp4_metal.py`: e2m1 block-scaled quant
138+
(16-elem blocks, fp8 e4m3 scales) using `mx.metal_kernel`. Round-trip
139+
RMSE ≤ bf16 → bf16 quant.
140+
- R05.2 SchemeRouter (`_quantize_8bit.py`) gets `QUANT_SCHEME_MXFP4`.
141+
- R05.3 Sharding spec gets `mxfp4_enabled` flag mirroring `fp8_enabled`.
142+
- R05.4 Parity test: e2m1 quant ↔ bf16 within ≤ 5% RMSE on a random
143+
tensor; smoke-train at mxfp4 reaches finite loss.
144+
145+
### R06 — Compile-trace panel (P2, 4 subs)
146+
147+
**Why**: user wants to see *what* the compiler fuses, what materializes,
148+
what passes through dlpack, and where MLX vs torch.compile vs TileLang
149+
takes over.
150+
151+
**Subs**:
152+
- R06.1 RPC `compile.trace(spec, backend in {mlx, tilelang, torch_inductor})`:
153+
reuses `torch_compile_backend.inspect_fx_graph` for the torch path
154+
and `dispatch_lower(prim, return_msl=True)` for the TileLang path.
155+
Returns `{ops: [{name, fused, materialised, dlpack_boundary}],
156+
fused_groups: [...], compile_artifact_path}`.
157+
- R06.2 UI: `CompileTracePanel.tsx` — list ops with colored chips:
158+
green=fused, yellow=dlpack-crossing, red=materialised, gray=stays
159+
in source backend.
160+
- R06.3 Hook into BrickContextPanel — clicking a brick highlights its
161+
ops in the trace.
162+
- R06.4 pytest: trace on a small spec returns ≥ 1 fused group when the
163+
TileLang path is engaged.
164+
165+
### R07 — Z3 sync-necessity checker (P2, 3 subs)
166+
167+
**Why**: every dlpack boundary or `mx.eval` is a candidate sync point;
168+
many are unnecessary. Z3 can prove necessity from the data-flow graph.
169+
170+
**Subs**:
171+
- R07.1 `cppmega_v4/spec/sync_checker.py`: build a small SSA-style
172+
graph from the spec's brick chain; encode constraints
173+
("op B reads tensor X which op A writes; if A and B are on same
174+
backend, no sync needed"); solve with z3 (`z3-solver` dep). Returns
175+
`{necessary_syncs: [...], redundant_syncs: [{op, reason}], advice: [...]}`.
176+
- R07.2 RPC `sync.check(spec)`.
177+
- R07.3 UI: badge in CompileTracePanel — "3 redundant syncs, click
178+
for advice"; advice modal explains each candidate.
179+
180+
### R08 — Mid-canvas feature injection (P1, 4 subs)
181+
182+
**Subs**:
183+
- R08.1 `cppmega_v4/buildspec/rewriters.py` already has MTP /
184+
MHC / IFIM / Engram rewriters — confirm and surface in catalog.
185+
- R08.2 `catalog.list_options('feature_injectors')` enumerates
186+
available rewriters with their effect descriptions.
187+
- R08.3 UI: new `FeatureInjectionBar.tsx` between ParallelComposeBar
188+
and InsertIntoEdgeBar — dropdown of {MTP_WEIGHTED, MHC, IFIM, Engram,
189+
n_gram_side_channel} + Apply button. Mutation goes through existing
190+
rewriter pipeline.
191+
- R08.4 Playwright: apply MTP rewriter via the bar → run train → assert
192+
`extras.train.mtp.per_head_losses` populates (proves the rewriter
193+
actually fired, not just listed).
194+
195+
### R09 — HF nanochat-style data quick-start (P1, 3 subs)
196+
197+
**Subs**:
198+
- R09.1 `scripts/data/hf_quickstart.py`: takes
199+
`{dataset_id, split, tokenizer, n_tokens}`, streams from HF (datasets
200+
lib), tokenizes with the chosen tokenizer, writes a tmp parquet
201+
shard ready for stage_train. Matches the karpathy-nanochat "fineweb
202+
edu shuffle" pattern.
203+
- R09.2 RPC `data.hf_quickstart` (long-running, publishes progress on
204+
`/ws/data/{job_id}`).
205+
- R09.3 UI: button in DataInspector — "Quick-start from HF" → modal
206+
with dataset_id input + token-budget slider; on completion the
207+
parquet path auto-populates.
208+
209+
### R10 — Tree-sitter / clang GitHub-corpus side-stream (P2, 4 subs)
210+
211+
**Subs**:
212+
- R10.1 We already have `scripts/nanochat_data/clang_enriched_to_parquet.py`
213+
+ `extract_git_history.py`. Wrap them into a single
214+
`scripts/data/github_corpus.py {repo_url, max_commits, max_tokens}`.
215+
- R10.2 RPC `data.github_corpus` parallel to `data.hf_quickstart`.
216+
- R10.3 UI: tabs in the HF-quickstart modal — "HF Hub" vs "GitHub
217+
repo (tree-sitter / clang)".
218+
- R10.4 Playwright: drive the GitHub branch against a small public
219+
repo; assert the resulting parquet has `source_doc_id` + clang
220+
side-channels populated.
221+
222+
### R11 — N-step train end-to-end (P0, 3 subs)
223+
224+
**Subs**:
225+
- R11.1 No new RPC — this is the *integration*: pick preset → R01/R02/R03
226+
fire → R08 inject MTP → R09/R10 attach data → stage_train runs N
227+
steps with live WS sparkline (V7-L37..L41 already shipped).
228+
- R11.2 Document the canonical flow in a new
229+
`docs/raschka_full_loop.md` cookbook.
230+
- R11.3 Manual UAT script in `docs/uat/v8_raschka_full_loop.md`:
231+
10-step user journey with expected screenshots.
232+
233+
### R12 — Playwright e2e harness for the full loop (P0, 3 subs)
234+
235+
**Subs**:
236+
- R12.1 `vbgui/e2e/scenarios/v8_raschka_full_loop.spec.ts`: a single
237+
end-to-end test that walks through R01 → R02 → R03 → R08 → R09 → R11
238+
on a synthetic 64-token quick-data path. Total time ≤ 90s on dev box.
239+
- R12.2 Each intermediate assertion captures `page.on('console')` +
240+
`page.on('pageerror')` into `test.info().annotations` so flaky runs
241+
leave diagnosable traces (as the user requested earlier).
242+
- R12.3 A `--full-loop` flag on the e2e runner that picks 5 different
243+
presets in a matrix and validates the same 10-step journey on each.
244+
245+
## 5. Workflow per epic (same as v5/v6/v7)
246+
247+
For each R-epic:
248+
1. `bd update <id> --notes` capturing the audit context above.
249+
2. Discuss → plan → execute → verify per gsd-quick template.
250+
3. Atomic commit per sub-task with `feat(v8-rNN): ...` prefix.
251+
4. Acceptance gate: pytest + vitest + Playwright cover every sub-task.
252+
253+
## 6. Acceptance counters
254+
255+
- **R01..R12**: 12 epics; 36 sub-tickets total.
256+
- **Tests added**: ≈ 25 pytest, ≈ 10 vitest, ≈ 15 Playwright e2e.
257+
- **New RPCs**: `architectures.scale_down`, `architectures.auto_fit`,
258+
`memory.matrix`, `compile.trace`, `sync.check`,
259+
`data.hf_quickstart`, `data.github_corpus`. (+ 3 ws endpoints:
260+
`/ws/data/{job_id}`, others reuse v7.)
261+
- **Backend new files**: ≈ 9.
262+
- **UI new components**: `MemoryMatrix`, `CompileTracePanel`,
263+
`FeatureInjectionBar`, HF/GitHub quickstart modal,
264+
GalleryTab scale-down slider, auto-fit button.
265+
266+
## 7. Out of scope (v9+)
267+
268+
- NVFP4 (Hopper/Blackwell only).
269+
- Multi-host training launcher UI (CLI runbook only — `mlx.launch` /
270+
mpirun via `scripts/launch_multi.py` ships in v7-B-real).
271+
- Replacing existing `tiny_aya` / `zaya1` preset internals.
272+
- Cross-preset auto-arch-search (NAS).
273+
274+
## 8. Done definition
275+
276+
- All 12 R-epics closed in bd.
277+
- VisualBuilderPlan-v8.md + VisualBuilderSpec-v8.md present.
278+
- `v8_raschka_full_loop.spec.ts` green on llama3_8b, qwen3_dense_4b,
279+
gemma3_27b, deepseek_v3, gpt_oss_20b.
280+
- `docs/raschka_full_loop.md` + `docs/uat/v8_raschka_full_loop.md`
281+
written.

0 commit comments

Comments
 (0)