fix(agents): a codex agent starts in a workspace it has never seen - #152
Open
rogeriochaves wants to merge 2 commits into
Open
fix(agents): a codex agent starts in a workspace it has never seen#152rogeriochaves wants to merge 2 commits into
rogeriochaves wants to merge 2 commits into
Conversation
Codex asks about a directory the first time it starts in one, and waits on the answer before it draws anything at all. A headless agent has nobody to answer, so its very first launch in a fresh workspace sat on the question until a person opened the pane. The session was up, the agent was not. The answer is a `[projects."<path>"]` table in config.toml, which is what codex writes once the question is answered by hand. The launcher now records it before it starts the process, since a question asked on the way up is one nothing after the launch can answer. It grants codex nothing it does not already have here: agents launch with `--dangerously-bypass-approvals-and-sandbox`, so the sandbox the question guards is already off for them. A directory the operator has already ruled on is left alone, trusted or not: only one codex has no entry for gets one. The table is appended whole, so nothing above it is reread as belonging to it, and a marker-managed block keeps its shape. Claude asks nothing on its way up, so nothing is written for it. Claude-Session: https://claude.ai/code/session_01BUKKUiZbSBHmrLK9JJj4Ba
On a box, the launcher typed `/rename pr-reviewer` into a real codex, pressed Enter, reported the session named, and left the command sitting unrun in the composer of a live agent. Two faults, one after the other. The check read the pane straight after the Enter. A pane that has not drawn the command yet looks exactly like one that has already run it, so the very check meant to catch an unsubmitted command was what passed it. The composer is now read until the command shows up in it, before any Enter, and only then is its disappearance an answer. A runtime that never draws the keystrokes reports the session unnamed, which is what it is. The Enter itself is dropped by a codex still loading a resumed session. It is now repeated until the composer clears, up to four times. An Enter on a composer the runtime has since cleared does nothing, so a retry costs a keystroke and never a second command, and the command is typed exactly once however many Enters it takes. Removing the wait-for-drawn gate fails the new test with the box's own symptom, and nothing else. Claude-Session: https://claude.ai/code/session_01BUKKUiZbSBHmrLK9JJj4Ba
rogeriochaves
force-pushed
the
fix/codex-directory-trust
branch
from
August 25, 2026 05:05
a49ecaf to
4fbeb39
Compare
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.
What
Codex asks about a directory the first time it starts in one, and waits on the answer before it draws anything:
A headless agent has nobody to answer. So the very first launch in a fresh workspace sat there until a person opened the pane: the tmux session was up, the agent was not, and #151 correctly declined to name a session it could not reach.
The answer, written before the process starts
The answer codex records by hand is a
[projects."<path>"]table inconfig.toml. The launcher now writes it up front, through a newprepareWorkspaceentry in the runtime table. Before the process starts, not after: a question asked on the way up is one nothing after the launch can answer.It grants codex nothing it does not already have here. Agents launch with
--dangerously-bypass-approvals-and-sandbox, so the sandbox this question guards is already off for them.Claude asks nothing on its way up, so nothing is written for it.
What it will not do
Checked end to end
A real codex, launched through
ensureAgentSessioninto a directory it had never seen:No question, and the name from #151 lands on the first launch instead of the second.
Tests
Six, covering the two scenarios added to
specs/sessions/headless-reconcile.feature:Gate: 338 tests pass,
tsc --noEmitclean.Second commit: reading the composer before deciding a name was taken
Deploying #151 to the agents box found a real fault in it. The launcher typed
/rename pr-reviewerinto a live codex, pressed Enter, reported the session named, and left the command sitting unrun in the composer of a running agent:Two faults, one after the other.
The check read the pane straight after the Enter. A pane that has not drawn the command yet looks exactly like one that has already run it, so the very check meant to catch an unsubmitted command was what passed it. The composer is now read until the command shows up in it, before any Enter, and only then is its disappearance an answer. A runtime that never draws the keystrokes reports the session unnamed, which is what it is.
The Enter itself was dropped. A codex still loading a resumed session swallows it with no sign. It is now repeated until the composer clears, up to four times. An Enter on a composer the runtime has since cleared does nothing, so a retry costs a keystroke and never a second command, and the command is typed exactly once however many Enters it takes.
Removing the wait-for-drawn gate fails the new test with the box's own symptom, and nothing else.
Checked on the box
Same branch built and deployed there, then the codex agent relaunched through
kanban reconcilewith no hand-holding:Codex's index gained the entry on its own, and the composer is clear.
Four more tests: waits for its own keystrokes to be drawn, presses Enter again for a runtime that dropped the first, gives up rather than pressing Enter forever, and never types the command twice. 341 tests pass,
tsc --noEmitclean.