diff --git a/.env b/.env index b532a31..769ebf2 100755 --- a/.env +++ b/.env @@ -1,3 +1 @@ DATABASE_URL=file:/home/z/my-project/db/custom.db -OVE_DIRECTORY_URL=https://s3374dir.openvisengine.com -OVE_DIRECTORY_API_KEY=+7MkRB+hkV0UBhPqM1haTQ0f8JGKqkuXwoBTdTSAouU= diff --git a/.zscripts/dev.pid b/.zscripts/dev.pid index 5a97808..ff0ed70 100755 --- a/.zscripts/dev.pid +++ b/.zscripts/dev.pid @@ -1 +1 @@ -1198 +1048 diff --git a/src/app/api/ove-directory/scripts/[id]/ratings/route.ts b/src/app/api/ove-directory/scripts/[id]/ratings/route.ts old mode 100644 new mode 100755 diff --git a/src/app/api/ove-directory/scripts/[id]/route.ts b/src/app/api/ove-directory/scripts/[id]/route.ts old mode 100644 new mode 100755 diff --git a/src/app/api/ove-directory/scripts/route.ts b/src/app/api/ove-directory/scripts/route.ts old mode 100644 new mode 100755 diff --git a/src/app/api/ove-directory/status/route.ts b/src/app/api/ove-directory/status/route.ts old mode 100644 new mode 100755 diff --git a/src/components/ava/directory-tab.tsx b/src/components/ava/directory-tab.tsx old mode 100644 new mode 100755 diff --git a/src/components/ava/upload-dialog.tsx b/src/components/ava/upload-dialog.tsx old mode 100644 new mode 100755 diff --git a/src/lib/ava/wake-lock.ts b/src/lib/ava/wake-lock.ts old mode 100644 new mode 100755 diff --git a/src/lib/ove-directory.ts b/src/lib/ove-directory.ts old mode 100644 new mode 100755 diff --git a/src/lib/server/ove-directory.ts b/src/lib/server/ove-directory.ts old mode 100644 new mode 100755 diff --git a/tool-results/osc12-1-preset-live.png b/tool-results/osc12-1-preset-live.png old mode 100644 new mode 100755 diff --git a/tool-results/osc12-2-rot-test.png b/tool-results/osc12-2-rot-test.png old mode 100644 new mode 100755 diff --git a/tool-results/osc12-3-final-live.png b/tool-results/osc12-3-final-live.png old mode 100644 new mode 100755 diff --git a/tool-results/osc12-4-mobile.png b/tool-results/osc12-4-mobile.png old mode 100644 new mode 100755 diff --git a/tool-results/read_1793817131261_fb699e6a294f.txt b/tool-results/read_1793817131261_fb699e6a294f.txt old mode 100644 new mode 100755 diff --git a/tool-results/read_1793817160288_8d6de58d6d8d.txt b/tool-results/read_1793817160288_8d6de58d6d8d.txt old mode 100644 new mode 100755 diff --git a/tool-results/read_1793835734103_a615e8778496.txt b/tool-results/read_1793835734103_a615e8778496.txt old mode 100644 new mode 100755 diff --git a/tool-results/read_1793917110778_bfd1ffe533cd.txt b/tool-results/read_1793917110778_bfd1ffe533cd.txt new file mode 100644 index 0000000..582df4c --- /dev/null +++ b/tool-results/read_1793917110778_bfd1ffe533cd.txt @@ -0,0 +1,160 @@ + 2200→- Round-trip EXACT on 207 scripts (90 tools/converted .ava + 6 rust-agent presets + presets.ts inline + 105 DB built-ins): 136,046 → 69,523 chars = 49% shorter overall (best 56%, worst 28%); determinism verified per script. + 2201→- Adversarial "soup" (every reserved symbol, all card suits, chess, zodiac, arrows, circled digits, control pictures, backslashes, CRLF, raw control chars, VS16/ZWJ sequences, emoji incl. ZWJ families, combining marks, surrogate edges): exact round-trip. + 2202→- 3,000-string fuzz over a hostile alphabet: 3,000/3,000 exact. CJK-comment scripts (colliding with the pair-packing block) and literal pair-block content round-trip via the escape path. + 2203→- Decode rejects: truncation (−1/−5/−20 chars), flipped body char (checksum), garbage/empty/malformed inputs; accepts: padded+quoted, bare body, VS16+ZWSP mangled (injected between EVERY char), name with colons/brackets (sanitized), >48-char names (capped). + 2204→ + 2205→BROWSER E2E (agent-browser + VLM, ALL PASS): + 2206→- Script tab shows both buttons; Script⇢Hash opens with `Bass Bloom:[▲…③⑬⑧⑭①⑧⑩⑪]` — 679 chars, "49% shorter than the script", semantic symbols + CJK pairs visible; Copy click → "Copied!" (clipboard API present). + 2207→- Full UI round-trip: hash captured → Hash⇢Script pasted → Decode → panel "Bass Bloom · 56 lines · 1341 characters · Compiles OK — mode: dots" → Load into Editor → editor content BYTE-IDENTICAL to the original (1341/1341 chars, string equality true). + 2208→- Errors: garbage → "does not look like an OVE share string…"; truncated (−15, loses "]") → "looks cut off — it should end with "]" (signature-based message); altered → checksum message. + 2209→- Re-open resets paste state (bug fix verified); Settings tab: no Music services section/heading/log-in buttons, Appearance intact (visible panel text verified). + 2210→- Mobile 375 px: toolbar wraps with both buttons on-screen, no horizontal overflow; both dialogs fit (16–359 px wide, Script⇢Hash 69–743 px in 812 px viewport after the height-cap fix; textarea ≤ 240 px, scrolls internally). 320 px header: scrollWidth 320 = clientWidth (v7.6.1's removal fixed the old ≤360 px overflow — re-measured as promised). + 2211→- VLM (dark, Script⇢Hash): nothing crosses the border, string/symbols/ Copy/stats all present, readable, no defects. VLM (light, Hash⇢Script): title, placeholder "My Script:[▲…]", Cancel/Decode well-formed, contrast good on white. VLM (mobile): fully visible, nothing cut off. + 2212→- Fresh reload: console 0 errors/0 warnings (release-notes drift guard silent — v7.7 entries match); dev.log clean (compile + 200s only). Test-browser localStorage cleared afterwards. + 2213→ + 2214→Stage Summary: + 2215→- v7.7 shipped: scripts are now shareable as single Unicode strings — ~half the length of the script, self-checking, copy/paste-survivable, lossless for ANY text (compiling not required) — and the Settings tab is decluttered while the house account keeps Stream-a-Link working for everyone. The shared dialog height cap protects every dialog app-wide from tall content on short screens. + 2216→ + 2217→--- + 2218→Task ID: 37 + 2219→Agent: main (Z.ai Code) + 2220→Task: v7.10.1 (user report while testing their new "Spectrum Bars" script): a section on the very right of spectrum visuals is inactive and never reacts to the music -- same dead right edge on other spectrum scripts. Explain why, then fix it engine-side so every script benefits. + 2221→ + 2222→DIAGNOSIS (why the right edge is dead): + 2223→- getspec()/sv mapped bar position 0..1 across the WHOLE FFT: bin = 2 + floor(p^1.6 * 4093) at 8192-point FFT, so pos 1.0 = bin 4095 = Nyquist (22.05/24 kHz). pos 0.8 already lands at ~16.8 kHz. + 2224→- Real music carries almost nothing up there, and every lossy source low-passes even lower: the demo collection is 192 kbps MP3 @48 kHz (LAME low-pass ~18.6 kHz), YouTube AAC ~15.5 kHz. Measured on demo-01 (20 s, 8192-FFT): 0.000% of total magnitude above 18.6 kHz; content above -40 dB rel. peak ends at ~13.4 kHz, above -60 dB at ~17.8 kHz. + 2225→- So bar positions above ~0.82 read byte 0 every frame -- the rightmost ~20% of every spectrum visual was permanently frozen at the floor. Not a script bug: every script sampling getspec over 0..1 (all 10 converted getspec presets included) showed the same dead edge, exactly like the Winamp AVS originals. The engine's own flux detector already caps at 16 kHz for the same reason (audio.ts getBands). + 2226→ + 2227→Work Log: + 2228→- src/lib/ava/audio.ts: new SPEC_TOP_HZ = 16000 const (with the full why-comment); getSpectrum() now maps the field from bin 2 (~12 Hz) to the 16 kHz bin instead of Nyquist: hiBin = clamp(ceil(16000/binHz)), bin = 2 + floor(p^1.6 * (hiBin - 2)). Same log-ish curve, every position now lands on frequencies music occupies; right edge = 12-16 kHz "air" band (cymbals/hats/sparkle). Matches the flux cap. + 2229→- rust-agent/src/spectrum.rs: SPEC_TOP_HZ const + spectrum_at() mirrors the new mapping exactly (source parity; not compiled locally, no cargo). + 2230→- help-panel.tsx: sv entry now states the span: "spectrum magnitude 0..1 (≈12 Hz to 16 kHz, log-ish -- the range music actually occupies)". + 2231→- version.ts 7.10.1 + history entry; release-notes.ts 7.10.1 "Spectrum edge unfrozen" (fixed, first-person voice). lint clean; tsc clean apart from the pre-existing base-target share-codec BigInt literals. + 2232→ + 2233→VERIFICATION (three independent measurements): + 2234→- Offline full-track emulation (Blackman window + AnalyserNode dB byte mapping, every 21 ms of demo-01): under the NEW mapping every one of 48 bars is >15/255 in 76-100% of frames and >60/255 in 68-99% -- nothing is structurally dead. Under the old mapping positions >0.82 read literal zero. + 2235→- Fresh in-page chain (eval: fetch demo-01 -> decodeAudioData -> own AnalyserNode at t=150 s): top positions dance (pos 1.0 = 16 kHz fluctuates 4..118/255 frame to frame). + 2236→- Live E2E with the USER'S OWN "Spectrum Bars" script (found in the test browser's localStorage from the previous session, 28 bars x 4 pts, running on Demo Track 2 at 60 FPS): per-bar pixel measurements across 6 frames show the rightmost bars (f 0.74-1.0 = 9.9-16 kHz) swinging 4%..76% with the music -- under the old mapping those bars sampled 16.8-24 kHz and sat pinned at 0 (the script's own below(lvl,0.004)?0 snap would hold them perfectly flat). Also verified with a purpose-built 48-bar "Edge Check" script earlier in the session. + 2237→- Anomaly chased and closed: one 5-sample window showed bars 36-48 at floor while bass danced -- turned out to be the demo track's outro (offline analysis: t=187-191 s has a legitimately dead 10-16 kHz band while lows keep going); the demo ended right after (SRC: IDLE, place advanced), matching the timeline. Not a mapping issue. + 2238→- What's New dialog: v7.10.1 "Spectrum edge unfrozen" first with CURRENT badge + FIXED tag; drift guard silent after a clean reload (one transient guard warning was hot-reload event ordering + stale console history); the one hydration error was agent-browser's own data-__ab-ci instrumentation, absent on a clean reload. Console otherwise clean; dev.log clean. + 2239→- Test-browser localStorage cleared afterwards (convention); scratch PCM deleted. + 2240→ + 2241→Stage Summary: + 2242→- v7.10.1 shipped: the frozen right edge of every spectrum visual is unfrozen. The bar field now spans ~12 Hz to 16 kHz (the range music actually occupies) instead of stretching to Nyquist, so the right bars land on the 10-16 kHz air band and dance with the hats/cymbals. The user's own Spectrum Bars script (whose 0.78+0.45*f treble tilt now has something real to boost) verified live: rightmost bars swing 4..76%. + 2243→ + 2244→--- + 2245→Task ID: 38 + 2246→Agent: main (Z.ai Code) + 2247→Task: v7.11 (user request, three parts). RESTORED RETROACTIVELY — the entry was lost in a session cutoff (same as Task 35 once was); scope reconstructed from the version.ts 7.11 history and the tool-results/v711-* evidence screenshots (v711-01 through v711-22, all PASS). (1) Mobile wake lock: while any audio source is live the site holds a Screen Wake Lock so phone/tablet screens stay on; released the moment the engine goes idle so normal inactivity dimming returns. (2) A respectful Demo Track button: no longer force-engages the Sequence checkbox when the visitor has loaded a preset (tree double-click / Load / copied preset) or brought their own script material into the editor — Demo just plays the track; the Zai-Magic showcase only starts for a visit that never picked or typed anything. (3) Script tab one-click Save: a valid script shows the Save button with no save target needed; auto-names from the script's name header (a hash import of "Spectrum Bars:[▼…]" saves as "Spectrum Bars"), "Empty Name" when nameless, " (1)"/" (2)"… suffixes on conflicts — and when the name had to be invented, a "Give This Preset a Name" dialog opens to rename the just-saved preset in one step (saved FIRST, renamed second, so nothing is ever lost). + 2248→ + 2249→Work Log (reconstructed): + 2250→- src/lib/ava/wake-lock.ts (NEW): Screen Wake Lock sentinel manager — acquire on source-live, release on idle, visibilitychange re-acquire (browsers silently drop the sentinel on hide), silent degradation where unsupported. + 2251→- audio-source.ts / control-panel / page.tsx: per-visit manualChoice flag + boot-script snapshot decide whether the Demo showcase may engage; ensureDefaultPreset gained the same guard (mic/file/link never clobber a custom draft either). Demo teardown paths (ended/stop/switch) all respect it. + 2252→- script-tab.tsx: Save button visible on any valid script with no target; auto-naming ladder (script name header -> hash import label -> "Empty Name" -> conflict suffixes); "Give This Preset a Name" dialog after any invented save. Hash⇢Script imports clear the stale save target and pass the decoded label through as the fallback name. + 2253→- version.ts 7.11 + history; release-notes.ts 7.11 entry. + 2254→ + 2255→E2E (evidence: tool-results/v711-01..22, ALL PASS): + 2256→- Fresh boot (no selection, no editor material): Demo engages the sequence showcase as before — v711-19/20. + 2257→- Preset loaded first (double-click, v711-03; embedded, v711-04): Demo plays the track, Sequence stays UNCHECKED (v711-06), the running script is untouched — a custom script can be debugged against the demo track without fear of replacement (v711-05 custom material case). + 2258→- Hash⇢Script -> Save: lands under "user created" as "Spectrum Bars" from the share-string label (v711-09/10/11); nameless script saves as "Empty Name" then the rename dialog appears (v711-12/15); duplicate conflicts get " (1)"/" (2)" suffixes (v711-16/17) and the rename updates the saved preset (v711-13). + 2259→- Default boot script + reload states (v711-18); mobile 375 px (v711-21) and desktop (v711-22) clean; wake lock verified by code path (headless browsers do not expose navigator.wakeLock — degrade-silent branch exercised). + 2260→ + 2261→Stage Summary: + 2262→- v7.11 shipped: the screen stays on while music plays, the Demo button stopped hijacking the preset selection, and one click saves any valid script with a smart name. This restored entry closes the gap in the build diary. + 2263→ + 2264→--- + 2265→Task ID: 39 + 2266→Agent: main (Z.ai Code) + 2267→Task: v7.12 (user request): add the classic-AVS background-movement family to the scripting — the background shifts up/down/left/right, spins clockwise/counter-clockwise, draws in and blows out, with the speed accelerating to the beat and hard hits flipping the spin direction while the fade to black stays slow (so colors blend) — then ship a permanent Zai-Magic preset "osc-rotations": a stationary centered oscilloscope whose left/right points color-shift together and whose center points hold their own hue, over a background rotating cw/ccw to the music with temporary beat acceleration. + 2268→ + 2269→Work Log: + 2270→- src/lib/ava/engine.ts — NEW background feedback transform (the AVS movement family): + 2271→ * Script controls, read from env AFTER [frame]/[beat] run so this frame's values apply this frame: bgrot (radians/frame, + = CLOCKWISE on screen — canvas y is down so ctx.rotate(+) spins cw), bgx/bgy (per-frame drift, the -1..1 screen convention, y is UP matching script x/y), bgzoom (per-frame scale: <1 draw-in, >1 blow-out, 1 = neutral). Values persist in env like any variable — set from [init] (persists forever), [frame] (every frame) or [beat] (on-beat jumps); neutral readings skip the pass entirely (zero cost for every preset that doesn't move). + 2272→ * applyBackground(): snapshot the live canvas into an offscreen buffer (globalCompositeOperation 'copy'), wipe the canvas black (the transformed snapshot must REPLACE the old content, not double-expose), then draw the snapshot back through the frame's transform (translate w/2+bgx*w/2, h/2-bgy*h/2; rotate; scale). Uncovered regions (rotated corners, slid-off edges) read black and the persistence fade blends the trails — exactly how the classic AVS plugins made "speed accelerates to the beat, a hard hit flips the spin, fade stays slow" work: the rate is just a script variable driven by a beatage envelope, and a [beat] section flips a dir variable on hard hits (bass vs bass_att). + 2273→ * Guards: bgNum() falls back to neutral for missing/NaN values (a NaN in a canvas transform matrix would black the screen with no error — every later draw becomes a silent no-op); per-frame clamps rot ±0.6 rad, drift ±0.25, zoom 0.5..2. Buffer recreated automatically on resize; null until first use (zero cost otherwise). Gated on this.script so a stale env after clearScript can never spin a blank canvas. + 2274→- src/lib/ava/embedded-presets.ts — eleventh Zai-Magic preset "osc-rotations" (user-named, lowercase so it sorts last in the tree): persist 0.965 (slow fade — colors blend), [frame] drives bgrot = dir * (0.0032 + punch * (0.014 + vol_att * 0.012)) with punch = exp(-beatage*3.2) (temporary beat acceleration that relaxes with the kick ring), bgzoom = 1 - 0.0009 - punch*0.0011 (a whisper of draw-in so trails spiral inward instead of ringing), hue drifts dt*0.012 + beat*0.02; [beat] flips dir on hard hits only (bass > 1.25 * bass_att — soft beats leave the spin alone); [point] draws the stationary centered scope x = i*2-1, y = v*(0.3+vol_att*0.8) with mirror-symmetric color h = hue + |i-0.5|*2 * 0.34 (points equidistant left/right of center share one hue, the center holds its own). EMBEDDED_SEED_VERSION 7.10 -> 7.12 (route re-seeds the subtree; fingerprint self-heal would have caught it too). "ten presets" comments updated to eleven (both the file-top and the Zai-Magic section header). + 2275→- src/components/ava/help-panel.tsx — bgrot / bgx/bgy / bgzoom rows in the variables table + three example formulas (beat-accelerated spin, hard-hit direction flip in [beat], draw-in). + 2276→- src/lib/version.ts 7.12 + history; src/lib/release-notes.ts 7.12 entry (2x added, first-person voice). Share codec deliberately untouched: its dictionary is a frozen compatibility contract (adding entries needs a new scheme marker) — bg* identifiers ride the pair packing like any custom variable. + 2277→ + 2278→HEADLESS VALIDATION (/home/z/tmp-validate/bg-transform/validate-osc.ts, ALL PASS): + 2279→- osc-rotations compiles; all 101 embedded presets still compile (regression guard). + 2280→- Compiled-program behavior: quiet frame bgrot 0.00397 rad/frame cw + bgzoom 0.99906; hard beat bgrot 0.0256 (6.5x) AND dir flips to -1; soft beat no flip; point pass x spans ±1 with |y| symmetric, mirrored positions share hue exactly (0.7906 both) while center is distinct (0.6206). + 2281→ + 2282→BROWSER E2E (agent-browser + pixel measurement + VLM, ALL PASS): + 2283→- Fresh boot: title "OVE -- Open Visualization Engine (v7.12)"; tree shows "Zai-Magic -- 11"; /api/presets re-seeded on the version gate and serves osc-rotations (106 presets total; sorts last in Zai-Magic as designed). + 2284→- Preset live on the demo collection (manual load first, then Demo Track — v7.11's respectful-Demo still holds: Random/Sequence stayed UNCHECKED with a preset loaded): footer "SCRIPT: osc-rotations · Demo Track 1/2 · FPS 59-60 · PTS 512 · BPM 132.3/138.8 locked". Mid-band (scope zone) mean 133/255; outer zones lit only by rotation-carried trails. + 2285→- bgrot isolation (line mathematically confined to the middle 35% band, so outer-zone content can ONLY be rotation-carried): outer zones hold a steady mean ~14/255 vs EXACTLY 0.00 in the no-bg control — rotation puts content where the line cannot reach. + 2286→- bgx sign: +0.012 drifts the bright cloud right (mean x 0.518); -0.012 mirrors it exactly (0.480) — the sign convention verified by symmetry. + 2287→- bgy sign: +0.02 pulls the bright cloud UP (mean y-from-top 0.368 vs 0.5 neutral). + 2288→- bgzoom: at 1.05/frame the outer zones went from dead 0.00 to ~38/255 (blow-out pushes the confined line's trails outward); at 1.003/frame with persist 0.92 trails die before traveling far (consistent with the fade math — equilibrium analysis, not a defect). + 2289→- What's New dialog: 7.12 "Background movement (AVS-style) + osc-rotations" first with CURRENT badge, drift guard silent. Help panel: bg* rows + examples all present. + 2290→- VLM on the live screenshot: horizontal oscillating waveform line at vertical center; large soft colorful trail masses around it; hue variation green at the outer left/right edges, yellow mid, red/pink at the center — the mirror-symmetric color design visibly realized; no defects; "60 FPS . 512 PTS" overlay normal. + 2291→- Console clean (0 errors/0 warnings); dev.log clean (59 successful requests, no compile errors). Footer: sticks to the viewport bottom on short pages (1280x800 Beat tab: docH 800, footer bottom 800) and pushes to the document end on long pages (375 px Presets tab: docH 1469, footer at doc end, no overlap); 375 px scrollWidth 375 = clientWidth (no horizontal overflow). Test-browser localStorage cleared afterwards. + 2292→ + 2293→Stage Summary: + 2294→- v7.12 shipped: scripts can move the whole picture — bgrot spins, bgx/bgy slide, bgzoom draws in / blows out — with the speed riding the music exactly the way the classic AVS plugins did it (beatage envelopes drive the rate, [beat] flips the spin on hard hits, persist keeps the fade slow so colors blend). The eleventh Zai-Magic preset "osc-rotations" demonstrates the full recipe: a stationary centered oscilloscope with mirror-symmetric color (left/right shift together, center holds its own hue) over a beat-accelerated, hard-hit-flipping rotating background. + 2295→ + 2296→--- + 2297→Task ID: 40 + 2298→Agent: main (Z.ai Code) + 2299→Task: v7.13 (user request): merge the two parallel development lines. The user supplied the v7.12 build ("updated script editor variables and the osc-rotations preset") as an encrypted zip on Google Drive (password: z.ai) and asked to compare it with this tree's "Upload to OVE-Directory" version (v7.11) and merge the improvements into one build. + 2300→ + 2301→MERGE ARCHAEOLOGY: + 2302→- The Drive zip (openvisengine.zip, 374 MB, AES-encrypted, compression type 99 — Python zipfile can't read it; pyzipper could) extracted to /home/z/drive-712/v712-full: APP_VERSION 7.12, worklog Tasks 37-39 (v7.10.1 spectrum fix, v7.11 wake lock/respectful-Demo/one-click-Save, v7.12 bg movement + osc-rotations). The partial ove-src12/ extraction from the earlier session verified identical (114/115 sha256; the one mismatch was a Drive-fetch artifact named "globals.css CSS"). + 2303→- Divergence map via the zip's own .git: BOTH repos share commit d59d398 (tree 953bae5... — IDENTICAL hash on both sides, a true common ancestor at v7.10). After it: this tree shipped v7.11 = the OVE-Directory (directory-tab.tsx, upload-dialog.tsx, /api/ove-directory proxy, lib/ove-directory.ts); the zip tree shipped 7.10.1 + 7.11-wake-lock + 7.12. The ONLY overlapping files were script-tab.tsx, version.ts, release-notes.ts (+ demo-track binaries, identical on both sides). + 2304→ + 2305→Work Log: + 2306→- Git 3-way merge: zip repo fetched as remote v712, `git merge 1ea335a` — everything auto-merged (engine.ts applyBackground + bgrot/bgx/bgy/bgzoom, audio.ts SPEC_TOP_HZ 16 kHz cap, rust-agent/spectrum.rs mirror, embedded-presets.ts osc-rotations + EMBEDDED_SEED_VERSION 7.12, wake-lock.ts NEW, audio-source.ts + page.tsx manualChoice/respectful-Demo, presets-tab.tsx, share-dialogs.tsx, store.ts markManualChoice, help-panel.tsx bg* rows + sv span) except three conflicts. + 2307→- script-tab.tsx (hand-merged): both sides' state blocks kept side by side — ours' uploadOpen/canUpload (Upload to OVE-Directory, gated on ✔ Compiled OK + no runtime error) + theirs' pendingName/rename* states (one-click Save + "Give This Preset a Name"); toolbar now carries the dual Save (target save / one-click new) AND the Upload button; Hash⇢Script import sets pendingName + clears editTarget + markManualChoice; UploadToDirectoryDialog mounted. Verified byte-lossless: diff vs the v7.12 original removes ONLY comment lines (theirs' code 100% intact; ours' upload code added). + 2308→- version.ts + release-notes.ts (hand-merged into ONE timeline): NEW 7.13 entry ("one build, every feature") on top, then 7.12 (bg movement + osc-rotations), 7.11 (the OVE-Directory), 7.10.2 (the parallel line's wake-lock/respectful-Demo/one-click-Save release — RENUMBERED from its original 7.11 so the list reads monotonically; noted in the 7.13 text), 7.10.1 (spectrum edge), 7.10 and below untouched. APP_VERSION = '7.13'. Drift guard green. + 2309→- engine.ts / audio.ts / embedded-presets.ts / wake-lock.ts / help-panel.tsx / audio-source.ts verified BYTE-IDENTICAL to the validated v7.12 originals (cmp) — the parallel line's E2E-proven behavior carries over by construction. + 2310→ + 2311→ENVIRONMENT RECOVERY (sandbox quirks, not code): + 2312→- The merge swapped db/custom.db underneath the running server → Prisma "readonly database" (dead inode); fixed by restart. + 2313→- Turbopack's persistent cache panicked twice ("Failed to restore task data — corrupted database") after file replacements/kills; fixed with rm -rf .next + clean start. + 2314→- Directly-spawned background servers were reaped when the Bash session ended; the stable path is the system's own .zscripts/dev.sh (disowned bun run dev). Server now up: / 200, /api/presets 200, /api/ove-directory/* 200. + 2315→- EMBEDDED_SEED_VERSION gate fired on first hit (7.10 -> 7.12): DB re-seeded to 106 presets incl. osc-rotations (verified in SQLite: seed=7.12, count=106, osc-rotations=1). + 2316→ + 2317→E2E (agent-browser + pixel measurement + VLM, ALL PASS): + 2318→- Fresh boot: title "OVE -- Open Visualization Engine (v7.13)"; tree root/embedded 106 = Amp Picks 66 + Dynamics 9 + Envision 15 + Synth-C 5 + Zai-Magic 11; osc-rotations sorts last in Zai-Magic as designed. + 2319→- osc-rotations live on Demo Track (dblclick-load via the treeitem's inner button): footer "SRC: DEMO · Demo Track · FPS 59-60 · PTS 512 · BPM 139.9 locked · SCRIPT: osc-rotations". Two frames 1.2 s apart: 20% of sampled pixels changed (animating). Zone means: mid-band 69.7/255 (the scope) vs corners 3.3-13.8/255 — outer-zone content can ONLY be rotation-carried (the line is confined to the middle), i.e. applyBackground is rotating the picture in the merged build. + 2320→- VLM on the clean capture: (1) bright horizontal oscillating waveform at the vertical center ✓; (2) colorful smeared trail masses at corners/edges "consistent with a rotating background layer smearing trails around the stationary center waveform" ✓; (3) mirror-symmetric hues — yellow/gold at BOTH extremes, warm pink/magenta in the middle ✓; (4) no UI defects ✓. + 2321→- Script tab: Apply / Save / Script⇢Hash / Hash⇢Script / Upload to OVE-Directory / New / Help ALL present; with a compiling script both Save and Upload enabled (upload title carries the publish/fix-then-apply guidance); Upload dialog opens with the share-string description. + 2322→- One-click Save flow: New (template) -> strip the name header -> Save -> saved as "Empty Name" -> "Give This Preset a Name" dialog opened automatically -> renamed to "Merge Test v713" -> "Preset renamed" toast; test preset removed from localStorage afterwards. + 2323→- Directory tab: live listing via the proxy (1 script, sort controls, "Spectrum Bars · LINES · Average: 4.5 · 2 votes", Get button). + 2324→- Help panel: bgrot / bgx / bgy / bgzoom rows + example formulas all present. + 2325→- What's New dialog: 7.13 "One build, every feature" FIRST with CURRENT badge; 7.12, 7.10.2 in the merged timeline; drift guard silent. + 2326→- Responsive: 375x812 no horizontal overflow (scrollWidth 375 = clientWidth), footer pushed to document end (docH 1651); 1280x800 footer sticks to viewport bottom (800 = 800). + 2327→- Console: 0 errors, 0 warnings (wake lock degrades silently in headless — no navigator.wakeLock); dev.log 0 errors. Test-browser localStorage cleaned afterwards. + 2328→ + 2329→Stage Summary: + 2330→- v7.13 shipped: the parallel line is merged — the spectrum 16 kHz cap, the screen wake lock, the respectful Demo button, the one-click Save with auto-naming + rename dialog, the AVS-style background movement family (bgrot/bgx/bgy/bgzoom) and the eleventh Zai-Magic preset "osc-rotations" all run in the same build as the community OVE-Directory, with one clean version timeline (the parallel wake-lock release folded in as 7.10.2). Only three files needed hand-merging; every engine-side change is byte-identical to its validated original. + 2331→ + 2332→--- + 2333→Task ID: 41 + 2334→Agent: main (Z.ai Code) + 2335→Task: v7.13.1 (user report): in Zai-Magic "Beat Matrix" the rightmost vertical line of dots sat offset +1 upwards -- its bottom dot did not line up with the other columns, and its top dot spilled over onto the next section to the right. Diagnose, explain, fix. + 2336→ + 2337→DIAGNOSIS (why the right column was short and a phantom dot spilled): + 2338→- The engine's point position i spans 0..1 INCLUSIVE (classic AVS Superscope convention; engine.ts: i = k/(n-1)). Beat Matrix's grid math assumed exclusive i = k/n: col = floor(i * cols) sends the LAST point (i = 1 exactly) to col 16 -- one column past the 16-column wall (x = 0.986/aspect vs the wall edge 0.87/aspect) at row 0 (top), reading getspec(1.0); and column 15 was left with only 9 dots (rows 0-8, no bottom: its lowest dot sat at y = -0.62 while every other column reaches y = -0.81). Verified headlessly before the fix: col 15 = 9 dots rows 0-8, col 16 = 1 dot, bottom-row y spread col 14 vs 15 = 0.19 script units. + 2339→- Sweep of all other floor(i*M) uses in the library (62 occurrences): every other one is benign -- angular presets close their loop (bar = bars lands exactly on bar 0's angle: seg*tau/segs with seg = segs = 2pi = 0), Aurora Veil's phantom lands off-screen (x = 1.19 > 1), the megabuf particle presets (Bass Bloom, Supernova) draw their phantom slot at alpha 0 (uninitialized megabuf reads 0), Strobe Lattice/Tunnel Vision/Prism Chandelier hide one endpoint dot in rotating/mirrored chaos, and the converted Winamp classics rendered identically under original AVS (which also uses inclusive i) -- their authors saw and accepted exactly this behavior. Beat Matrix was the only hand-authored ALIGNED grid where the defect is obvious, so it was the only one that needed the fix. + 2340→ + 2341→Work Log: + 2342→- embedded-presets.ts Beat Matrix [point]: the grid mapping now goes through CELL CENTERS -- cell = i * (cols * rows - 1) + 0.5, col = floor(cell / rows), row = floor(cell - col * rows). Because i = k/(n-1) over n = cols*rows points, cell = k + 0.5 exactly (up to 1-ulp dust), so every floor() sits half a cell away from an integer boundary: the endpoint can never spill and float dust can never shuffle a dot into a neighboring cell. getspec/x/y/hue all read col/row as before (col 0..15, row 0..9; the last point now lands at col 15 row 9, the author's original intent under i = k/n). A 6-line comment in the script documents the why. + 2343→- EMBEDDED_SEED_VERSION 7.12 -> 7.13.1 (library re-seed replaces the DB's Beat Matrix; verified in SQLite: seed = 7.13.1, 106 presets, fixed content present, old mapping gone). + 2344→- version.ts 7.13.1 + history entry; release-notes.ts 7.13.1 "Beat Matrix grid fixed" (fixed, first-person voice). + 2345→ + 2346→HEADLESS VALIDATION (/home/z/tmp-validate/beatmatrix/validate.mts, ALL PASS — REAL parser/compiler, not a re-implementation): + 2347→- Regression guard: all 101 embedded presets still compile. + 2348→- The fixed Beat Matrix [point] program executed over all 160 points with the engine's exact i = k/(n-1): 160/160 cells occupied, ZERO duplicates, max col 15, max row 9, bottom-right cell (15,9) present, all 16 columns carry their full 10 rows, 16 distinct x symmetric about 0, 10 distinct y rows aligned. + 2349→ + 2350→BROWSER E2E (agent-browser + 8-frame max-brightness composite + VLM, ALL PASS): + 2351→- Fresh load: title "OVE -- Open Visualization Engine (v7.13.1)"; /api/presets re-seeded on the version gate; Beat Matrix loads (PTS 160 = 16x10) and plays on the demo track (FPS 57-60, BPM 133.5 locked). + 2352→- Pixel lattice analysis of an 8-frame composite (captures the treble moments when the high-band columns light): exactly 16 dot columns detected, even 38-39 px gaps; the BOTTOM dot of every one of the 16 columns sits at the SAME pixel row (y = 619, spread 0 px) -- the row-9 position that only exists under the fix (the old code's col-15 lowest dot sat ~80 px higher). + 2353→- Phantom-dot check: the old spill position (x ~722, top row) shows ZERO bright pixels across the composite (x 710-750 all 0); the only brightness right of the wall is column 15's own glow decaying monotonically to nothing by x = 710 (175 -> 45 -> 0 bright-pixel counts), i.e. additive-blend glow, not a dot. The fullscreen-overlay icon (x >= 757) is outside the lattice zone. + 2354→- VLM on the composite: "16 columns"; bottom row fully lit across all 16 columns at the same height (clean straight bottom edge); no stray dot right of the rightmost column; no alignment defects. + 2355→- What's New dialog: 7.13.1 "Beat Matrix grid fixed" first with CURRENT badge; drift guard silent (0 console errors / 0 warnings across the session); dev.log clean (200s only). Test-browser localStorage cleared afterwards. + 2356→ + 2357→Stage Summary: + 2358→- v7.13.1 shipped: Beat Matrix's wall is whole -- every column carries its full 10 dots, the bottom edge is straight across all 16 columns, and the phantom dot that spilled past the right edge is gone. The fix lives in the preset's grid math (cell-center mapping, immune to the inclusive-endpoint and float dust alike); the engine's AVS-correct i convention is untouched, and the library re-seed delivers the fixed preset to every visitor. + 2359→ \ No newline at end of file diff --git a/tool-results/read_1793917130414_511a722bbd43.txt b/tool-results/read_1793917130414_511a722bbd43.txt new file mode 100644 index 0000000..fe4708a --- /dev/null +++ b/tool-results/read_1793917130414_511a722bbd43.txt @@ -0,0 +1,435 @@ + 1→// OVE — app identity + version stamp. + 2→// + 3→// Single source of truth for the product name and version shown in the UI + 4→// (header, footer, document title). Bump APP_VERSION whenever we ship a + 5→// large change so the running build can always be identified at a glance — + 6→// useful both for the z.ai Version History and for naming local backups + 7→// (v6.0 = rename to Open Visualization Engine + version indicator). + 8→// + 9→// STANDING RULE (since v7.6): every APP_VERSION bump MUST come with a + 10→// matching entry at the top of RELEASE_NOTES in src/lib/release-notes.ts — + 11→// that list powers the header's "What's New!" dialog. A dev-mode guard + 12→// warns in the console when the two drift apart. + 13→// + 14→// History: + 15→// 7.13.1 — Beat Matrix endpoint fix (user report): the rightmost column + 16→// of dots sat one row short -- its bottom dot missing -- while a + 17→// phantom dot spilled one column past the wall's right edge at + 18→// the top. Root cause: the engine's point position i spans 0..1 + 19→// INCLUSIVE (classic AVS Superscope convention, engine.ts: i = + 20→// k/(n-1)), but Beat Matrix's grid math assumed exclusive i = k/n: + 21→// floor(i*cols) turned the last point into col 16 (one past the + 22→// 16-column wall) at row 0, and column 15 was left with nine + 23→// dots (rows 0-8, no bottom). Fix: the script now maps through + 24→// cell centers -- cell = i*(cols*rows-1)+0.5, col = + 25→// floor(cell/rows), row = floor(cell-col*rows) -- which puts + 26→// every floor() half a cell away from an integer boundary, so + 27→// the endpoint can never spill and float dust can never shuffle + 28→// a dot. Full 16x10 bijection verified headlessly (all 160 + 29→// points in 160 distinct cells, col<=15, row<=9, bottom-right + 30→// cell present). Sweep of the other 100 presets: every other + 31→// floor(i*M) use is benign -- angular presets close their loop + 32→// (bar=bars lands exactly on bar 0's angle), Aurora Veil's + 33→// phantom lands off-screen (x=1.19), the megabuf particle + 34→// presets draw their phantom slot at alpha 0, and the converted + 35→// Winamp classics rendered identically under original AVS + 36→// (which also uses inclusive i). EMBEDDED_SEED_VERSION 7.12 -> + 37→// 7.13.1 re-seeds the library so every visitor gets the fixed + 38→// Beat Matrix. + 39→// 7.13 — one build, every feature: the parallel development lines are + 40→// merged. This tree now carries BOTH the community OVE-Directory + 41→// (v7.11 here) AND the parallel line's additions — the spectrum + 42→// 16 kHz cap (its 7.10.1), the screen wake lock + respectful + 43→// Demo button + one-click Save (its 7.11, folded into this + 44→// history as 7.10.2 to keep one clean timeline), and the + 45→// AVS-style background movement family (bgrot / bgx / bgy / + 46→// bgzoom) with the eleventh Zai-Magic preset "osc-rotations" + 47→// (its 7.12). Git three-way merge against the shared v7.10 + 48→// ancestor (identical tree hashes verified on both sides); the + 49→// only hand-merged surface was the Script tab toolbar, which + 50→// now carries the one-click Save and "Upload to OVE-Directory" + 51→// side by side, and the two changelogs (here + release-notes). + 52→// 7.12 — background movement + osc-rotations. Scripts can now move the + 53→// whole framebuffer every frame, the way the classic Winamp AVS + 54→// plugins did: bgrot (radians/frame, + clockwise on screen), + 55→// bgx / bgy (per-frame drift in the -1..1 screen convention, y + 56→// up), bgzoom (< 1 draw-in, > 1 blow-out) -- read after [frame]/ + 57→// [beat] so this frame's values apply this frame. The engine + 58→// snapshots the canvas into an offscreen buffer, wipes, and + 59→// draws the snapshot back through the transform, so the + 60→// persistence fade blends the moving trails: "speed accelerates + 61→// to the beat, a hard hit flips the spin, fade to black stays + 62→// slow" is pure script (a beatage envelope drives the rate; a + 63→// [beat] section flips a dir variable on hard hits via bass vs + 64→// bass_att). Neutral readings (0/0/0/1) skip the pass entirely + 65→// (zero cost for every preset that doesn't move); non-finite + 66→// values fall back to neutral (a NaN in a canvas transform + 67→// matrix would black the screen with no error); per-frame + 68→// clamps: rot ±0.6 rad, drift ±0.25, zoom 0.5..2. New 11th + 69→// Zai-Magic preset "osc-rotations" (user-requested): a + 70→// stationary centered oscilloscope (time-domain v) whose color + 71→// is mirror-symmetric -- points equidistant left/right of + 72→// center shift together, the center points hold their own hue + 73→// -- over a background rotating cw/ccw to the music that + 74→// temporarily accelerates on the beat; hard hits + 75→// (bass > 1.25 × bass_att) flip the spin; a whisper of draw-in + 76→// (bgzoom ~0.999) spirals the trails inward; persist 0.965 + 77→// keeps the fade slow so colors blend. Help panel: bg* variable + 78→// rows + three new example formulas. EMBEDDED_SEED_VERSION + 79→// 7.10 -> 7.12 (library re-seed adds the preset; the share + 80→// codec's dictionary stays frozen per its compatibility + 81→// contract -- bg* identifiers ride the pair packing like any + 82→// custom variable). Headless validation of the preset's + 83→// compiled programs: quiet 0.004 rad/frame, hard beat 0.026 + 84→// (6.5×) + direction flip, soft beat no flip, mirrored points + 85→// share hue / center distinct + 86→// 7.11 — the community OVE-Directory. A sixth tab (Directory) lists every + 87→// script published to the community directory — a separate VPS at + 88→// s3374dir.openvisengine.com, reached ONLY through this server's + 89→// backend proxy (/api/ove-directory/*), which holds the API key in + 90→// env and re-validates every upload (the share string must decode + 91→// AND compile). Publishing: the Script tab gains "Upload to + 92→// OVE-Directory" (enabled only while the editor shows ✔ Compiled OK + 93→// with no runtime error); the script travels as its Script⇢Hash + 94→// string, so the directory stores a fraction of the source. The + 95→// listing carries each entry's name, type and date, a 1–5 star + 96→// widget (the voter id is an HttpOnly cookie minted by the proxy; + 97→// one vote per script per visitor, enforced upstream), the live + 98→// "Average: #.#" to the right of the stars, and sorting by Name / + 99→// Type / Date / Rating (done upstream, both directions). "Get" + 100→// fetches the full record, decodes the hash back into the exact + 101→// script, files it in this browser's preset tree under + 102→// root/user created/OVE-Directory (content-deduped, names numbered + 103→// "(1) (2) (3)…" on collision) and offers "Open in editor". + 104→// Duplicate uploads resolve as success (409 DUPLICATE_HASH carries + 105→// the existing row); duplicate votes show the stored aggregates. + 106→// 7.10.2 — wake lock, a respectful Demo button, one-click save. While any + 107→// audio source is live the site holds a Screen Wake Lock so phone + 108→// and tablet screens stay on (released the moment the engine goes + 109→// idle so the normal inactivity dimming returns; browsers silently + 110→// drop the sentinel on hide, so a visibilitychange watcher + 111→// re-acquires it on return while music is still going; + 112→// unsupported browsers degrade silently). The Demo Track button no + 113→// longer force-engages the Sequence checkbox: a visitor who loaded + 114→// a preset (tree double-click / Load / Copy to my presets / created + 115→// one), brought their own script material into the editor (typed, + 116→// pasted, Hash⇢Script, file), saved their own default startup + 117→// script, or runs their own Random/Sequence mix keeps their + 118→// selection -- Demo just plays the track (the showcase's tree + 119→// re-scope, 20 s interval and retire-on-end all skip too; a new + 120→// per-visit manualChoice flag + a boot-script snapshot decide, and + 121→// ensureDefaultPreset gained the same guard so mic/file/link never + 122→// clobber a custom draft either; the showcase now only starts for + 123→// a visit that never picked or typed anything). Script tab: a valid + 124→// script shows the Save button with NO save target needed -- one + 125→// click creates a preset under "user created", auto-named from the + 126→// script's name: header (a hash import of "Spectrum Bars:[▼…]" + 127→// saves as "Spectrum Bars"), "Empty Name" when nameless, " (1)"/ + 128→// " (2)"… suffixes on conflicts, and whenever the name had to be + 129→// invented a "Give This Preset a Name" dialog opens to rename the + 130→// just-saved preset in one step (the preset is always saved FIRST, + 131→// renamed second, so nothing is ever lost to a naming problem). + 132→// Hash⇢Script imports clear the stale save target (the editor now + 133→// holds foreign content) and pass the decoded label through as the + 134→// save-name fallback when the script has no name: header + 135→// 7.10.1 — the frozen right edge of spectrum visuals. getspec()/sv mapped + 136→// the bar field across the whole FFT (bin 2 ... Nyquist, ~12 Hz to + 137→// 24 kHz), but music carries almost nothing above ~16 kHz and every + 138→// lossy source low-passes even lower (192 kbps MP3 at ~18.6 kHz, + 139→// YouTube AAC at ~15.5 kHz; measured across the demo collection: + 140→// 0.000% of total magnitude above 18.6 kHz), so the rightmost ~20% + 141→// of every spectrum visual read a permanent zero -- bars that never + 142→// moved. getSpectrum() now tops the field out at 16 kHz + 143→// (SPEC_TOP_HZ, matching the spectral-flux cap in getBands()), so + 144→// the right edge lands on the 12-16 kHz "air" band where cymbals, + 145→// hats and synth sparkle live. rust-agent's spectrum_at() mirrors + 146→// the change, and the help panel's sv entry now states the span. + 147→// 7.10 — ten demo tracks + first-person changelog + declutter. The demo + 148→// source is now a COLLECTION: ten mastered tracks in + 149→// public/demo-tracks/ (demo-01.mp3 … demo-10.mp3, filename order + 150→// 1→10, replacing the single Neural Mecha Pulse file). Each Demo + 151→// click plays the visitor's PLACE in the collection once through; + 152→// the place advances when a pass truly ends — natural finish or + 153→// the Stop button ('ended'/'stop' teardown reasons, a new + 154→// onDemoEnded signature) — and wraps 10→1; switching to another + 155→// source keeps the place. The place persists per visitor in + 156→// localStorage (ove.demoTrack.next), so returning picks up where + 157→// they left off. The engine caches one decoded buffer at a time, + 158→// keyed by track index (~50–60 MB PCM each — all ten would be half + 159→// a gigabyte). The header chip + footer SRC label show the current + 160→// track's name (Demo Track N). RELEASE_NOTES rewritten in the + 161→// operator's first-person voice (no more third-person marketing + 162→// copy or addressing the visitor), and every em dash in the + 163→// interface replaced with a plain double minus ( -- ) — including + 164→// the embedded preset library's descriptions and script comments + 165→// (EMBEDDED_SEED_VERSION 7.01 → 7.10 re-seed). Declutter: the + 166→// landing menu's source list line, the presets panel's two + 167→// read-only paragraphs, the Random/Sequence hint line, the empty + 168→// user-folder note reworded, the Settings theme/highlight/Native + 169→// paragraphs, the link dialog's privacy footnote and the footer's + 170→// engine-ok dot are all gone — compile errors still toast, so the + 171→// always-green badge was noise + 172→// 7.9 — footer credit + What's New polish. The footer's blank middle now + 173→// carries the maker's signature: "© {year} · Site Created & + 174→// Deployed by Sum'ting White" (year generated from the clock, + 175→// hydration-guarded) with a "View my portfolio at zcreations.dev" + 176→// link that opens zcreations.dev in a new tab — centered in the + 177→// blank area from xl (mx-auto between the stats and the version + 178→// stamp), dropping to its own centered row on narrower screens so + 179→// nothing ever crowds. The What's New dialog got a typographic + 180→// tidy-up: a hairline divider above every release box + 181→// (border-zinc-800 — a ramp step, so it matches every base theme + 182→// through the globals.css remaps), and each change row became an + 183→// invisible two-column grid — the kind tag top-right justified + 184→// against the column boundary, the description top-left with word + 185→// wrap — so all descriptions start on the same pixel column + 186→// 7.8 — share strings 2.0: ~72% shorter than the script (was ~49%). The + 187→// base-62 idea, cranked to 11,172… 32,164: after the symbol + 188→// dictionary (which grew ~170 data-mined entries — every function + 189→// WITH its open paren, every engine variable, the AVS idioms + 190→// "hue = hue + dt * " and "t = t + dt * ", " * 0.", ") * ", + 191→// blank-line+section skeletons, "linewidth: " / "blend: additive" + 192→// headers, ~70 number literals, and the library's common + 193→// variable names incl. chroma) the whole body is read as ONE BIG + 194→// NUMBER and rewritten in base 32,164 — one digit per character + 195→// from the CJK + Hangul blocks, ~15 bits a character vs base-62's + 196→// 5.95 (so "1400" costs ~0.85 of a character). The decoder gets + 197→// the body's alphabet back from a ~32-character bitmap header + 198→// instead of ~80 literal symbols. Short scripts where the header + 199→// wouldn't pay keep the v7.7 symbol form (encoder picks whichever + 200→// is shorter); ▲ strings from v7.7 still decode; still lossless + 201→// for ANY text, still copy-safe, still self-checking. Corpus + 202→// measure: median share string is 27% of the script's length + 203→// (best 22%), e.g. Bass Bloom 1341 → 326 characters + 204→// 7.7 — script sharing + settings declutter. Script⇢Hash / Hash⇢Script: + 205→// two buttons in the Script tab turn the editor's script into ONE + 206→// short shareable Unicode string ("Bass Bloom:[▲…①①①①①①①①]") and + 207→// paste one back — the script returns exactly as written (lossless + 208→// for ANY text, compiling NOT required, so WIP scripts can be + 209→// shared for debugging). The string is built from built-in symbol + 210→// references (♤ = line return, ♡ = beats, ♠ = beatage, ♦ = space, + 211→// ♩♪♫♬ = the four sections, one symbol per function/variable, plus + 212→// a pair-packing layer that folds leftover identifier/number text + 213→// two chars per CJK code point) — ~50% shorter than the script on + 214→// real presets. Copy-safe by construction (no raw whitespace or + 215→// control chars; platform-injected variation selectors / zero- + 216→// widths stripped on paste) and self-checking: 8 check digits (an + 217→// FNV-1a digest rendered as ①–⑯) reject strings that were cut off + 218→// by a character limit or altered in transit, instead of decoding + 219→// into garbage. Also: the Music Services log in / "log out of all" + 220→// section in Settings is parked (MUSIC_SERVICES_UI flag) — the + 221→// built-in house account already powers Stream-a-Link for + 222→// everyone; the section returns reworked in a later update + 223→// 7.6.1 — header declutter: the Set Beat button is gone from the header + 224→// (tap-tempo lives in the Beat tab, and the Space shortcut works + 225→// anywhere — both unchanged). The beat indicator dot stays. + 226→// 7.6 — "What's New!" dialog: a Sparkles button in the header (left of + 227→// the theme switch) opens the visitor-facing changelog — every + 228→// release from v4.0 on, newest first, each with one-line Added / + 229→// Improved / Fixed / Removed notes (src/lib/release-notes.ts, + 230→// color-coded tags, the running version badged "current", + 231→// scrollable with the thin scrollbar). A small emerald dot on the + 232→// button marks updates the visitor hasn't seen yet — per visitor + 233→// in localStorage, cleared on open (mount-guarded, no hydration + 234→// mismatch). Standing rule added: version bumps ship with their + 235→// release note; a dev-mode guard warns when they drift + 236→// 7.5.1 — Link dialog width fix: text no longer escapes the dialog box. + 237→// Root cause: Radix dialogs lay their children in an implicit CSS + 238→// grid whose single column sizes to the widest child's min-content; + 239→// the RECENT LINKS rows carry truncate spans (white-space: nowrap), + 240→// and Chromium measures a nowrap flex item's full text width for + 241→// that measurement — so a long saved title (e.g. "Bobby Foxx — This + 242→// Is Why We Can't Have Nice Things (Official Music Video)") blew + 243→// the column ~40 px past the 448 px dialog, and EVERY child (title, + 244→// description, input + Load, rows, footer) laid out beyond the + 245→// right border. Fix: the shared Dialog/AlertDialog content now pins + 246→// the column to minmax(0,1fr) — capped at the available width, so + 247→// no nowrap content can ever stretch a dialog again (covers every + 248→// dialog app-wide) — the Link dialog widened to max-w-lg for + 249→// comfier wrapping, and min-w-0 + break-words added on the + 250→// recents/playlist containers and error text as belt-and-braces + 251→// 7.5 — yt-dlp compatibility: single tracks resolve by DOWNLOAD + CONVERT + 252→// instead of proxying the extractor's stream URL. The old stream + 253→// URLs were IP-locked (googlevideo bakes in the resolver's IP), + 254→// expired within hours, and arrived as webm/opus — a container + 255→// Safari & co. refuse ("The media resource … was not suitable"). + 256→// The server now runs the operator's pipeline per track: + 257→// yt-dlp -f bestaudio/best -x --audio-format mp3 + 258→// --audio-quality 0 -o "/%(title)s.%(ext)s" URL + 259→// — audio-only download, universal MP3 at VBR-0 (~245 kbps), the + 260→// video's real title preserved for the Playing: label. The + 261→// finished file streams same-origin with full Range support from + 262→// a per-track workspace dir (30-min sliding TTL + orphan sweeper); + 263→// /api/audio/stream gained a file-serving mode. Hardening around + 264→// it: shared failure classifier for both yt-dlp passes (metadata + + 265→// download), 180 s download budget, 300 MB cap, bot-wall/stale- + 266→// extractor answers unchanged, ffmpeg-missing degrades to the old + 267→// proxy path (logged once), queue look-ahead lead 15 s → 60 s so + 268→// playlist transitions don't stall behind conversions + 269→// 7.4 — Sequence mode: a second mix checkbox next to Random. Ticked, it + 270→// cycles the scope folder's presets IN ORDER (the tree's exact + 271→// top-to-bottom order) instead of shuffling — and when it moves + 272→// past the last preset it wraps back to the first, so the folder + 273→// loops forever. Random and Sequence are mutually exclusive + 274→// (ticking either one unticks the other; both share the same + 275→// delay and folder scope), Random now never loads the same preset + 276→// twice in a row, and Sequence holds its breath through silence + 277→// exactly like Random does. The Demo showcase now runs SEQUENCE — + 278→// the one play-through walks every Zai-Magic preset in order + 279→// (20 s each) rather than repeating random picks, and when the + 280→// demo stops, whichever mode it checked is unchecked again + 281→// 7.3 — demo-flow refinements: the Demo Track is a single pass — it plays + 282→// "Neural Mecha Pulse" once through and stops (a demo, not a radio + 283→// station). However it ends (natural finish, Stop, or switching to + 284→// another source) the showcase unwinds: the randomizer the Demo + 285→// flow force-checked is unchecked again, and the visitor lands + 286→// back on the "Select an audio source" overlay. Preset-change + 287→// popups are gone ("Preset loaded" / "Random preset" / "Default + 288→// preset running") — the footer's SCRIPT: label already echoes + 289→// every change, so the toasts were pure intrusion; only compile + 290→// errors still toast. Club-mode randomizer now respects silence: + 291→// when no music is playing it never re-shuffles the selected + 292→// preset, even with the checkbox on — it waits for the next track + 293→// 7.2.1 — Supernova (Zai-Magic) preset fix: the particle kill condition + 294→// (|px|+|py| > 2.4) was physically unreachable — drag caps a + 295→// particle's total travel at vel/1.6 ≈ 1.0, so nothing ever + 296→// crossed 1.4, nothing ever died, and since respawning requires a + 297→// dead particle, the per-beat "budget = n" detonation could never + 298→// fire after the initial one — the preset exploded once on load, + 299→// then faded to permanent black. Now every beat force-clears the + 300→// whole 620-particle field in [beat] (guaranteed full re-detonation + 301→// on the very same frame), fully-cooled particles die by fade so + 302→// long beat gaps leave a gentle ember drizzle instead of black, + 303→// and each blast re-randomizes its geometry (no two explosions + 304→// alike). Embedded library re-seeded (seed marker 7.01) + 305→// 7.2 — new-visitor showcase flow. Defaults for first-time visitors: + 306→// the Black + Purple Outline theme with the Blue highlight + 307→// (previously royal purple + yellow), and Zai-Magic "Bass Bloom" + 308→// as the startup preset (previously the first Synth-C classic). + 309→// The idle overlay's Demo Track button now carries an animated + 310→// reflective shimmer (skewed light band sweeping left→right every + 311→// 3.2 s, reduced-motion safe) to draw the click — and that one + 312→// click starts the full showcase: the demo track plays while the + 313→// preset tree selects + expands Zai-Magic, randomize switches on + 314→// scoped to that folder with a 20-second change interval. Music + 315→// started with NO preset active (own draft running / selection + 316→// cleared) auto-loads Bass Bloom. Preset changes — manual load, + 317→// the random mix, the Demo flow — no longer hard-cut: the engine + 318→// snapshots the outgoing frame and blur-dissolves it into the new + 319→// preset over 700 ms (progressive blur + easeOutCubic fade + a + 320→// slight scale-up so the softening edges never gap; plain + 321→// crossfade where ctx.filter is unsupported) + 322→// 7.1 — real demo track + a beat detector that survives real music. + 323→// The Demo button now plays "Neural Mecha Pulse" (the operator's + 324→// mastered industrial-EDM banger, public/demo-track.mp3, loops + 325→// gaplessly) instead of the synthetic techno pattern — a real + 326→// recording is the honest test: deep sub for the bass bands, + 327→// driving mids, crisp highs, and a kick buried in sustained + 328→// sub-bass. That last part exposed the 6.x detector as fundamentally + 329→// broken on mastered music: a LEVEL threshold can never see the + 330→// kick through the sub (peak-to-mean caps at ~1.2× → sporadic + 331→// fires, phantom 120-BPM locks from the minInterval floor). + 332→// v7.1 rewrites detection the way real beat trackers work + 333→// (aubio/librosa-style): a full-band spectral-flux ONSET envelope + 334→// → autocorrelation over 300–1000 ms lags with a log-BPM prior → + 335→// comb-filter phase with grid hysteresis → beats fired on an + 336→// absolute grid kept glued by a PLL pull. Headlessly validated + 337→// against the actual track PCM (AnalyserNode chain replicated + 338→// frame-for-frame): locks the true ~133 BPM (the song drifts + 339→// 130.7→133.1 — the grid TRACKS it) in 1.9 s, 92% beat-gap + 340→// regularity, confidence 0.99 through the body; techno/hip-hop + 341→// patterns lock exactly; silence yields zero beats. Known limit: + 342→// sparse kick-vs-snare backbeats (dnb) may lock half-tempo — + 343→// stable, and two taps of Set Beat correct it. Visitor-stored + 344→// beat configs migrate (floorLevel changed units, level → flux). + 345→// The demo BPM slider is gone (a real track's tempo is detected, + 346→// not dialed in) — replaced by a track-name chip in the header + 347→// 7.00 — Zai-Magic: ten hand-authored presets in root/embedded/Zai-Magic + 348→// built around BEAT-SYNCED COLOR — the color wheel turns on the + 349→// kick, palettes swap per beat / per 4-beat bar, megabuf particles + 350→// remember the hue of the beat that spawned them + new script + 351→// tools: hsvr/hsvg/hsvb (HSV→RGB channels), smoothstep and the + 352→// beatage kick-envelope variable — all documented in the help + 353→// panel. (Numbered 7.00 rather than 6.10 — a new preset family + 354→// plus new script-language features is a major release; 6.9.3 was + 355→// the last patch of the 6.x line.) Beat engine fixes underneath so + 356→// the Demo track actually + 357→// locks tempo (was sporadic): demo synth remixed for detection + 358→// (hot kick owning the 20–100 Hz band, off-beat bassline voiced + 359→// C3+ with a sidechain pump — chronological envelope events!), + 360→// and the detector's default threshold 1.4 → 1.2 (the 170 ms FFT + 361→// window caps a clean kick's peak-to-mean at ~1.5×, so 1.4 fired + 362→// only sporadically and the BPM never locked) + 363→// 6.9.3 — canonical domain fix: metadataBase/og:url/og:image pointed at + 364→// openvisualengine.com (a DEAD domain baked in by 6.9.1) while the + 365→// real site is openvisengine.com — Facebook's "corrupted image" + 366→// error was its crawler fetching the image from a host that serves + 367→// nothing; all share URLs now use the correct short domain + 368→// 6.9.2 — share-image fix: og:image re-encoded as BASELINE JPEG (the + 369→// 6.9.1 progressive encoding rendered fine in every browser but + 370→// Facebook's Sharing Debugger rejected it as "corrupted"), swapped + 371→// in the title-card artwork (gradient wordmark over three + 372→// visualizations) and added a ?v=2 cache-bust so crawlers fetch it + 373→// 6.9.1 — social share preview: Open Graph + Twitter Card metadata with + 374→// a 1200×630 screenshot of the app (public/og-image.jpg) — sharing + 375→// openvisualengine.com on Facebook/X/WhatsApp/Discord now shows the + 376→// big image card instead of a bare link + 377→// 6.9 — house account: anonymous visitors play YouTube links through + 378→// the operator's shared disposable-account cookie (server-side + 379→// fallback under secrets/, never exposed) — YouTube bot walls stop + 380→// applying to guests; visitor's own login always wins. Engine fix + 381→// underneath: Deno runtime shipped in bin/ (YouTube requires a JS + 382→// runtime for signature/n-challenge solving on authenticated + 383→// sessions — without it, logged-in extractions return no formats) + 384→// 6.8.2 — login friction cut to ~4 clicks: the exported cookies.txt / + 385→// Cookie-Editor JSON file can be dragged straight onto the + 386→// login box (or picked via “Import the exported file…”) — no + 387→// opening the file, no copy/paste; “Log out” / sign-out + 388→// revocation note added (the official Google OAuth flow can't + 389→// power the site: Google's APIs never hand out stream URLs and + 390→// restricted-scope verification would reject an audio player) + 391→// 6.8.1 — cookie login made foolproof: the login dialog recognizes raw + 392→// Cookie headers, cookies.txt exports AND Cookie-Editor JSON, + 393→// validates the paste LIVE through one shared parser (a single + 394→// cookie's value — like a bare LOGIN_INFO string — gets an honest + 395→// "this will not log you in" warning), and the how-to steps lead + 396→// with the one-click extension export for Chrome AND Firefox + 397→// 6.8 — self-healing audio engine: when YouTube changes their mechanics + 398→// the server detects the stale extractor, updates yt-dlp in the + 399→// background (verified GitHub release download, atomic swap) and the + 400→// player retries seamlessly behind an "Updating in Background" + 401→// notice; bot walls answer "Google login required…" with an Open + 402→// Settings action, and unfixable failures get the honest + 403→// "A back-end problem has occurred. Please try again later." + 404→// 6.7 — lazy playlist queue: a playlist link becomes a queue of URLs that + 405→// streams ONE song at a time (each track is resolved by yt-dlp only + 406→// right before it plays — next-track look-ahead at ≤15 s to go), + 407→// queue bar with skip/jump/replay + server-side caps (max 2 parallel + 408→// extractions); music-service framework: Spotify + Apple Music are + 409→// registered providers whose playback ships in a later update + 410→// (logins already save, links answer with an honest notice) + 411→// 6.6 — music service logins (Settings tab): YouTube / YouTube Music, + 412→// SoundCloud, Spotify, Apple Music cookie login, encrypted on the + 413→// visitor's computer; Link button gains playlist picking + uses the + 414→// login to bypass bot walls + 415→// 6.5 — Settings tab (replaces the parked Native tab): theme picker with + 416→// base chrome (Royal Purple / Matte Black / Black + Purple Outline / + 417→// Light) × selectable highlight color (Purple, Yellow, Blue, Green, + 418→// Red, Orange), all per-visitor; simple OVE logo as the site favicon + 419→// 6.4 — beat detection suspends when no music is playing/loaded (no ghost + 420→// beats after Stop, BPM resets) + dark theme restyle: royal purple + 421→// chrome with light-yellow highlights + 422→// 6.3 — light/dark theme tick switch in the header (white theme via .light + 423→// palette remap; per-visitor, persisted by next-themes) + 424→// 6.2 — security hardening: read-only embedded library (server refuses all + 425→// writes) + per-visitor "user created" presets stored in the browser + 426→// 6.1 — preset library quality pass: every embedded stand-in is now a UNIQUE + 427→// generated visual (16 families × seeded parameters), approx badge + 428→// 6.0 — renamed to "Open Visualization Engine" + footer version stamp + 429→// 5.0 — folder-tree Presets page (Task 9–11 state, restored in Task 12) + 430→// 4.0 — link audio source (yt-dlp resolve + stream proxy) + 431→ + 432→export const APP_NAME = 'Open Visualization Engine' + 433→export const APP_SHORT = 'OVE' + 434→export const APP_VERSION = '7.13.1' + 435→ \ No newline at end of file diff --git a/tool-results/v711-01-fresh-home.png b/tool-results/v711-01-fresh-home.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-02-fresh-demo.png b/tool-results/v711-02-fresh-demo.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-03-preset-loaded.png b/tool-results/v711-03-preset-loaded.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-04-demo-with-manual.png b/tool-results/v711-04-demo-with-manual.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-05-demo-custom-material.png b/tool-results/v711-05-demo-custom-material.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-06-seq-unchecked.png b/tool-results/v711-06-seq-unchecked.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-07-state-check.png b/tool-results/v711-07-state-check.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-08-whats-new.png b/tool-results/v711-08-whats-new.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-09-decoded.png b/tool-results/v711-09-decoded.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-10-imported.png b/tool-results/v711-10-imported.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-11-saved-named.png b/tool-results/v711-11-saved-named.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-12-empty-name-dialog.png b/tool-results/v711-12-empty-name-dialog.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-13-renamed.png b/tool-results/v711-13-renamed.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-14-rename-conflict.png b/tool-results/v711-14-rename-conflict.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-15-empty-name-1.png b/tool-results/v711-15-empty-name-1.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-16-suffix-conflict.png b/tool-results/v711-16-suffix-conflict.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-17-named-dup.png b/tool-results/v711-17-named-dup.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-18-default-boot.png b/tool-results/v711-18-default-boot.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-19-default-demo.png b/tool-results/v711-19-default-demo.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-20-final-fresh.png b/tool-results/v711-20-final-fresh.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-21-mobile.png b/tool-results/v711-21-mobile.png old mode 100644 new mode 100755 diff --git a/tool-results/v711-22-desktop.png b/tool-results/v711-22-desktop.png old mode 100644 new mode 100755