Repository navigation
D: pin every directory above a nested gitlink during execute and fix (#99) - #104
Merged
Merged
Conversation
…99) The read-only tmpfs at a nested gitlink (#81) moved with its parent when the agent renamed that parent, so the old path could be refilled during the run. Each directory above a nested gitlink is now mounted again from the task's work volume at its own path (volume-subpath). A mountpoint cannot be renamed, so the gitlink's mount stays put; what is inside stays writable, nosuid and nodev, on the same volume and limits. checkTaskTree refuses more than 256 pinned directories or more than 128 KiB of mount paths. The validator derives the pins from the gitlinks and allows exactly those: the task's own work volume, writable, at that subpath. The probe checks each pin and that renaming it fails. plan-format.md no longer lists the exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Closes #99. Stacked on #100; base is
feat/d-gitlink-mounts-81. Retarget tomainafter #100 merges.What this does
#100 puts an empty read-only tmpfs at every gitlink for execute and fix. An agent could rename a parent of a nested gitlink: the mount moved with it, and the agent could then refill the old path during the run. Only the post-run inspection caught that.
Now every directory above a nested gitlink is pinned. The profile mounts the task's work volume again at that path:
A mountpoint cannot be renamed (EBUSY), so the gitlink's mount stays where it is. Inside a pinned directory, everything stays writable,
nosuidandnodev, on the same volume and limits.checkTaskTreerefuses more than 256 pinned directories, or more than 128 KiB of paths in the gitlink mounts. The second limit keeps thedocker createarguments bounded.validateContainerderives the pins from the gitlinks. It allows exactly those mounts: the task's own work volume, writable, at that subpath, with novolume-nocopy. It also refuses a subpath on/workitself.gitlink-writeprobe checks each pin from inside a real execute container: the pin is a mountpoint, it isrw,nosuid,nodev, renaming it fails, the gitlink is still there, and a file can be written inside the pin.rename(2)and hard links across a pin fail with EXDEV (mvcopies instead);volume-subpath;The spike results are in the #99 comment.
Review
Independent reviewer (fresh context). It found no way to move a gitlink mount or refill its path. It tested in real Docker with the production flags: renames of every parent level,
renameat2(RENAME_EXCHANGE),umount, user-namespace tricks (blocked byseccomp=builtin), and subpath escapes (refused by the daemon). It confirmed that Docker mounts parents before children whatever the argument order.Fixed:
touch && rmunderset -e, andrmdir, which a parent always refuses. The probe now writes, checks and removes as separate commands. The "removing fails" claim is gone from the docs. The probe also checksnosuidandnodevon each pin.volume-nocopypin, and a tmpfs in place of a pin, in addition to the missing, read-only and wrong-subpath cases.profile.gitlinkParents.rename(2), and the assumption that nothing writes between the check and the start.Declined:
DriverConfigandLabelson pins are not checked: the volume's own options are already checked throughdocker volume inspect.Lesson audit. These are covered by existing AGENTS.md rules: "Treat every behavioural claim … give it a test that fails if the claim is false" (probe and validator gaps), and "Pass text whose size follows user or agent input … the OS limits" (argument bound). No new rule is needed.
Evidence
npm run typecheckis clean.🤖 Generated with Claude Code