perf: expert speed mode + reliability hardening#3
perf: expert speed mode + reliability hardening#3pAulseperformance wants to merge 12 commits intomainfrom
Conversation
…ed imports - Extract use-hand-synth.ts (292 LOC) from App.tsx - App.tsx: 491 to 298 LOC (under 300 limit) - DevPanel: 715 to 360 LOC via HandTrackingPanel + TuningSliders - QuantumCanvas: import * as THREE to named imports - Add zustand-imperative-sync epilogue workflow
…racks hand position
…versation log - POST /api/forge: streams Llama 4 Scout response as SSE - GET /api/forge/log: retrieve past forge conversations - KV persistence via tee+waitUntil (zero client latency) - TerminalIntake: streaming typewriter AI response with forging state
…ken bot protection Phase 1: Pure CSS starfield renders in <50ms — no dead black screen Phase 2: QuantumCanvas lazy-loaded (1.5MB → async), initial bundle 372KB Phase 3: POST /api/forge requires HMAC-signed rip token (10min TTL, 5 uses) - POST /api/forge/token mints token on rip event - Bots without rip token get 401 - TerminalIntake sends Bearer auth header
…ersation history preserved
|
@copilot please review this PR again.\n\nCommit: 3e60e6c\n\nWhy:\n- Improve runtime speed and stability under load.\n- Harden worker auth/request handling and add regression safeguards.\n\nWhat:\n- Adaptive quality + true performance-mode fast path in runtime canvas.\n- Reduced per-frame CPU/GPU overhead in hot loops and synth update paths.\n- Refactored worker auth/request validation into testable modules.\n- Added CI quality gates (lint/typecheck/test/build). |
Agent-Logs-Url: https://github.com/ZPEVC/zpe-vc/sessions/bdad5089-96ae-4ee9-86d4-2d14578e6ca0 Co-authored-by: pAulseperformance <29057302+pAulseperformance@users.noreply.github.com>
Reviewed the full commit (3e60e6c). Everything looks solid — lint, typecheck, and all 8 tests pass clean. One minor indentation typo was present on the |
There was a problem hiding this comment.
Pull request overview
This PR improves runtime smoothness and hardens reliability by adding an explicit performance-mode fast path + adaptive quality in the Three.js “quantum canvas” runtime, and by introducing a Cloudflare Worker “forge” API with token gating, validation helpers, logging, and CI quality gates.
Changes:
- Added performance-mode behavior and adaptive quality controls to reduce per-frame hot-loop work and GPU load.
- Introduced Cloudflare Worker forge endpoints with request parsing/auth helpers, KV-backed usage/logging, plus Vitest unit tests.
- Added a CI workflow to run lint, typecheck, tests, and build on PRs/pushes.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| wrangler.jsonc | Adds AI binding and KV namespace for forge usage/log storage. |
| vite.config.ts | Adds Rollup manual chunking to improve caching/load performance for large deps. |
| src/worker/forge-request.ts | Adds JSON content-type detection and idea parsing/validation. |
| src/worker/forge-request.test.ts | Unit tests for forge request parsing/validation. |
| src/worker/forge-auth.ts | Implements HMAC-signed bearer tokens with TTL/use limits and bearer parsing. |
| src/worker/forge-auth.test.ts | Unit tests for signing/verifying tokens and expiry/tamper cases. |
| src/worker.ts | Adds forge API routes, token minting, AI streaming, and KV persistence. |
| src/widgets/terminal-intake/ui/TerminalIntake.tsx | Switches intake UX from mailto to streaming forge API + conversation UI. |
| src/widgets/dev-mode-button/DevModeButton.tsx | Removes per-render randomness for particle sizes to stabilize visuals/perf. |
| src/shared/ui/button.tsx | Adjusts exports (Button + ButtonProps) for UI button module. |
| src/features/quantum-canvas/ui/TuningSliders.tsx | Extracts shader tuning UI into a dedicated component. |
| src/features/quantum-canvas/ui/SynthControls.tsx | Throttles FFT band UI updates to reduce rerender pressure. |
| src/features/quantum-canvas/ui/QuantumCanvas.tsx | Adds performanceMode, adaptive DPR/bloom quality tiers, perf sampling, and hot-loop optimizations. |
| src/features/quantum-canvas/ui/PresetControls.tsx | Syncs preset loads/imports into the audio engine store. |
| src/features/quantum-canvas/ui/HandTrackingPanel.tsx | Extracts hand tracking + performance controls UI from DevPanel. |
| src/features/quantum-canvas/ui/DevPanel.tsx | Refactors DevPanel to use extracted sub-panels and cleaner state bridging. |
| src/features/quantum-canvas/lib/use-shader-presets.ts | Makes malformed preset persistence failure handling explicit. |
| src/features/quantum-canvas/lib/use-auto-sim.ts | Refactors sim point generation and timing to be deterministic and less jittery. |
| src/features/quantum-audio/lib/quantizer.ts | Improves typing for scale frequency table initialization. |
| src/features/hand-tracking/ui/use-hand-synth.ts | Extracts hand→audio bridge logic from App into a reusable hook with throttling. |
| src/features/hand-tracking/lib/looper.ts | Simplifies event due logic signature. |
| src/features/hand-tracking/index.ts | Re-exports useHandSynth. |
| src/app/starfield.css | Adds CSS starfield placeholder background to reduce perceived load time. |
| src/app/globals.css | Imports starfield CSS globally. |
| src/App.tsx | Integrates forge token minting, performanceMode into QuantumCanvas, and extracted hand synth hook. |
| package.json | Adds typecheck/test scripts and adds Vitest dependency. |
| package-lock.json | Locks new dependency graph (Vitest and its transitive deps). |
| .github/workflows/ci.yml | Adds CI job running lint/typecheck/test/build on PRs and main pushes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async function saveForgeLog(env: Env, idea: string, stream: ReadableStream): Promise<void> { | ||
| const reader = stream.getReader() | ||
| const decoder = new TextDecoder() | ||
| let fullResponse = '' | ||
|
|
||
| try { | ||
| while (true) { | ||
| const { done, value } = await reader.read() | ||
| if (done) break | ||
| const chunk = decoder.decode(value, { stream: true }) | ||
| for (const line of chunk.split('\n')) { | ||
| if (line.startsWith('data: ')) { | ||
| const data = line.slice(6) | ||
| if (data === '[DONE]') continue | ||
| try { | ||
| const parsed = JSON.parse(data) as { response?: string } | ||
| if (parsed.response) fullResponse += parsed.response | ||
| } catch { /* skip non-JSON lines */ } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
saveForgeLog() parses the streamed SSE by splitting each decoded chunk on '\n' without carrying over a partial line between reads. If a JSON data: line is split across chunks (common with streaming), this will drop/garble payloads and produce incomplete or corrupted fullResponse. Consider keeping a buffer string across reads (like the client does) and only JSON-parse complete lines.
| const serverUses = await getServerTokenUses(env, verification.payload.nonce) | ||
| if (serverUses >= MAX_USES) { | ||
| return new Response(JSON.stringify({ error: 'Forge token usage limit reached' }), { | ||
| status: 401, | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| }) | ||
| } | ||
| await incrementServerTokenUses(env, verification.payload.nonce) | ||
|
|
There was a problem hiding this comment.
Forge token usage tracking in KV is vulnerable to concurrent-request races: multiple requests with the same nonce can all pass the serverUses check before incrementServerTokenUses() writes, allowing more than MAX_USES. If this limit is meant to be enforced, KV alone can’t provide atomic increments; consider a Durable Object (or another atomic counter mechanism) for nonce usage accounting.
| async function getServerTokenUses(env: Env, nonce: string): Promise<number> { | ||
| const value = await env.FORGE_LOG.get(`forge-token:${nonce}`) | ||
| if (!value) return 0 | ||
| const parsed = Number(value) | ||
| return Number.isFinite(parsed) ? parsed : 0 | ||
| } | ||
|
|
||
| async function incrementServerTokenUses(env: Env, nonce: string): Promise<number> { | ||
| const nextUses = (await getServerTokenUses(env, nonce)) + 1 | ||
| await env.FORGE_LOG.put(`forge-token:${nonce}`, String(nextUses)) | ||
| return nextUses |
There was a problem hiding this comment.
KV keys for token uses (forge-token:${nonce}) are written without any TTL/expiration. Since tokens expire after TOKEN_TTL_MS, these counters will accumulate indefinitely and grow KV storage over time. Consider writing these counters with an expiration (e.g., slightly above TOKEN_TTL_MS) or periodically cleaning them up.
| const key = `forge-log:${Date.now()}` | ||
| await env.FORGE_LOG.put(key, JSON.stringify({ | ||
| idea, | ||
| response: fullResponse, | ||
| timestamp: new Date().toISOString(), | ||
| })) |
There was a problem hiding this comment.
Log entries are stored in KV without an expiration and use forge-log:${Date.now()} as the key. Two writes in the same millisecond can collide/overwrite, and logs will grow unbounded over time. Consider adding uniqueness to the key (e.g., timestamp + random UUID) and setting an expiration/retention policy via KV put options.
| // ── API Routes ── | ||
| if (url.pathname === '/api/forge/token' && request.method === 'POST') { | ||
| return mintForgeToken(env) | ||
| } | ||
|
|
||
| if (url.pathname === '/api/forge' && request.method === 'POST') { | ||
| return handleForge(request, env, ctx) | ||
| } |
There was a problem hiding this comment.
The token-minting endpoint (POST /api/forge/token) is unauthenticated and can be called repeatedly to mint unlimited valid tokens. As a result, the bearer token gate doesn’t meaningfully limit abuse of /api/forge unless there’s a separate rate limit or challenge. Consider adding per-IP rate limiting, a proof-of-work/challenge, or restricting minting to same-origin with additional validation.
| return ( | ||
| <Canvas | ||
| gl={{ antialias: false, alpha: false, powerPreference: 'high-performance', preserveDrawingBuffer: true }} | ||
| gl={{ antialias: false, alpha: false, powerPreference: 'high-performance' }} |
There was a problem hiding this comment.
preserveDrawingBuffer: true was removed from the Canvas GL config. The app appears to rely on reading the canvas for screenshots/record thumbnails (ExportControls uses canvas.toBlob() and PresetControls draws the WebGL canvas into an offscreen 2D canvas). Without preserveDrawingBuffer, some browsers can return blank/cleared frames for these capture paths. If captures must remain reliable, consider keeping preserveDrawingBuffer (possibly only when capture UI is active) or rendering to an intermediate target specifically for export.
| gl={{ antialias: false, alpha: false, powerPreference: 'high-performance' }} | |
| gl={{ antialias: false, alpha: false, powerPreference: 'high-performance', preserveDrawingBuffer: true }} |
| const callbacksRef = useRef(callbacks) | ||
| callbacksRef.current = callbacks | ||
| useEffect(() => { | ||
| callbacksRef.current = callbacks | ||
| }, [callbacks]) | ||
|
|
||
| // Refs to avoid tearing down the loop when slider changes | ||
| const simStateRef = useRef({ simMode, simSeparation, simRate, simMouseSpeed, simMouseRadius, simClicksOn, simMouseOn, simActive }) | ||
| simStateRef.current = { simMode, simSeparation, simRate, simMouseSpeed, simMouseRadius, simClicksOn, simMouseOn, simActive } | ||
| useEffect(() => { | ||
| simStateRef.current = { simMode, simSeparation, simRate, simMouseSpeed, simMouseRadius, simClicksOn, simMouseOn, simActive } | ||
| }, [simMode, simSeparation, simRate, simMouseSpeed, simMouseRadius, simClicksOn, simMouseOn, simActive]) |
There was a problem hiding this comment.
Updating callbacksRef.current and simStateRef.current inside useEffect introduces a window where the simulation loop runs with stale callbacks/state until the effect fires (after paint). This can cause dropped/incorrect sim events right after UI changes. Prefer updating these refs during render (synchronously) or using useLayoutEffect if you need to avoid tearing while still keeping the loop stable.
| "typescript": "~5.9.3", | ||
| "typescript-eslint": "^8.56.1", | ||
| "vite": "^8.0.0" | ||
| "vite": "^8.0.0", |
There was a problem hiding this comment.
vitest@3.2.4 (via @vitest/mocker / vite-node) declares a peer dependency on Vite ^5 || ^6 || ^7, but this repo pins vite: ^8.0.0. npm will install, but this peer mismatch can lead to runtime incompatibilities or hard-to-debug failures in npm run test/CI. Consider upgrading Vitest to a version that supports Vite 8, or pinning Vite to a supported major for the test toolchain.
| "vite": "^8.0.0", | |
| "vite": "^7.0.0", |
| "kv_namespaces": [ | ||
| { | ||
| "binding": "FORGE_LOG", | ||
| "id": "cd612b74d74c4e2dbc6ca71d91862629" |
There was a problem hiding this comment.
The new KV namespace config lacks a preview_id. Without it, wrangler dev can end up writing to the production KV namespace (or fail depending on setup), which is risky for the new forge token/log data. Consider adding a preview_id for local/dev environments (and/or defining separate envs).
| "id": "cd612b74d74c4e2dbc6ca71d91862629" | |
| "id": "cd612b74d74c4e2dbc6ca71d91862629", | |
| // TODO: replace with the actual preview KV namespace ID for development | |
| "preview_id": "00000000000000000000000000000000" |
Why
What
Validation