docs(skill): correct emulator sync points and tap targets

Log level prints after the tag, the app's own log precedes the host's running line, wait-frame/sleep are unavailable, and the card grid is two columns.
This commit is contained in:
2026-08-05 11:00:00 -04:00
parent 97abf037b8
commit 575f31e7ee
+23 -17
View File
@@ -32,11 +32,12 @@ Use an executable `.e32r40t` script. Assert on the app path the firmware logs ra
#!/usr/bin/env -S esp-emu --board e32r40t
boot .pio/build/esp32-32e/firmware.bin --sdcard sdcard/ --fresh-sd
wait-log "launcher ready" --timeout 120
wait-log "\[lua\] info: home ready" --timeout 180
wait-idle 3
tap 60 55
tap 85 127
wait-log "running Hello"
wait-log "\[lua\] .* started"
wait-idle 3
capture _scratch/emulator-app.png
```
@@ -50,27 +51,28 @@ Blank lines and `#` comments are allowed. Scripts also run explicitly or through
```sh
esp-emu --board e32r40t --state /tmp/my-test run flow.e32r40t
printf '%s\n' 'boot .pio/build/esp32-32e/firmware.bin' 'wait-log "launcher ready"' | esp-emu --board e32r40t run
printf '%s\n' 'boot .pio/build/esp32-32e/firmware.bin' 'wait-log "info: home ready"' | esp-emu --board e32r40t run
```
## Synchronization
Lua logs carry a level in the prefix (`[lua:info] home ready`), so match `\[lua:info\]` and
not `\[lua\]`.
`LogProvider` prints the level after the tag -- `[lua] info: home ready` -- so match
`\[lua\] info:` and never `\[lua:info\]`, which matches nothing and burns the whole timeout.
Firmware sync points, in order: `running <path>` (printed by the host for every app,
including the launcher itself), `[lua:info] home ready` (menu
drawn, touch accepted), then whatever the app logs through `log.info(...)`. Exiting an
app relaunches the launcher, so both lines repeat.
Firmware sync points, in order: an app's own `log.info(...)`, then `running <path>` printed
by the host for every app including the launcher. The app line comes **first**, because
`init()` runs inside `startApp()` and the host logs the route after it returns. Wait for
`[lua] info: home ready` and then `running Home`. Exiting an app relaunches the launcher, so
both lines repeat.
A scripted tap must land after the app is idle: `setup()` can block for seconds on a
full-screen clear under TCG, and a 250 ms press that lands during it is missed
entirely. Wait for the app's own ready log, then `sleep` a few seconds.
entirely. Wait for the app's own ready log, then `wait-idle 3`.
- Use `wait-log REGEX` as the default synchronization and assertion mechanism.
- Assert on the `running ...` line rather than on tap coordinates: menu rows follow SD directory order, which the image build decides.
- Use `wait-frame [COUNT]` only when a panel redraw is itself the behavior under test.
- Use `wait-idle SECONDS` only when silence is the actual readiness signal.
- Use `wait-idle SECONDS` between a ready log and the first tap, and between a tap and a capture.
- `wait-frame` is an e-ink command and hangs on this board; `sleep` is not a command at all. A script using either stops silently.
- Capture and inspect the final screen after semantic log assertions.
## Touch
@@ -78,12 +80,16 @@ entirely. Wait for the app's own ready log, then `sleep` a few seconds.
`tap` always takes physical panel pixels (320x480 portrait), because the glass never rotates.
Screens are laid out by `/.lua/lib/ui.lua`, so read tap targets off a `capture` rather than
computing them. The status bar takes the top 44 rows; card grids use three portrait columns
and four landscape columns. With the current apps, portrait Home card centres are near
`(109,102)` and `(210,102)`, while Settings' first row is near x=59/160/261 at y=102.
computing them. The status bar takes the top 44 rows and card grids are two columns wide in
portrait. With the current apps, portrait Home card centres are near `(85,127)` / `(235,127)`
and `(85,275)` / `(235,275)`, and Settings' rows sit at x=85/235 with y=115/240/375.
Taps that land within the first few seconds after a ready log are missed, so `wait-idle 3`
before the first one.
A grid reflows when the frame does, so the rotated launcher is not the portrait one turned
sideways -- its cards move and change count per row. After any rotation, capture and read the
new targets instead of converting the old ones.
Use `touch-hold` plus `capture` plus `touch-release` to photograph a pressed button:
`on_press` fires on release, and the pressed style is only visible mid-gesture.
@@ -127,7 +133,7 @@ the submodule and are not committed here. Directory contents overwrite matching
## Lua-only Logic
Pure Lua helpers run far faster on the host than in the emulator. Stub the `gui`, `input`, `sys` and `log` tables and load the app directly, as `test/settings_calibration.lua` does:
Pure Lua helpers run far faster on the host than in the emulator. Stub the `screen`, `tree`, `touch`, `sys` and `log` tables and load the app directly, as `test/settings_calibration.lua` does -- or use `test/fake_device.lua`, which is the single definition of that binding surface:
```sh
nix run nixpkgs#lua -- test/settings_calibration.lua