Status: Partially done. @apvd/worker now has continueTraining, Dual extraction, and WASM init fix (commit 2b73c4b). Static frontend still has duplicated worker/client logic that should be replaced with @apvd/worker imports.
Static's training pipeline has ~1500 lines of duplicated worker/client logic across 3 files, reimplementing what @apvd/worker should provide. The duplication includes:
extractNumber/Point/ShapeDual unwrapping (3 copies)tier/resolution/isKeyframe/nearestKeyframetiered storage (3 copies)- Session management, training loops, progress reporting (2 copies)
WorkerRequest/WorkerResponsetypes (2 copies)
Additionally, @apvd/worker has bugs (missing WASM init, no Dual unwrapping) and missing features (continueTraining, sparkline data extraction).
Goal: Make @apvd/worker the single source of truth, then have static use it.
Static FE active code path:
App.tsx
→ TrainingClientProvider (contexts/TrainingClientContext.tsx, 789 lines)
→ createWorkerClient(worker) [prod] / createMainThreadClient() [dev]
→ useTrainingClientHook (hooks/useTrainingClient.ts, 1059 lines)
→ client.continueTraining() for batch advances
→ apvd.make_step() on main thread for step display
Dead code:
hooks/useTraining.ts (303 lines) - no longer imported
hooks/useCompactedModel.ts - only imported by useTraining.ts
- Add
"continueTraining"toWorkerRequest.typeunion - Add
ContinueTrainingResulttype (move from static's TrainingClientContext.tsx):export interface ContinueTrainingResult { totalSteps: number currentStep: number minError: number minStep: number currentShapes: Shape[] currentError: number steps: Array<{ stepIndex: number; error: number; shapes: Shape[] }> sparklineData?: SparklineData }
- Add
continueTraining(handle, numSteps)toTrainingClientinterface
- Fix WASM init bug (line 86): Add
await wasm.default?.()beforewasm.init_logs() - Add Dual unwrapping functions (
extractNumber,extractPoint,extractShape,extractShapes) — move from static's worker.ts - Use
extractShapeseverywhere instead of rawas Shape[]casts (current code returns Dual-wrapped shapes to client) - Add
handleContinueTraininghandler — port from static's worker.ts (usesapvd.train()for batch computation, extracts sparkline data) - Add
"continueTraining"case toonmessageswitch - Add sparkline data extraction to
handleTrainBatch(currently missing — static's version extracts gradients and per-region errors)
- Add
continueTraining(handle: TrainingHandle, numSteps: number): Promise<ContinueTrainingResult>method toWorkerTrainingClient
- Export
extractNumber,extractPoint,extractShape,extractShapes(static's main-thread client and useTrainingClient hook need these)
// Re-export @apvd/worker's worker implementation.
// This file exists so Vite can bundle it with proper dependency resolution.
import "@apvd/worker/worker"Remove:
createWorkerClient()function (~70 lines) — useWorkerTrainingClientfrom@apvd/worker- All
extractNumber/Point/Shape/Shapesfunctions (~50 lines) — import from@apvd/worker WorkerRequest/WorkerResponsetype definitionsBatchTrainingRequest/BatchStep/BatchTrainingResulttype definitions — import from@apvd/clientContinueTrainingResult/SparklineDatatype definitions — import from@apvd/client
Keep:
TrainingClientextended interface (addscontinueTrainingto base)createMainThreadClient()for dev mode (but importextractShapesfrom@apvd/worker)TrainingClientProvider,useTrainingClientcontext/hookisDevcheck for prod/dev switching
Update production path:
import { WorkerTrainingClient } from "@apvd/worker"
// ...
const workerClient = new WorkerTrainingClient(
new URL("../workers/training.worker?worker", import.meta.url)
)- Remove
extractNumber/Point/Shape/Shapes(3rd copy, ~50 lines) — import from@apvd/worker - Remove
tier/resolution/isKeyframehelpers (~20 lines) — import from@apvd/workeror@apvd/wasm - Import
ContinueTrainingResult,SparklineData,TraceExport,TraceExportV2from@apvd/clientinstead of redefining - Remove local
TraceExport/TraceExportV2type definitions (~50 lines) — already in@apvd/client/types.ts
- Delete
src/hooks/useTraining.ts(303 lines, no imports) - Delete
src/hooks/useCompactedModel.ts(only imported by dead useTraining.ts)
- @apvd/worker currently uses fixed LR:
step(wasmStep, learningRate)(default 0.05) - Static uses error-scaled:
step(wasmStep, prevError * learningRate)(default 0.5) continueTraininguses Rust'strain()which does error-scaled internally- Resolution: Keep fixed LR for
handleTrain(recommended), addcontinueTrainingwhich usestrain()for batch computation (matching static's behavior)
- @apvd/worker's
initWasm()only callswasm.init_logs(), missingawait wasm.default() - Static correctly calls
await wasmModule.default()first - Fix: add
await (wasm as any).default?.()beforeinit_logs()
- WASM
make_stepreturnsStep<Dual>where coordinates are{ v: number, d: number[] } - @apvd/worker casts directly to
Shape[]— BUG: returns Dual-wrapped shapes - Static correctly uses
extractShape()to unwrap Dual → plain number - Fix: add extraction functions to @apvd/worker, use everywhere
- Static needs a main-thread fallback for Vite dev server (Workers don't work well in dev)
- Keep
createMainThreadClient()in static's TrainingClientContext - Import shared utils (
extractShapes) from@apvd/workerto reduce duplication
| File | Change |
|---|---|
client/src/types.ts |
Add ContinueTrainingResult, update WorkerRequest.type, add continueTraining to TrainingClient |
apvd-wasm/ts/worker.ts |
Fix WASM init, add Dual extraction, add continueTraining, add sparklines |
apvd-wasm/ts/client.ts |
Add continueTraining() method |
apvd-wasm/ts/index.ts |
Export extraction utils |
| File | Change |
|---|---|
src/workers/training.worker.ts |
Replace 750 lines with 1-line re-export |
src/contexts/TrainingClientContext.tsx |
Remove ~600 lines of duplication |
src/hooks/useTrainingClient.ts |
Remove ~120 lines of duplication, import from shared |
src/hooks/useTraining.ts |
DELETE (dead code) |
src/hooks/useCompactedModel.ts |
DELETE (dead code) |
Net reduction: ~1400 lines removed from static
- Build @apvd/worker:
cd apvd-wasm/ts && pnpm build - Build @apvd/client:
cd client && pnpm build - Build WASM:
cd apvd-wasm && wasm-pack build --target web - Test static dev mode:
cd ~/c/rac/apvd/static && pnpm dev→ verify training works - Test static prod build:
cd ~/c/rac/apvd/static && pnpm build→ verify no build errors - Manual test: Load a layout, click play, verify training advances, verify step navigation works