codex/opencode: keep looking for the conversation id, not just for 45s - #18
Open
lvwerra wants to merge 1 commit into
Open
codex/opencode: keep looking for the conversation id, not just for 45s#18lvwerra wants to merge 1 commit into
lvwerra wants to merge 1 commit into
Conversation
A codex session that came back from a Space restart with its history gone (agent-manager-2 on the live Space) had no `codexSessionId` pin at all, so it launched `codex resume --last` and got a blank conversation. The pin was missing because capture gave up too early. Codex writes NOTHING identifying to disk until the first message is submitted: measured on 0.146, an idle TUI produced no rollout file for 60s+, and one appeared within 3s of pressing enter. Capture polled at +5s/+15s/+45s and then stopped forever, so it only ever pinned sessions whose first message arrived inside that window. The Space's own history shows the split cleanly — every codex session whose rollout appeared within 11s of creation is pinned; every one that took 16s or longer (agent-manager-2 at 81s, my-assistant at 107s) is not. Once unpinned, nothing retried, and the next launch fell through to `codex resume --last`. That resolves through codex's own thread index — state_5.sqlite under $CODEX_HOME, which lives on local disk and is wiped by every restart, then rebuilt from the rollouts at boot. This boot it rebuilt 17 of 18, missing exactly the agent-manager conversation, with its backfill cursor stranded on the previous file. No index row for that cwd means `resume --last` starts a FRESH thread and exits 0, so `|| exec codex` can't even notice: the pane returns looking new. (A pin, by contrast, works with no index at all — `codex resume <id>` restored the full conversation from a CODEX_HOME holding only that rollout file.) So keep looking for as long as the pane lives: the same opening ladder, then a steady 60s beat, ending when the pin lands or the session is gone. opencode gets the same treatment through a shared pollForPin — its ses_ row also only appears once the conversation has content, which its old 90s ceiling had the same problem with. Claude is untouched: it gets an id up front via --session-id, so its capture is only verifying a pin we already asked for. Exercised against a live pane (isolated DATA_DIR + CODEX_HOME): a session left idle 75s before its first message — dead ground under the old ladder — got its rollout at t≈80s and was pinned on the following beat, and relaunching it brought the conversation back. An unpinned session abandoned at 20s stayed unpinned across two beats after a fresh matching rollout appeared in its folder, so an outlived loop can't hijack a later conversation. Co-Authored-By: Claude Opus 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.
A codex session that came back from a Space restart with its history gone (agent-manager-2 on the live Space) had no
codexSessionIdpin at all, so it launchedcodex resume --lastand got a blank conversation.The pin was missing because capture gave up too early. Codex writes NOTHING identifying to disk until the first message is submitted: measured on 0.146, an idle TUI produced no rollout file for 60s+, and one appeared within 3s of pressing enter. Capture polled at +5s/+15s/+45s and then stopped forever, so it only ever pinned sessions whose first message arrived inside that window. The Space's own history shows the split cleanly — every codex session whose rollout appeared within 11s of creation is pinned; every one that took 16s or longer (agent-manager-2 at 81s, my-assistant at 107s) is not.
Once unpinned, nothing retried, and the next launch fell through to
codex resume --last. That resolves through codex's own thread index — state_5.sqlite under $CODEX_HOME, which lives on local disk and is wiped by every restart, then rebuilt from the rollouts at boot. This boot it rebuilt 17 of 18, missing exactly the agent-manager conversation, with its backfill cursor stranded on the previous file. No index row for that cwd meansresume --laststarts a FRESH thread and exits 0, so|| exec codexcan't even notice: the pane returns looking new. (A pin, by contrast, works with no index at all —codex resume <id>restored the full conversation from a CODEX_HOME holding only that rollout file.)So keep looking for as long as the pane lives: the same opening ladder, then a steady 60s beat, ending when the pin lands or the session is gone. opencode gets the same treatment through a shared pollForPin — its ses_ row also only appears once the conversation has content, which its old 90s ceiling had the same problem with. Claude is untouched: it gets an id up front via --session-id, so its capture is only verifying a pin we already asked for.
Exercised against a live pane (isolated DATA_DIR + CODEX_HOME): a session left idle 75s before its first message — dead ground under the old ladder — got its rollout at t≈80s and was pinned on the following beat, and relaunching it brought the conversation back. An unpinned session abandoned at 20s stayed unpinned across two beats after a fresh matching rollout appeared in its folder, so an outlived loop can't hijack a later conversation.