SOURCE / PINNED RELEASE
Made of little things.
Limb Race
- Release
- 6a8ae4fc626e…
- Author-recorded commit
- 008c01ee6454…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-c2869f12ad8
Archive hash verified: 7be8492d1f89b891…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
# Verification evidence
Verified on 2026-09-23 with soyLI 0.20.0 on macOS arm64.
## Automated checks
- `pnpm verify`: 6 guidance checks and 87 game/data regression checks pass; TypeScript and single-file build pass.
- Physics regressions cover rigid and bendy Runner designs completing Meadow Run and long corner legs completing both ledge tracks. A 24-case matrix of circle sizes, an oval and an eccentric wheel across both ledge tracks/materials stays blocked for the full 180-second race limit. This tests representative wheel designs rather than claiming a proof for every possible drawing.
- Additional checks cover vertical-face collision response, no horizontal thrust in midair, no propulsion with the motor off, reverse travel with reversed rotation, spring deflection/recovery, material-dependent times, Live Draw preserving progress, snapshots copied by value, square-corner reach, malformed geometry rejection, continuous retraced-stroke rendering, and the 16 versioned board IDs.
- `pnpm test:conformance`: **5 passed, 0 failed, 5 skipped**. Boot, sandbox, forbidden globals and optional-domain degradation pass. Three manifest checks skip because no signed publication manifest was supplied. Wire and lifecycle coverage are not measured by this invocation.
- `soyli check`: **blocked by a soyLI 0.20.0 config-size bug** before host loading. The CLI pretty-prints the legal compact board configuration beyond its own 16 KiB read limit. Real-host interaction tests in `soyli dev` pass; they do not turn this failed check into a pass. See `docs/host-gaps.md`.
- Authored code and the final bundle have no direct network, browser persistence, signer, host DOM or external asset references. Artifact is one `dist/index.html` with inline JS/CSS.
## Challenge expansion
Six new courses bring the total to ten. Regression fixtures complete each with one unchanged, legal four-corner drawing in both materials (no live edits):
| Course | Rigid | Bendy |
| --- | ---: | ---: |
| Sawtooth | 15.09s | 21.14s |
| Pinpoint | 19.20s | 24.37s |
| Trench Trouble | 30.10s | 24.97s |
| Skyline | 23.13s | 57.68s |
| Ridge Runner | 30.25s | 77.01s |
| The Gauntlet | 76.23s | 78.57s |
Runner starter designs fail all six over the full race limit. Additional full-size wheel tests fail Sawtooth, Trench Trouble and Skyline in both materials. Terrain validation checks unique IDs, finite coordinates, ordered boundaries and start/finish support. The four original tracks, motor and collision rules remain unchanged. Personal physics-v2 times remain comparable. Shared drawing boards now use separate `-draw1` IDs; personal records still separate track, mode and material.
`tests/challenges-smoke.mjs` completes a real 15.09-second Sawtooth race from four pointer-drawn strokes, verifies the share action is hidden on challenge courses, checks the explicit personal-only Shared state, inspects saved limbs, verifies track isolation and reload persistence, and selects the final course through the scrolling menu in both themes. Close controls and difficulty labels remain visible. No browser errors.
## Hosted behavior
`tests/host-smoke.mjs` exercised the actual `allow-scripts` iframe in soyLI:
- Complete a Classic race, verify drawing controls lock, pause/resume without clock advancement while paused.
- Submit a genuine completed run to the isolated local CVM service, then read it back. Separate browser sessions see one another's local shared entries and separate scoped actor IDs.
- Inspect a personal design and reuse it; mouse drawing and undo; apply a new shape during Live Draw.
- Reload and confirm stored personal history remains available.
- No page errors during those flows.
`tests/improvements-smoke.mjs` draws four actual corner strokes into the square, completes Step It Up in Bendy mode (9.08 seconds), submits the result to the local shared board, inspects/reuses the saved material and verifies rigid/bendy ranking isolation. It also checks material locking, ten track options, removal of the wheel preset and live drawing with bendy limbs. No page errors.
`tests/optional-smoke.mjs` completes a race in an opaque iframe without any injected capabilities. It verifies personal session history, missing-storage feedback, a hidden share action, and a clear unavailable state on the Shared tab. It also covers the non-secure-context local run-ID fallback.
## Frames, themes and touch
- Actual iframe sizes **200×160**, **320×560**, **900×600**, **2400×1200**, both light and dark: no document overflow; 200×160 shows the declared minimum-size notice. Working state survives resizing.
- The host normally supplies a fixed light palette. The dark test sends a standard `theme.changed` event from the parent test harness, checks the applied colors, and captures the result. Browser dark-mode emulation alone is not counted as a theme test.
- `tests/mobile-smoke.mjs`: Chromium mobile/touch emulation at **390×844**, **360×640**, **844×390**; real touch start/move/end drawing, Live Draw edits, pause/resume and selection of the final course (10 / 10) pass. The pad and race action remain visible, with 44px touch controls. The white drawing surface remains square at every tested frame. Phone toolbar spacing was tightened after testing uncovered overflow.
- Test-only iframe sizing overrides the manager's minimum height and host chrome. Assertions check the iframe's own `innerWidth`/`innerHeight` before interaction.
- Physical iOS/Android devices have not been tested.
## Shared drawings and custom levels
`pnpm test:sharing` runs the built game in the actual soyLI host with two independent browser contexts, ephemeral test signers, an isolated Nostr storage relay and the local CVM service. Non-loopback HTTP and WebSocket traffic is blocked. The test temporarily changes the runtime relay hint before building, then stops its owned preview, verifies its listener closed, and restores configuration byte-for-byte.
Verified: consent denial followed by retry; signed public level creation; anonymous discovery; another identity remixing into its own record; owner updates after reload; relay rejection followed by retry; stale drafts refused; identity changes rejecting prepared writes; malformed level records skipped; and tombstones hiding originals while remixes survive. A custom starter course finishes and stores its complete terrain snapshot. A real original-course race is shared, then another identity inspects and reuses its drawing. Equal/worse score probes preserve the prior attachment; an improved score changes the entry revision, and stale UI selections refuse the replacement drawing until refresh.
The editor passes the light/dark layout matrix at 200×160, 320×560, 390×844, 844×390, 900×600 and 2400×1200 with no document overflow. The small-frame notice remains the game's minimum-size fallback. Captures are real UI screenshots, not generated illustrations.
## Capabilities and publication
CVM uses `soy.boards.v2` with bounded JSON drawing attachments. STORAGE holds bounded personal races and level drafts. The public backend context remains copied to `soy-backend.json`. Public levels use the shipped `soy.app-data/1` helper, SDK OUTBOX/IDENTITY and host consent. No signer, direct network, relay pool or browser persistence is introduced in the napplet. Theme and appearance configuration remain optional; hard requirements remain empty.
Host limitation: 16 configured boards, no dynamic board for each custom level. Custom and challenge-pack times remain personal. Shared score identity remains an authenticated session actor, not a verified Nostr profile; level authors are their Nostr public keys. Times are client-reported. Shared Live Draw attachments hold the finish drawing; personal records retain bounded edits.
Observed soyLI 0.20.0 integration issue: preview prepends the temporary CVM relay to the host's relay list, so the helper's default destination cannot store NIP-78 records. The app selects the first explicitly declared runtime storage relay using the helper's supported `relays` option. Host configuration and consent still govern publication. Local integration is verified with an isolated storage relay; public board registration, public level persistence and the deployed website are not certified by this test. The public provider responded to `soyli backend status --json` and advertises `soy.boards.v2`. No public release or test level/score records were published.
The initial history includes a public backend context at its former `.napplet-space/` path. The prior soyLI 0.19.0 publication scan rejected that directory even though no credentials were present. Release preflight has not been repeated under 0.20.0; history was preserved.
## Media and preview cleanup
- `preview-levels.png`: selected, inspected 1200×750 real editor screenshot. Recipe: open Create a level, name it Cliffside circuit, append Step up → Drop → Trench → Uphill, then Save draft. The starter ramps remain at the beginning.
- `.napplet-space/promotion/editor-touch-portrait.png`: inspected 390×844 touch-emulated editor screenshot. The mobile smoke test adds/reorders a step, saves the draft, tests the course and pauses it at 390×844, 360×640 and 844×390. All three pass with no browser errors. Actual iOS/Android devices remain untested.
- `.napplet-space/promotion/editor-900.png` and `editor-390.png`: desktop and narrow editor layout captures; all six frame sizes pass in light and dark.
- No clip is selected. Previous clips belong to earlier builds, and the fresh soyLI capture/check path is blocked by the config-size issue. Portrait recording remains unsupported by the bundled recorder.
- Caption: **“Draw the racer. Build the challenge. Share both.”**
- Test previews are stopped in cleanup. The final manual preview was `http://127.0.0.1:52915/`; its owning session is stopped after verification. Restart with `soyli dev --port 0 --no-open`.
## Release asset verification, 2026-09-23
The final game build again passes all 6 guidance and 87 physics/data checks and TypeScript. A tested, isolated CLI compatibility build passes `check` using profile `space-playback-4`; details are in `docs/host-gaps.md`. No sandbox, credential, signing or source-history checks were disabled.
The selected cover is now `preview-release.png`, a fresh 1200×750 Ridge Runner race with four pointer-drawn diagonal limbs. `promo-portrait.png` is an actual 390×844 portrait capture of the same scene. The editor cover remains available as `preview-levels.png`.
`preview-release.webm` is a fresh official capture of this exact artifact: 960×600, VP8, 25 fps, 9 seconds including the recorder’s final hold, 870,270 bytes. Live Draw and Bendy are selected, and the drawing changes Runner → Star → Runner while racing Meadow Run. Representative frames and full end-to-end playback were inspected in Listing; the cover loaded at 1200×750. The artifact hash matches the rebuilt HTML. See `docs/release-assets.md` for the recipe and captions.
