Skip to content

fix: replay buffered thread lifecycle events before turn filtering - #581

Open
axisrow wants to merge 1 commit into
openai:mainfrom
axisrow:ao/codex-plugin-cc-5/preserve-subagent-thread-labels
Open

fix: replay buffered thread lifecycle events before turn filtering#581
axisrow wants to merge 1 commit into
openai:mainfrom
axisrow:ao/codex-plugin-cc-5/preserve-subagent-thread-labels

Conversation

@axisrow

@axisrow axisrow commented Aug 1, 2026

Copy link
Copy Markdown

Summary

  • Replay buffered thread/started / thread/name/updated notifications unconditionally before applying turn-scoped belongsToTurn() filtering to the rest of the buffer in captureTurn().

Why

Closes #36.

The live notification handler in captureTurn() already special-cases thread/started and thread/name/updated to bypass turn-scoped filtering (since a subagent's turn ID isn't known yet when its thread first announces itself). The buffered-replay path that runs once the main turn ID becomes available did not apply the same bypass — it ran every buffered notification through belongsToTurn(), which drops thread-lifecycle events for threads that don't yet have a tracked turn ID.

If a subagent thread announces itself early enough to be buffered rather than handled live, its label gets silently dropped, and job logs and progress output fall back to raw thread IDs like thr_2 instead of the agent's nickname (e.g. design-challenger).

Fix

Apply the same thread/started / thread/name/updated bypass in the buffered-replay loop that the live handler already uses.

Validation

  • node --test tests/*.test.mjs — all subagent-labeling tests pass:
    • task logs subagent reasoning and messages with a subagent prefix
    • task ignores later subagent messages when choosing the final returned output
    • task can finish after subagent work even if the parent turn/completed event is missing
    • task using the shared broker still completes when Codex spawns subagents
  • npm run build passes with no type errors.
  • Confirmed the pre-existing fixture (with-subagent in tests/fake-codex-fixture.mjs) already sends thread/started for the subagent thread ahead of the main turn's response, exercising exactly this race.
  • 5 unrelated pre-existing test failures (state-dir temp path assumptions, status/result job listing) reproduce identically with and without this change, confirming they're environment-specific and not caused by this fix.

thread/started and thread/name/updated notifications for subagent
threads can arrive before the main turn ID is known and get buffered.
The live notification handler already special-cases these two methods
to bypass belongsToTurn() filtering, but the buffered-replay path in
captureTurn() did not, so early subagent thread labels were silently
dropped and job logs fell back to raw thread IDs like thr_2.

Apply the same bypass when replaying buffered notifications.

Closes #36
@axisrow
axisrow requested a review from a team August 1, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant