Skip to content

fix(agents): bind native replies and usage to the requested turn - #570

Merged
futrime merged 3 commits into
mainfrom
fix/native-turn-binding
Nov 6, 2026
Merged

futrime merged 3 commits into
mainfrom
fix/native-turn-binding

Conversation

@futrime

@futrime futrime commented Nov 6, 2026

Copy link
Copy Markdown
Member

Claude Code and Codex run turns of their own (wakeups, finished tasks, CLI-queued work). On main those turns' replies, usage and callbacks were read into whichever prompt was being answered. Ported from the internal fork (63952525, bf74ff8c, d7349846, 0402ccd7, ad06f99c), as behaviour rather than diff, and without the fork's new unprompted watcher event.

Claude Code

  • Every prompt is sent under a command uuid. Only the turn Claude starts under that uuid answers the prompt.
  • A turn of the CLI's own (a wakeup, a task_notification, a uuid hmz never gave) is left out of the answer and the events. Its usage, live and at its result, still goes to the session meter and budget.
  • A prompt merged into such a turn fails as contended, so it is retried.

Codex

  • A turn is the one turn/start answers with. Notifications that arrive before that answer wait for it. Other turns' items, completions and usage never reach the turn reader.
  • A result's tokens and spent cover only its own requests, not the thread's rise across the turn.
  • Usage is read in stream order on the pump. Ended turns are remembered, so late output is dropped and late totals settle on the meter without reopening the turn. A late, smaller total no longer winds the count back.
  • Approvals and questions reach hooks and agent.ask only for the turn under way or the goal being pursued. Others, and callbacks for idle threads, get an RPC error. Callbacks held while a turn is still starting are refused if the turn is abandoned.
  • A thread belongs to its session even when a goal opened it, so usage after the goal returns is still charged there.

Docs: docs/reference/agents.md (Sessions and turns, contended).

Tests

  • New tests/integration/test_agents_reply_binding.py: 7 of its 9 tests fail on main and all pass here. The other 2 guard that the CLI's own usage still counts against the budget.
  • The unit fakes now include turnId on callbacks. The Codex integration fakes answer turn/start with a turn id, as real Codex does.
  • uv run --all-extras pytest passes. pre-commit run --all-files is clean.

Claude Code and Codex run turns of their own (wakeups, finished tasks, CLI-queued
work). Their replies, usage and callbacks were read into whichever prompt was
being answered.

- claude: every prompt is sent under a command uuid; only the turn started under
  it answers the prompt. A turn of the CLI's own is dropped from the answer, its
  usage still charged to the session; a prompt merged into one fails as contended.
- codex: a turn is the one turn/start answers with. Notifications before that
  answer wait for it; other turns' items, completions and usage never reach the
  turn, and a turn's tokens are its own requests' rather than the thread's rise.
- codex: ended turns are remembered, so late output is dropped and late totals
  settle on the meter without reopening the turn or rewinding the count.
- codex: approvals and questions reach hooks only for the turn under way or the
  goal being read; others, and idle threads, get an RPC error. A goal's thread
  stays its session's for usage after the goal returns.
@futrime
futrime added this pull request to the merge queue Nov 6, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 6, 2026
…urn-binding

# Conflicts:
#	docs/reference/agents.md
#	src/hmz/coganchor/agents/codex.py
@futrime
futrime added this pull request to the merge queue Nov 6, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 6, 2026
…urn-binding

# Conflicts:
#	src/hmz/coganchor/agents/codex.py
#	tests/integration/test_agents_codex.py
@futrime
futrime added this pull request to the merge queue Nov 6, 2026
Merged via the queue into main with commit ae666ee Nov 6, 2026
15 checks passed
@futrime
futrime deleted the fix/native-turn-binding branch November 6, 2026 03:08
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