Give the shooter its one missing flag, and redraw the frames - #103
Merged
Conversation
docs/media had drifted a whole release behind the app: list.webp and list-full.webp still showed the duration chip bar #95 deleted, and room.webp still showed the on-map walk-time pill #94 removed. Twice the conclusion was that no browser was available here. It was, and the blocker was one launch argument. Chromium's sandbox needs a non-root user to drop privileges to and refuses to start without one, so as root it exits 1 before it ever writes DevToolsActivePort — the "chrome exited with 1" that got read as "no browser". --no-sandbox is added only when process.getuid() is 0, so a desktop run keeps its sandbox. chromePaths() also learned the Playwright cache (PLAYWRIGHT_BROWSERS_PATH and ~/.cache/ms-playwright, newest build first), which is where the Chromium on this machine lives; CHROME= still works and is no longer needed. All five frames were regenerated in one run, not just the two stale ones, so the set is one moment of one app. The pinned clock and pinned position are unchanged, so the frames are the same photograph they always were, of a newer app. What the app now prints changed with them, so frames.json and the README follow the pictures rather than the other way round: - the chip bar is gone and the sheet says "You asked for 2h00." - the list ranks differently and departmental rooms carry a label, so the top rows are Cunz Hall 160 and PAES A111 - the room screen's second button reads Directions, not Maps - ask.webp shows four buttons under "How long?", not three under "How long do you need?" — alt text that was already off the image The README's worked example pointed at the third row of the middle screenshot, which is no longer Psychology Building 217. It now reads the second row, PAES A111: the row and the room screen both say free till 4:00pm, the room screen says Yours for 5h36 once you get there (read off the app during the shoot), and PEA0111's Wednesday interval in data/rooms-1268.json starts at 970 minutes, 4:10pm, which is the ten minutes of packup the row takes off. The #77 sentence keeps its point without the old room's number. Verified by opening each frame: no chip bar under the list, no "3 min walk" pill on the map in room.webp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xiX95r6nnUUmhD3KwMnWM
…ndbox Review verified every new README number from primary sources and found the shooter's own race is more frequent than this branch disclosed: it hit on the reviewer's first --check and twice in nine runs, roughly 20%, not the zero-in-four reported here. Page.navigate resolves when the navigation BEGINS, not when the document commits, so the three predicates after it can run against the OUTGOING page. From about:blank that is a loud crash and harmless. The second boot() of a shoot reloads the SAME url, and there the stale document is the already booted app: every predicate passes against it, boot() returns while the reload is still in flight, and the ask frame can be a photograph of the list. A wrong picture that looks right is the one failure this script must not have, because nothing downstream can tell. It marks the document and waits for the mark to disappear; only a committed navigation clears a property set on the old one. child.stderr.resume() threw away the browser's own explanation and left a bare "chrome exited with 1". Two agents read that message and concluded no browser existed on this machine, when the discarded text named the sandbox and the fix was one flag -- this whole branch is the cost of that line. The last 4 KB of stderr is kept and printed with the exit code. Two alt texts described things the pictures do not show. list.webp's cited "117 rooms free, 39 shown", which is the #say live region: .sr is 1px and clip-path inset(50%), so no sighted reader can find it, and readme.test.mjs cannot catch it because it checks alt numbers against innerText, which includes screen-reader-only nodes. ask.webp's listed four duration buttons as peers when 2 hours is filled accent red in the frame, which is also the choice that makes the next screenshot read "You asked for 2h00." The header claimed the finder covers a Playwright Chromium; that splice is on the Linux branch only, and win32 and darwin return before it. Narrowed to what the code does. Re-ran the shooter after the race fix: all five frames and frames.json come back byte-identical to the committed ones, so the change is to the failure mode and not to the output. 731 tests, 727 pass, 0 fail. check-dead-code --strict: 84 files, no dead code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xiX95r6nnUUmhD3KwMnWM
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.
docs/mediahad drifted a release behind the app:list.webpandlist-full.webpstill showed the duration chip bar #95 deleted, androom.webpstill showed the on-map walk-time pill #94 removed. Twice the conclusion was that no browser was available in this environment. It was available, and the blocker was one launch argument.The diagnosis: one flag
Chromium is at
/opt/pw-browsers/chromium-1194/chrome-linux/chrome(Chromium 141).chromePaths()only searched/usr/bin/*and/snap/bin/chromium, soCHROME=was needed to get pastfindChrome()— and then the launch died withchrome exited with 1. That exit is Chromium's sandbox: it needs a non-root user to drop privileges to, refuses to start without one, and dies before it ever writesDevToolsActivePort. CI and container runs are root, so--no-sandboxis now added only whenprocess.getuid?.() === 0; on a normal desktop account the sandbox stays on.chromePaths()also learned the Playwright cache (PLAYWRIGHT_BROWSERS_PATH, then~/.cache/ms-playwright, newest build first), soCHROME=is no longer required here.node scripts/shoot.mjsand--checkboth run clean with no environment variables set.What was regenerated
All five frames in one run, not just the two stale ones, so the set is one moment of one app. Pinned clock (
2026-09-16T10:20 Eastern) and pinned position (Thompson Library steps) unchanged — the same photograph, of a newer app.The app prints different things now, so
frames.jsonand the README follow the pictures:· departmentallabel, so the top rows are Cunz Hall 160 and PAES A111 where they were Psychology Building 115 and University Hall 448ask.webpshows four buttons under "How long?", not three under "How long do you need?" — alt text that was already off the image before this changeThe README's worked example read the third row of the middle screenshot, which is no longer Psychology Building 217. It now reads the second row, PAES A111. Every number in that paragraph is measured: the row and the room screen both print free till 4:00pm, the room screen prints Yours for 5h36 once you get there (read off the app during the shoot, via the script's own probe output), and
PEA0111's Wednesday interval indata/rooms-1268.jsonstarts at minute 970 — 4:10pm — which is the ten minutes of packup the row takes off. The #77 sentence keeps its point without quoting the old room's number.How the images were verified
By opening each
.webpand looking at it, before and after, not by exit code:list.webp— before: a chip row30m / 1h / 2h / rest of daypinned under the list,2hlit red. After: no chip bar; the sheet header reads "You asked for 2h00." and the first row is Cunz Hall 160, 4 min.room.webp— before: a red-on-black "3 min walk" pill sitting on the dashed line mid-map, plus the chip bar. After: the dashed line and the lit footprint are there and the pill is gone; the selected row is lit in the list with its chevron.list-full.webp,timeline.webp,ask.webp— checked too: eight rooms in eight buildings 3–7 min out, the Cunz Hall 160 calendar with its two KNSISM blocks and the now-line at 10:20, and the four-button question screen.Bytes
+58,776 bytes, +8.3%. The frames are unchanged in size (1179x2556) and quality (WebP 95); the increase is content — the full-height list now carries eight taller rows, and the timeline frame shows a calendar with more drawn in it than the old one.
Checks
npm test— 731 tests, 727 pass, 0 fail, 4 skipped, matching the baseline on main. The readme test caught the drift first: it failed onlist.webp alt text says "25 seats" and the screen does notuntil the alt text was rewritten to the new picture.node scripts/check-dead-code.mjs --strict—84 files, no dead code.node scripts/shoot.mjs --check— clean, all five frames pass the blankness and stillness gates.Not done
sw.jsuntouched: noSHELL_CACHEre-stamp, noSHELL_ASSETSedit.npm test # node --test, 589 tests, no networkline is stale (it is 731 now). Left alone as unrelated to this change.--checkrun of the session threw once insideboot()— an evaluate againstabout:blankbefore the navigation landed — and has not reproduced across the four runs since. Not chased in this PR; it is a race inPage.navigate/waitFor, not the sandbox.🤖 Generated with Claude Code
https://claude.ai/code/session_017xiX95r6nnUUmhD3KwMnWM
Generated by Claude Code