SchOS/.claude/memory/schos-bootcheck-trust.md
Nexoniarz c55e65de5e memory: the e820 work, and why the extended suite flaps
Records the measured effect of the region-based allocator (2.2x on a cold
ls, 6 s off the boot), the two pre-existing UEFI blockers found while
verifying it, and the three confounds that each produced a confident
wrong answer about guest speed in one session.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 21:05:34 +02:00

76 lines
3.6 KiB
Markdown

---
name: schos-bootcheck-trust
description: bootcheck silently stopped running and five of seven modes asserted nothing; how to tell a real pass from a script that died
metadata:
node_type: memory
originSessionId: 9d8a2aef-bcf0-47a0-96c6-f706efab4a95
modified: 2026-08-09T19:05:06.942Z
---
**A green run is only green if you counted the checks.** On 2026-08-09 the
bootcheck suite was reported passing seven times when it had not executed at
all, and separately when five of its seven modes asserted nothing whatsoever.
**Why:** `bootcheck.ps1` had `[string]$Qemu = (Find-Qemu)` as a param default.
PowerShell binds parameter defaults *before* any function in the script body is
defined, so it died on its first line with "Find-Qemu is not recognized" —
text containing neither `FAIL` nor `Exception`, which were the two words being
grepped for. Empty output was read as success. Resolve after the param block:
`if (-not $Qemu) { $Qemu = Find-Qemu }`.
**And:** an earlier index-based edit (`s[:a] + inner + s[c:]`) that removed the
obsolete `-SchFS` block also deleted the `Expect` blocks for `-Tty`, `-Usb`,
`-Sock`, `-Ps` and `-Evdev`. Those modes still booted, still printed, and still
exited 0 — asserting nothing. It happened before `git init`, so no commit ever
had them; they were reconstructed from failure text quoted earlier in the
transcript.
**How to check a run is real:**
```sh
grep -c '\[ok\]' # must be non-zero, and roughly what you expect
grep -c 'boot check passed'
```
Counting `FAIL` alone cannot distinguish "passed" from "never ran". Expected
counts as of 2026-08-09: base 23, Tty 47, Ps 28, Sock 60, Fb 32, Usb 27,
Evdev 25 — Tty and Sock include `[ok]` lines printed by the guest programs
themselves.
**Never pipe a long bootcheck through `head`.** It closes the pipe, kills the
script partway, and looks like a hang. Redirect to a file and grep the file.
**Why:** the general lesson is that absence of failure output is not evidence
of success. Both of these produced clean-looking runs while testing nothing.
**How to apply:** after any change to the harness itself, verify the check
count, not just the absence of FAIL.
## The extended suite is timing-fragile on the Fedora laptop
`Wait-Prompt` waits a fixed **20 s**; measured on this machine with the guest's
own `/proc/uptime`, a cold `ls /bin | wc -l` takes **23 s** and took **51 s**
before the e820 work. When it overruns, the script sleeps 2 s and types anyway,
so the next command lands in a busy shell and the transcript interleaves — and
the check that fails is then some *later* one whose output is no longer
adjacent to its command. `yes writes through a pipe` failed this way while
`y`/`y` were plainly correct in the transcript. Treat a single FAIL in
`-Fb -Tty -Usb -Sock -Evdev -Ps` as suspect until the transcript is read.
**Leaked QEMU made this worse and is now fixed** (commit 4e0478c): the
`finally` cannot run when the *script* is killed, so QEMU outlived it and, under
TCG, taxed every later run. Each run now records its pid and reaps the previous
one's orphan.
## Measuring anything about guest speed
Do not use host wall clock, and do not compare runs made minutes apart. Three
confounds each produced a confident wrong answer in one session:
1. **Stray QEMU** pinning a core (see above).
2. **`build/schfs.img` ages** — it accumulates writes across boots. Delete and
`make build/schfs.img` before every timed boot.
3. **Ordering / host drift** — alternate the variants and run each twice.
Time it from inside: `cat /proc/uptime` either side of the command. The guest's
tick does not care what the host is doing. See [[schunix-verify-by-driving-shell]].