Skip to content

A computer's disk is read after each start and save, and its owner told as it fills - #1015

Open
futurepaul wants to merge 3 commits into
claude/restore-sets-aside-what-wont-fitfrom
claude/computer-disk-told
Open

futurepaul wants to merge 3 commits into
claude/restore-sets-aside-what-wont-fitfrom
claude/computer-disk-told

Conversation

@futurepaul

@futurepaul futurepaul commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #1007. A production computer whose disk filled could not start again, and nothing told its owner it was filling.

The change

  • The cell reads its container's disk with one exec, df -P -B1 / (DISK_READ, best effort, 5 s), after each start comes up and after each save.
    • It keeps the last read in its saves (ComputerDisk {total, free, at}). That's a cache: a release from before it drops the value, and the next read restores it.
    • The restored and saved log lines carry {total, free}.
    • disk_of_df parses both GNU's output (the Hermes image) and BusyBox's (the stub).
  • A new notice, disk_filling {total, free} (add-only), tells the owner the room left once a read finds the disk used past 80% (DISK_TOLD_USED_PCT) and at most 5 GB free (DISK_TOLD_FREE_MAX).
    • On a computer's own 20 GB disk that's 4 GB left.
    • The 5 GB condition is there so the dev and CI fleets' computers, which share a terabyte host disk, aren't told of room they have plenty of.
  • The shell's words, Paul's, in one line, in cell/shell/computer.js (diskSaid): "Your computer is almost full (3.2 GB left). Delete files you don't need, or ask an agent to tidy up." The number is the real free space the notice carries, in GB, or in MB under a GB.
  • Kept small for the Wasm budget: no view field (the notice carries what it needs, the log lines the rest) and no test lever.

Tests

  • Core:
    • a_disk_is_read_from_df: GNU and BusyBox output, and every malformed case;
    • a_disk_filling_is_told_until_a_read_finds_room: the 80% and 5 GB edges, a shared host disk, order and replay, a read with more free than its size refused, and saves stored before it;
    • the simulation checks every disk_filling it tells.
  • Shell: cell/shell-tests/computer-disk.test.mjs (node --test) checks the words exactly, in GB and in MB.
  • e2e computers lane, DISK_CHECKS: the real disk is read as a start comes up, and read again, newer, after a save. The saves lever shows the reading, and each read is judged by what made it, never a fixed wait.
  • Commands run: cargo xtask check exit 0, and cargo xtask e2e --only computers: 284 passed, 0 failed, both on this head (A folder that will not fit is set aside, never a computer that will not start #1007's bc9e302d9 plus this commit).
  • Wasm: 6,479,786 bytes, +14,007 against A folder that will not fit is set aside, never a computer that will not start #1007's 6,465,779. That's down from +19,417 before the view field and the lever went. It fits the 6.6 MB budget of The cell's Wasm budget is 6.6 MB #1013.

🤖 Generated with Claude Code

…ld as it fills

A computer whose disk filled could not start again, and nothing told its
owner it was filling. Now the cell reads its container's disk (df -P -B1
/, one exec, best effort) after each start comes up and after each save:
the restored and saved log lines carry {total, free}, its saves keep the
last read, and a new notice, disk_filling {total, free} (add-only),
tells its owner the room left once a read finds it used past 80% with at
most 5 GB free (a computer's own 20 GB disk at 4 GB; a dev box's or CI's
shared disk is not told of room it has plenty of). Its words live beside
the set-aside ones in cell/shell/computer.js.

Kept small for the Wasm budget: no view field (the notice carries what
it needs, the log lines the rest) and no test lever; the computers lane
reads the real disk as a start comes up and after a save, and the core's
and shell's tests prove when it is told.

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

@futurepaul futurepaul left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex review @ 6da69fa: CHANGES

  1. Keep best-effort disk reads outside the start-success deadline — cell/src/computer.rs:1152. try_start has succeeded, but Event::Ready is not returned until the new five-second read_disk await completes. The lifecycle remains Starting meanwhile, and its deadline alarm can mark it failed. For example, a restore/check/gate completed at 899 seconds previously succeeded; a timed-out df now lets the 900-second alarm fire, and the later Ready is ignored in Asleep. The current restore budget already allocates all 900 seconds and neither it nor the timing assertions includes DISK_READ_MS. A deterministic lifecycle probe reproduces the failed transition. Apply successful readiness before awaiting telemetry, or explicitly budget/skip the read so it cannot push success past the deadline; cover this ordering without sleeps and update affected timing guards.

  2. Add a separate clearing threshold to prevent notice flapping — crates/core/src/computer.rs:2017 and :2254. The notice uses the same instantaneous threshold to appear and disappear. On a 20 GB disk, consecutive readings of 3,999,995,904 and 4,000,004,096 free bytes alternate the notice on/off; the same issue exists around the 5 GB cutoff on larger disks. I reproduced [true, false, true, false] through Saves::measured and notices. Ordinary temporary-file/cache changes can therefore repeatedly remove and re-add the warning. Keep the warning latched until a clearly higher free-space/lower-used threshold is reached, with compatible persisted state and tests that oscillate around both boundaries.

Reviewed only this PR's diff above #1007. Ordinary exec/parse/storage failures are swallowed as intended, and older Saves JSON defaults the disk cache to absent. Validation: 57 core computer tests, 5 proto computer tests, and both shell disk tests passed; the additional deterministic probes exposed the cases above. No Docker or e2e run.

futurepaul and others added 2 commits November 3, 2026 10:24
"Your computer is almost full (3.2 GB left). Delete files you don't
need, or ask an agent to tidy up.", the number its real free space as
the notice carries it. One line, as the updating notice is; its test
holds the words exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex on #1015: the disk read sat between a start's restore and its
Ready, so a restore that ended near the deadline plus a slow df could
let the deadline fail the start, its late Ready ignored. The read now
comes after the event is applied (reads_disk_after): once a start's
Ready made it awake, or an awake save worked; never a sleep's save,
whose stop follows. It logs a disk line of its own.

And the notice flapped: one threshold showed and cleared it, so reads a
few KB apart at the edge told and untold it in turn. It now latches
(Saves' disk_told, a cache like the read): told at 80% used with at
most 5 GB free, cleared only at 70% used or 6 GB free. Tested around
both edges, a computer's disk and a host's shared one; the lane reads
the disk once a start is ready, after an awake save, and at the next
start.

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

@futurepaul futurepaul left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex review @ 089e586: PASS

The disk read now follows application of Ready/Saved and their actions, so it no longer holds a successful start in Starting or delays a sleep's save. The persisted defaulted latch has distinct set/clear thresholds, covers oscillation at both boundaries, and preserves stale-read rejection; Paul's wording is reflected in the shell tests. All 58 core computer tests, 5 proto computer tests, and both shell disk tests passed; no Docker or e2e run.

@futurepaul

Copy link
Copy Markdown
Collaborator Author

Local proof on 089e586c0: cargo xtask check exit 0; cargo xtask e2e --only computers — 285 passed, 0 failed, 1 skipped (the hosted lane's). Wasm 6,481,078 bytes, +15,299 against #1007's 6,465,779 (within #1013's 6.6 MB).

This branch has not been deployed

No deployments
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