Skip to content

test(uci): menu-driven rig proving the HTTPS banner names the real host (#128) - #130

Merged
JC-000 merged 1 commit into
masterfrom
test/banner-hardware-rig
Aug 22, 2026
Merged

test(uci): menu-driven rig proving the HTTPS banner names the real host (#128)#130
JC-000 merged 1 commit into
masterfrom
test/banner-hardware-rig

Conversation

@JC-000

@JC-000 JC-000 commented Aug 22, 2026

Copy link
Copy Markdown
Owner

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.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 one walks the menu the way a human does (I to init, G to start the GET) and reads screen RAM at $0400.

Hardware result

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

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 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 — only screen_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.
  • 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

  • Lets the fetch finish and sends Q, because do_https_get only reaches tls_close/net_tcp_close after the viewer returns. Resetting with a live firmware socket poisons the UCI lease pathGET_IPADDR then returns 0.0.0.0 on every interface and only a wall power cycle clears 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.

Scope

Test-only plus a CLAUDE.md entry. No src/, cfg/ or Makefile changes, 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

…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant