Back to Sketch Loop
SOURCE / PINNED RELEASE

Made of little things.

Sketch Loop

Release
14966bba4a2a
Author-recorded commit
e68361295d81…
License
LICENSE
Author’s source reference
nostr://npub1n8ga89w8h6tvwamxusfyzexw8gjy84yxu9rxgnmk955cxtml4ujswzxydd/wss%3A%2F%2Fgit.napplet.soy%2F/n-929bc2a88cb

Archive hash verified: 5e0385e3c08f944f. The source-to-build association is the author’s claim; it has not been independently rebuilt.

docs/verification.md
# Verification — 2026-09-16

## Result

Implemented and tested locally in soyLI 0.9.0. Preview: http://127.0.0.1:4173/ while `soyli dev --no-open` is running. No publication was performed.

## Build and host evidence

- `pnpm type-check`: pass (also included in `pnpm verify`).
- `pnpm build`: pass; `dist/` contains only the inlined `index.html`.
- `pnpm test:guidance`: 6 tests passed.
- `pnpm test:sketch`: 7 tests passed, covering the supplied BusyMozaic, collapsed/escaped social text, scopes and loops, runaway execution, blocked host/prototype access, size limits, and exact GIF timing.
- `pnpm test:conformance`: **conformant**, 5 passed, 0 failed, 5 skipped. Manifest checks (3), wire envelope evidence (1), and lifecycle evidence (1) were not supplied and were skipped. These are not claimed as verified.
- `soyli check --json`: pass, profile `space-playback-2`, Chromium 153.0.8010.12.
- Final artifact hash: `3e4939f95fbe1954d1f637930e3d74f08f2ad71d0575f9896d246a060218b17b`.
- `soyli screenshot preview.png --json`: captured after final implementation and selected in `napplet.json`; visually inspected.

## Actual sandbox integration

`node tests/browser.mjs` passed in the real soyLI host with its `allow-scripts` iframe and restrictive CSP:

- BusyMozaic loads and animates, as do Orbit study and Ribbon field.
- Pause/resume, syntax errors, unavailable host-global access, and infinite-loop termination recover correctly.
- Export cancellation keeps the sketch usable.
- Generated a 1.1-second GIF at 15 fps, saved through the actual host picker, wrote it in 256 KiB chunks, and downloaded the file through the host-provided link.
- Downloaded GIF: 1,197,125 bytes, 450 × 300, 17 frames.
- Independent `ffprobe` reported GIF duration **1.100000 seconds**, 450 × 300, 17 frames. `ffmpeg -v error -i ... -f null -` decoded every frame without errors.
- Explicit draft save and subsequent reload restored code and export settings. Restored user code requires Run before execution.
- No page errors were recorded.

An additional isolated browser check changed the real host Settings form: duration 5 → 7, FPS 15 → 20, crisp preview → smooth. All changes applied live, and duration persisted on reload.

## Layout and themes

Checked the exact iframe viewport at **200×160, 320×560, 900×600, and 2400×1200**, in both dark and light runtime themes, including editor, preview, and GIF views. No horizontal document overflow or clipped horizontal controls. The actual frame dimensions were asserted, overriding the host's iframe minimum height in the test only. Root, body, and html backgrounds followed runtime theme-change messages. Representative screenshots were inspected and are retained privately in `.napplet-space/qa/`.

The tiny/compact/short layouts use view tabs; larger frames show code, preview and export controls together. There is no app title chrome and no minimum-size refusal.

## Authority and remaining limits

Product code uses optional SDK `theme`, `storage`, `config`, and `fs` helpers. No hard `requires`; missing domains disable only their enhancement. No relay use, Nostr operations, cross-napplet operations, browser persistence, network access, dynamic code evaluation, or direct host access. Pasted code receives an allowlist of drawing/math functions and interpreter-owned data. The shipped Acorn/gifenc bundle passed forbidden-global scanning.

This is a **2D p5-style subset**, not complete p5.js or JavaScript compatibility. Unsupported APIs fail visibly; see Help/README for the supported surface. Some color/noise/text behavior differs from p5.js (noise is deterministic value noise). No assets, DOM, WebGL, imports, async code, classes or array methods. Repeating a GIF cannot guarantee a seamless loop. Transparent output is flattened on black.

File export was verified against local soyLI. Other hosts may lack FS, deny operations, impose smaller quotas, or expose a different save UI. Deployed-host behavior was not tested because the napplet has not been published. The custom interpreter is bounded and regression-tested, but has not received an independent security audit.

## Main changes

- `src/interpreter.ts`: bounded parser/evaluator and pasted-post normalization.
- `src/sketch.ts`: 2D drawing surface and examples.
- `src/export.ts`: deterministic timed GIF rendering, limits and cancellation.
- `src/main.ts`, `index.html`, `src/styles.css`: editor, responsive preview/export UI and optional SDK integrations.
- `config.schema.json`: relevant export defaults and preview settings.
- `tests/sketch.test.mjs`, `tests/browser.mjs`: focused behavior and real-host integration checks.
- `README.md`, `docs/build-spec.md`, metadata and `preview.png`: usage, boundary specification and reviewed listing assets.
- SDK updated from 0.24.4 to 0.28.0 for FS; added Acorn and gifenc. Existing build and conformance substrate preserved.