Skip to content

fix(computers): a disk form's console shows the session's programs again, so releases publish - #666

Merged
earakely-scale merged 4 commits into
mainfrom
edgararakelyan/disk-console-shows-session
Nov 13, 2026
Merged

earakely-scale merged 4 commits into
mainfrom
edgararakelyan/disk-console-shows-session

Conversation

@earakely-scale

@earakely-scale earakely-scale commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

What changes

Every release since v0.9.1522 has failed to publish at the same step: the disk form agentenv-ubuntu-24.04-disk's "Check that it boots" timed out after 900 s on GitHub's arm64 runner, and the amd64 job was cancelled with it. Nothing has reached PyPI since 0.9.1521.

The guest boots fine. The check couldn't see it:

The fix:

  • root.conf sends the session's supervisord's output to the console (stdout_logfile=/dev/stdout), as when it was the first process. Nothing read session.log.
  • The disk's init makes the four standard links before it starts the computer, as a container runtime would. A shell's <(...) in the guest gets /dev/fd too.
  • The boot check (infra_build.py _boots) waits for root's programs as well as the session's.
  • A unit test pins root.conf's console logging and the init's /dev/stdout link to what the check reads.

The slow tier's disk race (folded in from #668)

This PR changes the disk, so CI builds it fresh, and its integration-local-slow (3/12) failed twice on a race that also fails main now and then (eac7660, and #580's merge): launcher_test.py's three tests, KeyError: 'image'.

  • Why: a slow shard's two pytest workers both compose the shared desktop. When its disk's key is new, neither finds it stored, so both build it under localhost:5000/agentenv-computers:<key> with different bytes. The second moves the tag off the image the first pinned by digest, and the first's boot (--mount type=image, which Docker doesn't pull for) fails with "No such image". On the rerun, their two pushes of the tag collided instead (the registry answered 500).
  • The composer: a Linux disk is now looked up, made and pushed holding a lock of its key (linux-disk:<key>), as Windows and Omarchy disks already are, so a second compose of it waits and reuses the first's. A unit test checks each arch's disk is looked up, made and pushed holding it, and fails without the change.
  • The integration tier: agent-env keeps its locks in the state root, and each integration test has one of its own, so the composer's lock alone didn't span the two workers. A new tst/integration/conftest.py keeps the locks that guard this machine's Docker and registry (composes, disks, disk exports, image builds, pulls and saves) in one folder for the run, as one user's processes share theirs. Two processes with separate state roots then take turns on linux-disk:<key>, which I checked locally.
  • Docker itself is consistent: on a Docker 28 daemon on the containerd image store, docker image inspect and --mount type=image agree on a pinned name every time; once the tag moves to a rebuilt image, the first image's pinned name is gone for both.

Testing

On an agent-environments-admin Graviton host with no KVM, so arm64 under TCG as on GitHub's arm64 runner. I took the base image v0.9.1529 published (agentenv-ubuntu-24.04:src-f3e72c92…-arm64) with only this branch's root.conf swapped in, built its disk with this branch's recipe, and ran the release's own check (infra_build.py smoke agentenv-ubuntu-24.04-disk … --launcher …):

Disk Result
root.conf fix alone (d2331f7) the console still showed only clock, egress and session: the guest had no /dev/stdout
Both fixes (05d4f08) "booted to its desktop under TCG" in 2½ minutes, all six programs running

Unit: test_infra_build_script.py (63) plus the base's clock, egress and shipped-computer tests pass.

The amd64 disk wasn't booted separately: it takes the same init and root.conf, under KVM on the x64 runner.

After merge

The next tag publishes the new base and disk images and everything since 0.9.1521 to PyPI; the bot then opens the pin bump.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no actionable new issues were found.

Summary

Restores session startup messages on disk consoles and makes the boot check wait for both supervisors' programs.

  • Disk boot checks now see starts from both supervisors.
  • Linux disk builds wait their turn when keys match.

No actionable new issues were found. Tests were inspected, not run.

Reviews (4) · Last reviewed commit: "test: the integration tier's workers sha..." · Reviewed by Greptile

earakely-scale and others added 2 commits November 13, 2026 09:30
…so a disk form's boot check sees its desktop

Since #649 root's supervisord runs the session's supervisord as a program, and wrote its output to a root-only file.
A disk form's console then showed root's programs alone (clock, egress, session), so the release's boot check, which
waits on the console for every program supervisord.conf declares, timed out after 900 s on every tag since
v0.9.1522, though nothing failed to start.

- root.conf sends the session's supervisord's output to root's stdout, the console, as when it was the computer's first
  process.
- The boot check waits for root's programs as well as the session's.
- A unit test pins the session program's console logging to what the check reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… output reaches its console

The disk's init mounted devtmpfs, which has no /dev/fd, /dev/stdin, /dev/stdout or /dev/stderr: a container runtime
or udev makes those links. Root's supervisord then wrote the session's output to a plain file named /dev/stdout
instead of the console. The init makes the four links before it starts the computer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale and others added 2 commits November 13, 2026 10:56
…s, so a boot's pinned disk stays put

Two composes of the same new disk key on one machine (the slow tier's two pytest workers, each composing the shared
desktop) both found nothing stored and both built it. Each build tags localhost:5000/agentenv-computers:<key> and its
bytes differ, so the second moved the tag off the image the first had pinned by digest. The first's probe then
mounted name:tag@digest with --mount type=image, which Docker doesn't pull for, and failed with "No such image",
failing launcher_test's three tests with KeyError: 'image' on every run that built the disk rather than copied it from
the mirror (eac7660 and d1fcdf8 on main, and PRs that change the computer images).

The Linux disk is now looked up, made and pushed holding a lock of its key, as Windows and Omarchy disks are, so the
second compose waits and reuses the first's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…machine's Docker and registry

agent-env keeps its locks in the state root, and each integration test has a state root of its own, so the disk lock
alone didn't stop two pytest workers composing one computer at once: on this PR, both still built the desktop's disk
under the same tag and the first's boot failed as before. A session fixture keeps the locks whose ids name this
machine's image work (composes, disks, disk exports, image builds, pulls and saves) in one folder for the run, as one
user's processes share theirs, so such work takes turns across workers and the second reuses what the first pushed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale added a commit that referenced this pull request Nov 13, 2026
…against one-after-another asks

On CodeBuild (#666's Integration Tests), test_the_drivers_readiness_asks_every_apps_server_at_once took 3.15 s with
2.5 s allowed: its clock started before it built the fake driver's client, and three 1 s app checks asked at once left
only 1.5 s for that on a busy machine. The driver does ask them at once (runtime.ready_checks gathers them). The clock
now starts at the request, and each app's check takes 2 s, so asked at once the status takes about 2 s, one after
another 6 s, and the bound is 4 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale added a commit that referenced this pull request Nov 13, 2026
…hout the click-repaint timing, and its probe test names what failed

The scripted drive's click-repaint assertion failed on 5 commits, main included, two ways: the first recorded frame
showing the clicked cell came 37 ms past the frame allowed, and on #666 no recorded frame showed the change at all.
Both come down to when the recorder writes a frame under load. The test still checks each screenshot against the
recording's nearest frame, in time and in pixels, which is what puts the two on one clock.

The probe test failed on #666 with "scored below 1 (probe: 0)" and nothing more; it now names each probe check that
failed and why, from the run's verification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale merged commit 6c9c28f into main Nov 13, 2026
61 of 63 checks passed
@earakely-scale
earakely-scale deleted the edgararakelyan/disk-console-shows-session branch November 13, 2026 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant