Commit Graph
3 Commits
Author SHA1 Message Date
NoahandClaude Fable 5.1 8805b6106c qemu: review pass over the rig driver and boot script
Four review passes with fixes between them (flare-edge's flow-framework
review, 2026-09-09). qmp.py: drive() split out of a 330-line dispatcher,
every verb guarded so a raising verb records a fatal row instead of ending
the run, the shot path sanitised, the rs485 and wait verbs judged through
shared helpers; imgtools.py: a bench subcommand for phash/structural
timings and a colour probe that samples instead of scanning the frame;
ui-drive.sh: the boot poll no longer walks every pixel per tick and the
simulator's control socket path is passed as one word. Offline tests: 8.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3G6m9Aw5RyVY4ZowtKzEj
2026-09-09 13:52:47 -06:00
NoahandClaude Fable 5.1 bd5c5af9db qemu: structural hash relative to the background, taps that land on the pixel
imgtools.structural() marked a cell occupied when its grey exceeded an
absolute 10/255, and the WardenOS page background is grey 16: every cell
of every region read occupied and no structural check could ever fail
(#19). Occupancy is now grey deviating from the crop's own median by more
than DEVIATION_THRESHOLD, or edge energy above EDGE_THRESHOLD. Measured on
real captures: a switch knob left/right differs in 240 of 256 cells (was
0), a dark card reads its icon and text and nothing else. Every committed
reference is recaptured with flare-edge tools/flow-run-all.sh --capture.

qmp.py to_axis() truncated the pixel-to-axis conversion and LVGL's
evdev calibration truncates on the way back, so many pixels landed one
short (130 -> 5924 -> 129) and a tap could miss the control hit had just
confirmed at that pixel (#21). It now rounds up to the smallest axis value
that truncates to the requested pixel; test_qmp_drive.py asserts the round
trip for every pixel at three panel sizes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3G6m9Aw5RyVY4ZowtKzEj
2026-09-08 13:53:59 -06:00
NoahandClaude Fable 5.1 86a9544dcc qemu: json/stat/region channels, seeding, driver tests
- rootfs/sbin/init: the control bridge answers `@cat PATH` locally so the
  driver can read /tmp/warden-web-status.json out of the guest. That file
  has no trailing newline; the bridge adds one so the sentinel stays on
  its own line and the line-based reader never blocks.
- tests/qmp.py: wait_json/assert_json (dotted paths, eq/ne/contains/
  len_eq/len_ge/gt/lt), assert_stat off the FIFO's stats reply,
  capture_region, assert_region NAME [TOLERANCE] and assert_ocr. A
  tolerance other than the captured one, a reference box that does not
  fit the screendump, a missing reference or a missing tesseract is FATAL
  for that step and the run continues (flare-edge #147).
- tests/imgtools.py: P6 reader, crop, perceptual and structural hashes,
  compare, with a self-test.
- tests/test_qmp_drive.py: drive() with QMP and the control channel
  faked, pinning the per-step ok/fail/fatal contract.
- mkimage.sh SEED_DIR and ui-drive.sh --seed/--refs: settings fixtures
  staged into userdata before warden-ui starts, and a reference store
  handed to the driver.
- ci: the driver tests and the imgtools self-test run in qemu-tools.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013aHKWzT5EF86RFKRMtAv9n
2026-09-07 23:26:01 -06:00