openai / openai/codex

migrate-rollouts leaves persisted subagent threads with empty projected history

Open
#38,762 11 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

app-server bug CLI session subagent
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

What version of Codex CLI is running?

codex-cli 0.148.0-alpha.9. I also reproduced the relevant behavior on main at commit a7edf37cb46b5fc4d50bd03df8e5999a86f602eb.

What subscription do you have?

Not applicable. This happens during an offline local-store migration.

Which model were you using?

No model call is involved.

What platform is your computer?

macOS arm64.

What terminal emulator and version are you using (if applicable)?

Not relevant to the reproduction.

Codex doctor report

Not attached. I can reproduce this with a synthetic rollout fixture, and a doctor report would include unrelated local-state information.

What issue are you seeing?

After migrating a persisted legacy subagent, its raw rollout can still contain history while thread/read and resume surfaces show an empty thread.

For a migrated subagent, the migration currently writes subagent_history_start_ordinal equal to expected_ordinal, which is the end of the rewritten rollout. Projection then hides every record below that boundary. Since no existing record is at or beyond the end-of-file boundary, none of the migrated history is exposed as thread turns or items.

This is easy to notice with a named or otherwise persisted delegation thread that is still visible in thread/list: the thread exists and its rollout is non-empty, but opening it shows no previous turns.

What steps can reproduce the bug?

I used an isolated temporary Codex home and a synthetic legacy subagent:

All identifiers, names, timestamps, and rollout contents below are synthetic.

  1. Create a legacy rollout with SessionSource::SubAgent, a compacted checkpoint, and one child-local user/assistant turn.
  2. Make the thread persisted and visible to thread/list.
  3. Run codex migrate-rollouts --apply --thread 00000000-0000-7000-8000-000000000002 against the temporary home.
  4. Inspect the migrated session metadata, then read or resume the thread through the app-server.

The migrated metadata has subagent_history_start_ordinal == number of rollout lines. The retained rollout is non-empty, but the projected thread has no active turns.

What is the expected behavior?

Migration should keep inherited or bootstrap context hidden where necessary, while preserving the subagent's own displayable turns for thread/read and thread/resume.

The boundary should point to the first displayable child-local record instead of always pointing to the end of the rewritten file. If ephemeral workers and persisted user-facing subagents intentionally need different behavior, the migration should distinguish those cases.

Additional information

I traced the behavior to these paths:

That test makes the migration-layer behavior clear, but I am not sure it captures the expected app-server behavior for a persisted thread that a user can reopen. A focused regression test could migrate a named synthetic subagent, exercise thread/read or thread/resume, and verify that its child-local turn remains visible while inherited context stays hidden.

I found this while looking at the same migration path as #38761, but kept it in a separate report because this issue is about subagent history projection rather than legacy name preservation.

If this is not the intended behavior for persisted subagents, I'm happy to work on the focused fix and regression test if a maintainer invites a PR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the migration call in codex-rs/thread-store/src/local/rollout_migration.rs and the boundary handling in rollout_migration/publish.rs, then read projection in thread_history_materialization.rs. Run the focused migration test in rollout_migration_tests.rs and consider a persisted named subagent through thread/read or thread/resume. Done means child-local turns remain visible while inherited context stays hidden.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.