Two claims in docs/threat-model.md were false rather than loose. An escape would be a downgrade, and the account already holds more than the escape would grant: root on the VM is strictly more capability than a process inside a container with a trimmed capability set. Root on this VM is already a row in the blast radius table, which is the case the model is drawn around, and the hypervisor firewall bounds it identically however root was reached.
The escape section names what an escape reaches that the container did not, and it is not one thing. Every other project on the box becomes readable, and uncommitted work in those exists nowhere else. Beyond that, the model API credential: dejima keeps it out of the container deliberately, so a session can use the API while it runs and cannot carry the token away, and the proxy holding it runs on the devbox. That makes an escape onto the devbox the step that turns temporary use into a token someone keeps.
It is not the only loss that reaches past the machine, and no longer says so. Source and uncommitted work leave just as easily. What puts the credential first in the queue is that it is a standing capability rather than a copy of data, and that it sits at a known path under a known name, which makes it among the easiest things on the box to find.
That also corrects the rootless rejection, which claimed the set it would protect was close to empty. It is small but not empty, and the control covers neither half of it: the proxy runs as whichever account runs the session, and one account owns every project, so moving the session to a dedicated account moves the projects with it.
The threat model no longer rests on the adversary being unsophisticated. Real supply-chain malware fingerprints its environment, stages, beacons and can hand a session to a person, and a prompt injection borrows the agent as its adaptive component. What the model rests on instead is that every one of those moves needs egress, which the node firewall bounds whether the thing being bounded is a script or a person driving it. Being undirected changes what is likely, not what is possible.
One person's work per devbox is stated as a requirement of the threat model rather than an observation, and cross-project context poisoning is stated as handled in dejima, in the present tense.
Two things dejima states canonically and this repository did not carry.
The maturity disclaimer, in the same three places dejima pins it: README, SECURITY.md and the document that argues at length for security properties. Its own wording covers all three repositories by name - these projects, any of these repositories - so a reader landing here would not have seen it. Duplicated rather than linked, which is the opposite of what attribution and the security policy do, and deliberately: a disclaimer behind a link is a disclaimer the reader does not see, and its whole value is being on the page where the argument is being made.
test/disclaimer.bats pins it in all three. The line is the one most likely to be dropped without anyone deciding to drop it, by a rewrite of a section that happened to contain it, and every other test here would still pass on a repository that had lost it. It earned its place immediately: a git checkout during development reverted the README paragraph and the guard caught the commit that would have shipped without it.
The push rule goes in the credentials section, where it belongs: a session's forge is the one you chose, and everywhere else is where its dependencies live. Linked rather than restated, because the argument has a canonical home and a second copy of an argument is a second copy to keep right.
The README leads with what a devbox is and why it is a different problem from a CI runner: it holds uncommitted work, so it cannot be rolled back, and rollback is the entire containment story of the sister project. What this does not claim comes before what it does, because for a security tool an overstated claim is what turns a warranty disclaimer into an argument about misrepresentation.
CI runs on the CONFINED tier, not the privileged one the sister repository uses. Everything here is bats over shell, YAML and markdown; nothing needs a Docker socket or the host's network namespace, and asking for a runner that grants both would be taking a privilege for no reason in a repository whose subject is not doing that. The resolution diagnosis was rewritten to match: on this tier .dejima/allowed-domains is a possible cause, and it is named first because it is the one thing a change here can break.
The compose-schema and runner-env jobs are dropped. They assert on runner tiers this repository has no equivalent for.
The wordmark comment is copied verbatim, including the reasoning about Gitea's sanitizer stripping style attributes and why every space is a real U+00A0. Both files ship so a mirror on a light-themed host changes one line.