Skip to content

feat(computer): a versioned disk boot seed, and a reset an older launcher can't misread - #476

Merged
earakely-scale merged 3 commits into
mainfrom
edgararakelyan/fd-5170-disk-boot-protocol-version-the-launcher-guest-seed-and-the
Nov 4, 2026
Merged

earakely-scale merged 3 commits into
mainfrom
edgararakelyan/fd-5170-disk-boot-protocol-version-the-launcher-guest-seed-and-the

Conversation

@earakely-scale

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

Copy link
Copy Markdown
Collaborator

FD-5170: a computer's disk composed by one agent-env version gets booted by later ones. composer.pending reuses any build recorded as ready, and disks shared through registries or HF bundles are booted by whatever version the user runs. Two contracts crossed versions with no version number: the seed the launcher hands the disk's init, and launch reset. This makes both safe across versions, with the three decisions taken in FD-5170's review. Diagrams: Disk Boot Protocol.

What changes

  • The seed is a protocol (D1 (b)): agentenv_protocol.computer.seed defines it.
    • It holds the CIDATA label, the #agentenv-environment header, the file each version goes in, the oldest-version file agentenv-seed-oldest, a reference writer and reader for version 1, and a SAMPLE / SAMPLE_USER_DATA pair that both sides are tested against.
    • Version 1 is today's format, byte for byte.
  • The launcher writes every version it supports.
    • seed writes user-data (v1, unchanged) and agentenv-seed-oldest = 1 into its own folder, with lines sorted in byte order (LC_ALL=C) so they match the spec.
    • launch copies that whole folder onto the CIDATA disk.
    • A later version N goes in user-data.vN beside the earlier ones.
  • The disk's init reads the newest version it knows.
    • Its seed reader moved to boot/seed-env, which init sources and uki.sh puts in the initramfs.
    • It reads the newest version it knows that the seed carries. If the seed carries none of them, it stops the boot with agentenv-init: this disk reads seed v1; this agent-env writes v2 or later; recompose it with agent-env env build.
    • A seed without the oldest-version file, from a launcher before this PR, counts as version 1.
    • There are no image labels, record stamps or composer.pending changes. Only the init knows what it reads, since a composed disk takes its init from its base disk's boot partition.
  • Reset is guarded (D2 (a)): RESET is sh -c '[ -d /var/lib/agentenv-vm/control ] || exit 75; exec /usr/local/bin/launch reset'.
    • A launcher from before feat(computer): the disk form on Modal VM sandboxes #468 has no control folder, and would take launch reset for a second boot. Its QEMU then fails to bind the forwarded ports, and the computer is left unreset.
    • On local Docker, exit 75 raises "the computer in container … was booted by an older agent-env, whose launcher can't reset it in place; redeploy it".
    • Modal never ran a launcher that old, so it needs no mapping.
    • local_docker/cli.py's docker() now raises DockerFailed, which carries the exit code.
  • Not here (D3 (b)): surfacing a failed boot's console is FD-5171. Until then, the stopped-boot line shows in the computer's console only, and the user sees a readiness timeout.
  • Docs: the protocol README gains "A disk's boot seed", and computers/README.md gains the seed versions and the reset refusal.

Changing boot/ changes the disk recipe's digest. So new composes, and the next release's published base disks, get new keys. Disks already composed are untouched, and they keep booting: see X1 below.

Tests

  • Unit:
    • the launcher's seed output and seed-env's reader, each checked byte for byte against the protocol's sample;
    • seed-env with an older launcher's seed, a newer launcher's seed (user-data.v2 beside v1), a seed past its versions (refused with the line above), and no user-data;
    • RESET exiting 75 for real on a host without the control folder;
    • local Docker's reset_vm refusal, and other failures passing through;
    • Modal's reset command;
    • the launcher Dockerfile's ENTRYPOINT equalling LAUNCH, and its COPY;
    • the protocol package's sample tests.
  • On a fresh agent-environments-admin EC2 VM (c8i.4xlarge, nested KVM):
    • ruff check passed;
    • make unit-test: 12,905 passed, 7 skipped;
    • launcher_test.py and disk_boot_test.py: 2 passed.
  • Across versions, on the same VM: main at 0.9.1431 and this branch, each disk booted through the other's provider and launcher, probed at full, reset in place, ready again, and probed:
Disk Launcher Result
X1 main's (old init), key b6c144d5… this branch's (writes agentenv-seed-oldest) 53 passed, 1 n/a; reset; 53 passed; the card's name read from the seed
X2 this branch's (new init), key bbf366c3… main's (no oldest-version file) 53 passed, 1 n/a; reset; 53 passed; the card's name read from the seed
X3 this branch's a launcher whose seed says only v2 is written the guest printed agentenv-init: this disk reads seed v1; this agent-env writes v2 or later; recompose it with agent-env env build and powered down 2 s into boot
  • The same branch also passed agent-env run tst/integration/computer/disk --task probe (probe, reset in 6.6 s, probe) on its own disk.

Not in this PR

  • Surfacing a failed boot's console (FD-5171).
  • Dropping seed version 1, which waits for every disk without this init to be gone: those composed by 0.9.1422 to 0.9.1431 stop no boot.
  • A protocol file for reset, until reset's own format first changes.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the previous variable-name collision is fixed, and no new blocking issue was found.

Summary

This PR defines a versioned disk boot seed and guards reset commands against older launchers.

  • Disk boot seeds now tell init which formats they carry.
  • Disk resets now check whether the launcher supports resetting in place.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Launcher writes seed files] --> B[Disk selects a supported version]
    B -->|Supported| C[Read values in a subshell]
    C --> D[Check names and quote values]
    D --> E[Apply exports in init]
    B -->|Too new| F[Stop boot with recompose message]
    G[Provider requests reset] --> H{Control folder exists?}
    H -->|Yes| I[Run launch reset]
    H -->|No| J[Refuse reset and request redeploy]
Loading

Reviews (3) · Last reviewed commit: "fix(computer): the seed reader shares no..." · Reviewed by Greptile

…cher can't misread

A disk composed by one agent-env version boots under another's launcher, so the NoCloud seed becomes a protocol,
agentenv_protocol.computer.seed: the launcher writes every version it supports (user-data is version 1, unchanged; a
later version N goes in user-data.vN) and the oldest it writes in agentenv-seed-oldest. The disk's init reads the
newest version it knows, from boot/seed-env, which it now sources, and stops the boot, saying to recompose the disk,
when the seed carries none of them. reset_vm's command first checks for the launcher's control folder, so a container
an agent-env from before reset in place started is refused a reset, to be redeployed, rather than booted twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale requested a review from a team as a code owner November 4, 2026 04:51
…es to itself

init sources seed-env before it exports the image's environment, so an image variable named reads replaced the
versions it reads and skipped the seed, and one named file, name or the like was overwritten. Its variables are now
local and prefixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he seed

Local variables kept the image's variables safe, but a seed variable named like one of them (_seed_reads) was exported
into the local and lost on return. The reader now works in a subshell and hands back only exports, each name checked
and each value quoted, which seed_environment evaluates. The tests export the image's variables after sourcing the
reader, as init does, and name seed variables after the reader's own; both fail on each earlier reader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale merged commit b679ef5 into main Nov 4, 2026
25 checks passed
@earakely-scale
earakely-scale deleted the edgararakelyan/fd-5170-disk-boot-protocol-version-the-launcher-guest-seed-and-the branch November 4, 2026 06:26
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