feat(web): rebuild streaming demo as a verified download + rename demos to concepts - #886
Conversation
The reset effect re-anchored `tamperByte` to the file's midpoint on every change of the `FileAsset` object, and auto-edit replaces that object every 500 ms — so the slider snapped back to center within half a second of the user releasing it. Clamp to the new byte length instead of re-centering on object identity. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`StreamingBaoVerify` reset its playback state on every `file`-identity change, and `baoFile` (its input) updated every 4th auto-edit tick — so playback and the tamper dropdown got killed mid-use roughly every 2s. Same bug class as the tamper-slider snap-back. Replace it with `StreamingVerifiedDownload`: pressing Start snapshots the current file once (chunks, bao root, outboard), then streams it back as a sequence of bao slices, verifying each against the root as it lands. Verified bytes assemble into a buffer that paints the default PPM's canvas progressively, top row to bottom, so the image visibly fills in only from bytes that passed verification. A "Corrupt the connection" toggle flips a byte in every freshly-fetched slice; the verifier rejects it (visible red × on the chunk strip), then the retry arrives clean and painting resumes. Because the section now snapshots at Start instead of tracking the live file, no effect is keyed on `file` identity, and the recurring `bao_encode` pass (the demo's heaviest wasm call) no longer runs on a timer — it runs once, on click. This removes the `baoFile` / `baoTickRef` / `BAO_THROTTLE_TICKS` throttle machinery from `StreamingDemo` entirely. Measured (Node experiment against the built wasm pkg): | Input | chunks | outboard | proof/slice | bao_slice | bao_verify_slice | |-------------------|--------|-----------------------|---------------|------------|-------------------| | default ~768 KiB | 9 | 49,160 B (6.25%) | 1.9-13.9 KiB | ~0.1 ms | ~0.15 ms | | 16 MiB random | 197 | 1,048,520 B (6.25%) | 2.2-18.3 KiB | ~0.3 ms | ~0.1 ms | | 128 MiB (cap) | 1,576 | 8,388,552 B (6.25%) | 2.4-9.9 KiB | 3-11 ms | ~0.2 ms | | 19 B file | 1 | 8 B | 8 B | ~0 | ~0 | At the 128 MiB cap, the one-time Start cost is ~320 ms sync (`chunk_boundaries` 189 ms + `bao_encode` 133 ms) — acceptable in a click handler. No new tests: jsdom lacks canvas, so the parent `StreamingDemo` already can't mount under vitest; existing suites stay green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
mkit-web | 2026817 | Commit Preview URL Branch Preview URL |
Jul 17 2026, 05:39 PM |
Code quality reviewOverall this is a solid change — the snapshot-at-Start design deletes the
No structural regressions otherwise: the corrupt/retry flow reads clearly, the counters' arithmetic checks out ( |
…hunk mapping Extracts the pure byte/format helpers into apps/web/src/lib/ppm.ts, dedupes the five copies of the chunk-mapping loop behind a stripChunks helper, and replaces the DOWNLOAD_IDLE shared constant with a freshDownloadState() factory. Addresses the code-quality review findings on #886. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ers<> The overridesRef type in streaming-demo.tsx leaned on Parameters<typeof generateDefaultPpm>[1] to avoid exporting the type — indirection where a one-line type export is the direct contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Review findings addressed in 21970c5 and a040d87:
All four checks pass locally (fmt / lint / typecheck / test, 214/214). |
Erica's direction: the old chunker/blob/delta sections and the auto-edit loop are gone — the progressive verified download is now the entire streaming demo. This also fixes a measured perf stall: the auto-edit loop plus the old sections saturated the main thread with ~1.7s long tasks in dev, starving the stream timer down to ~3.4s/chunk; with them removed the designed ~600ms cadence is restored. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…download Corruption was invisible by design: rejected bytes never reached the verified image, so the toggle just filled a button. Add an unverified pane next to the verified one that paints whatever arrives, first attempt wins, so tampered chunks land and stay while the verified pane rejects, stalls, and re-fetches clean. The corrupt toggle now restarts an idle stream so the effect is immediate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Panes now sit side by side (w-40 pins caption wrap), canvases actually clear on restart (clearRect before the translucent placeholder fill), and corrupted spans render as solid black stripes — XOR noise was invisible against the noise-grid default file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, CTA idle state, drop uploads Implements Erica's live-page annotation feedback on the verified-download demo: collapses the raw/verified comparison to one verified image, turns the corrupt control into an accessible switch placed above the buttons, and makes the idle state a lone Start CTA. Removes duplicated/explanatory copy and upload support (drag-and-drop, file input, size cap, and the now-dead FileAsset.source field and FilePreview blob/img fallback) since the demo only ever streams its generated PPM. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pill was a bare role='switch' button whose only child was aria-hidden — no accessible name, and clicking the visible text did nothing. Track, thumb, and label now live inside the button. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The old "retry arrives clean" rule made corruption consequence-free: every rejected chunk auto-healed on its second attempt, so the image always completed and the chunk strip just flickered red. Now every attempt is tampered while the toggle is on — the stream pins at the current chunk, waste climbs, and the image visibly stops filling until the connection is fixed. Deletes the retryPending/isRetry mode and the per-tick batching that only existed for the removed 128 MiB uploads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rebuilds the streaming tab around a single idea: a progressive verified download — the generated grid file streams in chunk by chunk, each chunk arriving as a Bao slice that is verified against the root before a byte of it is shown.
The experience
Also in this PR
/demos→/concepts(nav label, slug, SEO). All six legacy demo routes 301 to/concepts#…, plus a new/demos→/conceptsredirect; tests cover all seven.lib/ppm.ts;streaming-demo.tsxis 461 lines (was 924 before the PR) with the upload-era generality (per-tick batching, non-PPM fallbacks) removed.Measured numbers (Node, against the built wasm)
🤖 Generated with Claude Code