Back to Powder Tool
SOURCE / PINNED RELEASE

Made of little things.

Powder Tool

Release
242076e6da24…
Author-recorded commit
c4489f440f27…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-48e516e34e5

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

docs/powder-verification.md
# Verification and capture notes

Verified 2026-09-23 with soyLI 0.18.2 on macOS arm64. This is a local build; nothing was published.

## Results

- `pnpm verify`: 6 guidance checks, 22 physics regressions, TypeScript, and single-file production build pass.
- `pnpm test:conformance`: **5 passed, 0 failed, 5 skipped**. Passes cover sandbox, runtime injection, boot, forbidden globals, and optional-domain absence. The three manifest cases lack a signed event; wire evidence and lifecycle measurement are absent in the reference harness. Skips are not verified coverage.
- `soyli check`: pass, host profile `space-playback-4`, Chromium 153.0.8010.12.
- Built `dist/index.html`: one self-contained file, approximately 60 KB. No authored direct network, browser persistence, signer, host DOM, or relay access. No hard requirements. Optional SDK domains remain theme, storage, and config; no relay escape hatches.
- Real-host interactions: material selection, painting, pause/step, body placement, undo, save/clear/load, and 300→600 resolution changes pass. Emitter placement, material/rate/width/direction edits, disabling, paused stepping, move, save/load, deletion, and undo pass. Both desktop and touch flows use visible controls.
- Physics tests cover the original material/body behavior plus gas rise/sink ordering, combustion, inert helium, CO₂ extinguishing, gas confinement, source rates/directions, blocked outlets, source deletion, invalid save rejection, lossless version-2 saves, legacy version-1 loading, and stage resampling.
- On this machine, the 600-cell-wide Gas lab runs at approximately 60 fps in headless Chromium. This is not a phone performance measurement.

## Frame and touch checks

All four actual iframe sizes passed in light and dark: **200×160, 320×560, 900×600, 2400×1200**. Checks assert no document overflow, matching background on html/body/root, accessible primary controls, and pause/step/material interaction. Dark/light are delivered as standard theme-change messages from the test host; soyLI's default preview palette is light.

The existing scene is fitted during frame resize without losing its contents. Choosing an example creates a world suited to the current frame. The Stage detail control resamples the current scene to a new cell count; lowering detail merges small features, and Undo restores the previous grid.

The harness fixes the actual iframe size and removes its minimum height. This is a test-only override of the manager frame, whose normal minimum is 300px; the 200×160 result is not inferred from screenshot dimensions.

Touch emulation uses real browser viewport sizes and coarse-pointer input:

| Browser viewport | Actual napplet frame | Result |
| --- | --- | --- |
| 390×844 | 390×709 | Pass |
| 360×640 | 360×505 | Pass |
| 844×390 | 844×300 | Pass |

Touch tests cover water painting, stone placement, undo, emitter setup/placement/disable/removal, scene controls, visible host settings, and toolbar targets of at least 44px. The manager is scrolled to bring the canvas into the visible viewport before touch input. Physical iOS/Android performance and device-specific behavior remain untested.

Reproduce while the preview is running:

```sh
soyli dev --port 0 --no-open
# Use the actual URL it prints in another terminal:
POWDER_PREVIEW_URL=http://127.0.0.1:PORT/ node tests/host-ui.mjs
```

The test uses Chromium/Playwright already supplied by the conformance tool. Detailed results and screenshots go under ignored `.napplet-space/promotion/`. This verification used `http://127.0.0.1:64639/`; the owned preview is stopped after testing.

## Media

- `preview-v2.png`: inspected 1200×750 cover of the Gas lab, selected in napplet.json. Four distinct gas sources demonstrate upward and downward flow.
- `preview-gases.webm`: silent 960×600 recording. Its saved action recipe opens the scene selector, chooses Gas lab with `g`, confirms with Enter, and lets the sources run. Requested duration is six seconds; soyLI may append a final hold.
- `.napplet-space/promotion/portrait-gaslab.png`: an actual emulated phone frame, not a crop of the landscape UI.
- Earlier preview files are preserved. The selected clip must match the current artifact hash; after changing app code, recapture it rather than altering the hash.
- Portrait video is not produced by soyLI's fixed landscape recorder. A manual portrait recipe is to open Gas lab at 390×844, change a source from helium to hydrogen, add fire, and record the result for five seconds.

Caption: “Build flowing worlds with fine particles, reactive gases, and configurable sources.”

## Product limits

This is a cellular material simulation coupled to convex rigid bodies, not a scientific fluid or thermodynamic solver. Liquids use local spreading and approximate buoyancy. Gases have material-specific motion, lifetime, and reactions; there is no continuous pressure or temperature field. Changing outlet direction positions emitted cells on that side of the source; their subsequent motion follows their material.

There are at most 48 bodies and 24 emitters. A source emits only into empty, unoccupied cells; blocked outlets discard their unused budget. Scene storage keeps one validated, lossless snapshot with a 480 KB size guard; extremely detailed scenes can exceed that limit and show an error. Version-1 saves remain readable. Host storage scope may change across builds. Undo keeps eight edit snapshots in memory and is not a continuous simulation rewind.