SOURCE / PINNED RELEASE
Made of little things.
Funclet
- Release
- 0b497cfc2f66…
- Author-recorded commit
- 1e531b24f490…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6b7a37cac1d
Archive hash verified: 71d97a89ed8c40c2…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
# Funclet verification — 2026-10-23
The Three.js visual redesign, taller receiver, camera movement and HTTP station fallback are implemented
in the existing soyLI project. The user's revised scope explicitly
keeps Wavefunc favourites read-only. The release media and capture procedure are
recorded in `funclet-promotion.md`; publication delivery is tracked by soyLI.
## Automated checks
| Check | Result |
| --- | --- |
| `pnpm type-check` | Pass |
| `pnpm build` | Pass; one self-contained 576,319-byte `dist/index.html` |
| `pnpm test:guidance` | 6 passed |
| `pnpm test` | 10 passed: station/list formats, stream eligibility, HTTP fallback validation, MCP payload validation, partial reads, batching, canonical media IDs, stale session cleanup |
| `pnpm test:conformance` | 5 passed, 0 failed, 5 skipped |
| `node tests/ui-smoke.mjs` | Pass: 3D interaction/motion/recovery/fallback checks, fixture scenarios and 14 frame/theme combinations |
| `node tests/host-smoke.mjs <printed soyli URL>` | Pass with live Wavefunc services |
| `node tests/external-host-smoke.mjs <printed soyli URL>` | Pass: real IDM Ambient HTTP record, host cancel/open, destination station and seven frame sizes |
| `soyli check` | Checked, `space-playback-6`, Chromium 153.0.8010.12 |
| Boundary scan and `git diff --check` | Clean |
Final checked HTML SHA-256:
`827e224bd54a82743c6f9f0724f58daa0356a6be8b03c2861ca53f1a4e0a1c36`.
The upstream conformance harness skipped three signed-manifest checks (no signed
publication supplied), wire envelopes (its fixture emitted none), and lifecycle
(not measured by that harness). These are not independently verified by its pass.
The hosted tests separately exercised actual OUTBOX, MEDIA, CVM, CONFIG and LINK traffic.
## Real soyLI host
Started with `soyli dev` and used its printed loopback URL.
The iframe loaded with the runtime-injected domains and no page exceptions.
Station search for Radio Paradise returned actual matching stations. Search through
both click and Enter works within `sandbox="allow-scripts"`; the app does not rely
on native form submission, which is blocked in that sandbox.
Omarchy Radio played through a canonical shell-owned session. Verified play, pause,
resume and volume 35%. Approved the host's read-only Wavefunc CVM connection;
`extract_stream_metadata` returned real artist/title values, including
“Party!” by Keith Thomas during the final run. CVM artist search
returned Nina Simone and other catalogue matches. The host settings panel displayed
Station artwork and Now playing refresh. Guest favourites explained how to connect
an account without blocking listening.
The app was exercised with touch emulation and measured iframe dimensions:
200×160, 320×560, 900×600, 1440×900, 390×844, 360×640 and 844×390, each with light and
dark browser theme settings. The manager's iframe width/height were overridden
for these tests, including `min-height: 0` for the true 160px case. App CSS was not
modified by the test. No horizontal document overflow; app-owned paper/ink colors
remained stable. Tiny frames showed the resize notice and active-player control.
The portrait, regular, tiny and live cover screenshots were visually inspected.
`preview-landscape.png` is a real 1200×750 frame capture from the final hosted build,
selected in `napplet.json` alongside the silent 960×600, 10-second `preview-live.webm`.
`preview-portrait.png` shows actual 390×844 touch layout. The cover and portrait were
visually inspected; the clip decoded fully, was reviewed throughout and played in
Listing. Detailed evidence remains ignored under `.napplet-space/testing/` and
`.napplet-space/promotion/`. The owned preview is stopped after verification; run
`soyli dev` to reopen it.
## 3D scene and graphics checks
The real hosted frame initializes WebGL2 and displays locally generated Three.js
geometry: bevelled receiver, instanced speaker grille, extruded `[WF]` lettering,
rotary dial, play key, orbit ring, lighting and cast shadows. The screen's custom
fragment shader draws a moving signal trace, grid and scanlines. This is a playback
indicator, not audio analysis. The cube rotates slowly while idle or paused and
faster during playback. The camera drifts gently and eases toward the mouse position;
it holds steady during a mesh-control gesture. The taller case separates the display,
controls and labels. Transparent, lit label textures sit flush on the face without
rectangular sticker backgrounds.
Built-artifact browser tests tap the real mesh play key, drag the real volume dial
and verify the resulting host commands/state. Pixel comparisons establish motion
while playing and paused, and unchanged frames in reduced motion, including when
the mouse moves. Tests also
exercise station-info switching, deliberate WebGL context loss and restoration,
and a fresh device with WebGL unavailable; HTML playback keeps working in both
failure cases. No shader compilation or page exceptions were reported.
Pixel density is capped at 1.75; the grille uses one instanced draw. Continuous
animation stops when hidden, reduced-motion, undersized or covered by station details.
Geometry, textures, materials, input handlers and animation frames have explicit
teardown. This is not a physical-device GPU performance benchmark.
The artifact is larger because it now includes the Three.js renderer. Vite emits
its advisory 500 kB chunk warning; the required single-file artifact is preserved.
The final HTML contains no external script/style imports or forbidden network/
browser-persistence references. Three.js matches the source Wavefunc's 0.177.0
version and is pinned along with its types. No Blender server was exposed in this
session; all geometry and textures are procedural and require no external assets.
## HTTP station fallback
The real IDM Ambient record advertises only `http://213.141.131.10:8000/idmambient`.
HTTP-only stations are labelled before selection. Selecting one reveals an explanation,
an explicit Open in Wavefunc action and the original selectable stream URL beside the
row and in station details. Selection itself does not navigate or create a MEDIA session.
The current soyLI runtime accepts HTTPS only for both MEDIA and LINK. Its LINK handler
was inspected directly; raw HTTP cannot be opened through that domain. The supported
fallback opens Wavefunc's existing HTTPS station route using the event ID, without
rewriting the stream URL. The live test cancelled the host confirmation and checked
the visible fallback, retried, approved the link and verified IDM Ambient on the actual
destination page. The URL remains available to copy into another player.
Fixture tests cover missing LINK, denial, exceptions, mixed HTTP/HTTPS stations,
credential rejection, primary-stream ordering and delayed handoffs. Current playback
continues on failure; a successful handoff pauses only the session that was current
when the link was requested, preserving any newer station. Six usable frame sizes
keep the fallback reachable inside the scrollable directory; the 200×160 frame shows
the resize notice. All seven avoid horizontal overflow. Desktop and narrow captures
were visually inspected.
## Isolated fixture coverage
The UI harness runs the built HTML in an `allow-scripts` iframe with explicit test
fixtures. It verifies read-only favourite list loading, exact referenced station
resolution, clearing lists on account changes, stale search rejection, search click
and keyboard input, error/partial results, touch playback, now-playing updates,
denied metadata without repeated prompts, and missing IDENTITY/CVM/RESOURCE/CONFIG/LINK/
THEME fallbacks. Fixture artwork is not used as the listing screenshot.
## Remaining limits
- The user's public list and exact references were checked through the deployed
host; both saved station records were absent there and in direct Wavefunc relay
probes. Connected-account transitions remain fixture-tested. See the incident
report for the remaining Wavefunc data follow-up.
- No physical iOS/Android device or audible speaker output was verified. Browser
playback state and stream progress were verified; touch coverage is emulated.
- Track/album CVM response parsers share the validated path; live artist search
was exercised, but live track and album searches were not separately checked.
- Host settings open with the correct schema; persistence across host reloads was
not separately verified.
- Station availability, codec compatibility, relay uptime and metadata quality
depend on third-party services. Unsupported streams remain visible with an
explanation; Funclet does not loosen the sandbox to play them.
- There are no list writes, account sign-in implementation, downloads, zaps,
stream transcoding, HLS support or application-owned networking.
## Production incident regression — 23 October 2026
See [the incident and host improvement report](funclet-live-issues.md).
- `pnpm verify`: six guidance checks, sixteen domain/service/player tests, type
check and single-file build passed.
- `pnpm test:conformance`: five passed, five skipped (signed manifest, wire and
lifecycle evidence not provided to the reference harness).
- `pnpm test:ui`: partial search errors retain usable results; missing saved
records have a distinct explanation. Existing animation, playback, optional
domain and seven-size/two-theme checks remain covered.
- Hosted smoke: station search, playback, CVM metadata/artist search, settings,
touch and both themes passed.
- Candidate services through the deployed host: 48 named stations, 19 IDM
matches, two existing exact station references resolved. The user's public
list loaded, but its two references returned no records.
The earlier release was only smoke-tested publicly for launch and playback. Its
local-only search and fixture-only favourite verification missed these differences.
`tests/live-release.mjs` now checks the actual published catalogue/search;
`tests/live-services.mjs` supports pre-release host testing without substituting
a signed artifact or mocking relay results.
