Repository navigation
Its owner gets a folder set aside back beside the work, or drops it - #1016
futurepaul wants to merge 4 commits into
Conversation
A folder a start set aside (it did not fit) was kept and told, with no
way out. Now its owner can get it back: woken if it sleeps, its archive
is restored beside the live work, in a folder of its own named for what
it was, the day it was saved and its save's number
(/data/work/restored-work-2026-11-03-594), so nothing live is replaced;
then it is aside no more and its archive is deleted, its files in /data
for the next save to keep. One that does not fit yet stays aside (409),
saying so. Or they drop it, its archive deleted.
POST /api/computers/{id}/aside/{record}/back answers {back, view};
DELETE /api/computers/{id}/aside/{record} the view. The set_aside
notice's row gains Get it back and Delete it (each folder named when
there are several), their words beside the notice's.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
futurepaul
left a comment
There was a problem hiding this comment.
Codex review @ cf90904: CHANGES
-
[P1] Do not replace an existing get-back destination —
cell/src/computer.rs:1357–1361.back_dirdeterministically choosesrestored-work-<date>-<save>, but nothing checks or reserves that destination before passing it toDirectoryBackup.restore. The pinned SDK explicitly replaces an existing target directory. A person can already have files at that path; also, if an earlier restore swapped successfully but its response/DO was lost, the archive remains aside and retrying replaces any edits made in the recovered folder. Choose/reserve a fresh destination and publish without replacing an existing directory (or refuse a collision), keeping the archive on conflict. Cover a populated destination and retry after a completed swap with lost acknowledgement. -
[P1] Keep the archive until the recovered files have a durable save —
cell/src/computer.rs:1367–1373. After the SDK writes the folder onto the running container, the handler immediately removes its Aside record and deletes its archive, without taking or verifying a save containing that folder. All currently kept saves therefore still omit the recovered data. A container crash before the next save—potentially while the get-back request is still inforget/tell_owner—loses the restored files and the only archive that could recover them. Retain the source record/archive until a successful save of the same running generation includes the recovered destination; a failed save, crash or interrupted get-back must leave it recoverable. Add a deterministic crash/save-failure case around that boundary.
Reviewed only the diff above #1007. Both routes enforce person identity and ownership; explicit full/unusable/throwing restore failures return before releasing the archive. All 56 core computer tests and 3 shell aside tests passed; no Docker or e2e run. The current tests cover successful return/drop but not the two loss scenarios above.
…a save holds it Codex on #1016 found two ways to lose data. A folder coming back went to a name it never checked, and the SDK's restore replaces what is there: a person's own folder at that name, or, on a retry after a move whose answer was lost, the edits made in the recovered folder since. And its archive was deleted before any save held the recovered files: a crash before the next save lost both. Now it comes back into a folder nothing was at (back_dirs: its name, else -2 to -8), reserved before anything moves, so a retry in the same life goes where its first try went. It is restored into a stage beside it, marked with its record (.fragment-back), and moved into place with mv -n -T, which moves nothing onto a folder there; a try that finds its own marked folder there takes it as back, one that finds another's is refused (409) and reserves afresh next time. And it stays aside, its archive kept, until a save of that same life begun after it came back worked (Aside::saved); a crash or a failed save before then loses nothing, and its next life tells its owner of it again. Tests: the core's reservation, retry, save gate, crash and drop; the computers lane past a person's folder at its name, an answer lost (the lever lose-back-ack) and retried with edits kept, a crash with its saves failing (kill, fail-saves) and it back again, a save releasing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ogether Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…at the crash cut Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
futurepaul
left a comment
There was a problem hiding this comment.
Codex review @ acffb09: PASS
Reviewed this PR's own changes on #1007, including the fixes since cf90904: persisted destination reservations, the non-overwriting final move, marked retries after a lost acknowledgement, and archive retention until a successful save of the same life begun after recovery. Both previous blockers are addressed; the new optional stored fields remain backward-readable, owner routing is unchanged, and lose-back-ack is behind the existing test-fleet guard. Validation: 56 core computer tests, the aside UI test, and a local filesystem probe for destination collisions and preserved edits passed; Docker/e2e were not run.
|
Local proof on |
Stacked on #1007. A folder a start set aside (it didn't fit on the disk) was kept and told, but its owner had no way to get it back or remove it.
The change
POST /api/computers/{id}/aside/{record}/back→{back, view}./data/work/restored-<work|files>-<YYYY-MM-DD>-<save>(back_dir), so nothing live is replaced and two never meet.Aside::release, thenSaves::let_goand the forget pass, both rows in one step). Its files are in/datanow, and the next save keeps them.DELETE /api/computers/{id}/aside/{record}→ the view. The folder leaves and its archive is deleted. None aside by that id is 404.set_asiderow gains Get it back and Delete it, each naming its folder when several are aside, with a confirm before delete. The words sit beside the notice's incell/shell/computer.js.entry.mjs'srestoretakes an optional target directory.docs/api.md(both routes) anddocs/computers.md.Tests
a_folder_aside_comes_back_beside_the_work_or_is_dropped:back_dir's names: two folders never meet, a work folder versus its own files;node --test).ASIDE_OUT_CHECKS:aside_checksset aside comes back, and the agent readswork/restored-work-…/aside.txtthere;cargo xtask checkexit 0, andcargo 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'sbc9e302d9plus this commit).🤖 Generated with Claude Code