test(uci): menu-driven rig proving the HTTPS banner names the real host (#128) - #130
Merged
Conversation
…st (#128) The #128 banner fix shipped with its on-screen behaviour unverified, and the existing rigs could not have verified it: rig_https_wiki.py and rig_https_local.py both drive http_get through a DMA'd trampoline, so neither ever executes do_https_get — which is where the banner lives. The wikipedia rig PASSes with a banner saying anything at all. This rig walks the menu the way a human does ('I' to init, 'G' to start the GET) and reads screen RAM at $0400. Result on hardware — U64E 601A96, fw 3.14d, 48 MHz, comb wikipedia build at master 305051c: BANNER: 'HTTPS GET EN.WIKIPEDIA.ORG...' names EN.WIKIPEDIA.ORG: True says FOO.BAR: False and the fetch that followed completed: http_status=200, http_body_total = 125,235 B into REU $10:0000, first 512 body bytes byte-identical to a live host-side reference, article wikitext readable in the viewer on the real screen. Two traps the rig is written around, both of which produced a false FAIL in its first version: - `decode_screen()` returns LOWERCASE rows; only `screen_text()` uppercases, when it joins them. Comparing a raw row against "HTTPS GET" therefore never matches, and the rig reported "no banner appeared" against a screen that had one. The screen dump is what gave it away — every row was a handshake marker, i.e. the machine was doing exactly the right thing. - At 48 MHz the handshake prints ~24 progress markers and scrolls the 25-row screen, so the banner is short-lived and the scan must start immediately with no sleep. Device hygiene, deliberately not optional: - It lets the fetch run to completion and then sends 'Q', because do_https_get only reaches tls_close / net_tcp_close after the viewer returns. Resetting a machine with a live firmware socket poisons the UCI lease path — GET_IPADDR then returns 0.0.0.0 on every interface and only a wall power cycle clears it. The clean exit is not politeness. - It runs the /Temp GC after enable_uci (fw <= 3.14d leaks one temp file per REST body; run_prg is a big writemem). Measured: 3 stale attachments removed on the first guarded run. - Progress is a DMA poll of http_body_total, not a screen marker: the viewer's status row ends in "Q=QUIT" and so does the main menu, so the obvious marker cannot tell them apart. Test-only plus a CLAUDE.md entry; no src/, cfg/ or Makefile changes, so every shipped image is untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the verification gap I flagged on #129: that fix shipped with its on-screen behaviour unverified.
Why a new rig was needed
No existing rig could have caught the #128 banner bug.
rig_https_wiki.pyandrig_https_local.pyboth drivehttp_getthrough a DMA'd trampoline, so neither ever executesdo_https_get— which is where the banner lives. The wikipedia rig PASSes with a banner saying anything at all.This one walks the menu the way a human does (
Ito init,Gto start the GET) and reads screen RAM at$0400.Hardware result
U64E
601A96, fw 3.14d, 48 MHz, comb wikipedia build at master305051c:The fetch that followed completed:
http_status=200,http_body_total = 125,235 Binto REU$10:0000, first 512 body bytes byte-identical to a live host-side reference fetch, and the article wikitext readable in the viewer on the real screen.Two traps it is written around
Both produced a false FAIL in the first version, which is the reason they're documented in the file rather than just fixed:
decode_screen()returns LOWERCASE rows — onlyscreen_text()uppercases, when it joins them. Comparing a raw row against"HTTPS GET"never matches, so the rig reported "no banner appeared" against a screen that had one. The screen dump is what gave it away: every row was a handshake marker, i.e. the machine was doing exactly the right thing.Device hygiene, deliberately not optional
Q, becausedo_https_getonly reachestls_close/net_tcp_closeafter the viewer returns. Resetting with a live firmware socket poisons the UCI lease path —GET_IPADDRthen returns 0.0.0.0 on every interface and only a wall power cycle clears it./TempGC afterenable_uci(fw ≤ 3.14d leaks one temp file per REST body;run_prgis a big writemem). Measured: 3 stale attachments removed on the first guarded run.http_body_total, not a screen marker — the viewer's status row ends inQ=QUITand so does the main menu, so the obvious marker cannot tell them apart.Scope
Test-only plus a CLAUDE.md entry. No
src/,cfg/orMakefilechanges, so every shipped image is byte-untouched.Left unmerged for your call: the standing autonomy covers fixing Armitage64's issues, and this is new test tooling rather than an issue fix. Say the word and I'll merge it.
🤖 Generated with Claude Code