fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(orchestrator): Keep Claude child work on the child thread - #5456

Open
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message
Open

fix(orchestrator): Keep Claude child work on the child thread#5456
mwolson wants to merge 331 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/claude-subagent-empty-prompt-message

Conversation

@mwolson

@mwolsonmwolson commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What Changed

A Claude child can keep talking after the parent root settles. Later text, tools, and results were landing on the parent thread, so the child's work showed up in the wrong conversation. Those later frames now stay on the child.

A blank or whitespace Agent prompt, or progress that arrived before the real prompt, opened the child with an empty "Sent by another agent" bubble. The child now waits for real prompt text before showing that opening message. A child that never gets a prompt still runs. It just starts with no blank bubble.

Checked on a live Claude thread. One Agent launched with a single space, another with a real prompt. The blank child had no user message. The sibling had exactly one opening message with the real prompt.

Why

Settle on the parent is not the end of that child's stream. Routing later frames with the parent's turn mixed the two conversations.

The empty bubble was the same class of mistake: the child thread showed a user message that nobody sent.

Review both here. #5388 claude-postsettle-attribution is closed as absorbed.

UI Changes

Child output after the parent settles stays in the child thread on web and mobile. A blank Agent launch no longer creates an empty "Sent by another agent" bubble.

No before/after screenshots.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches Claude subagent lifecycle, wake buffering, and tool-result attribution in orchestration-v2; incorrect routing could misplace child-thread events or drop legitimate wake traffic.

Overview
Subagent child threads no longer get an opening “Sent by another agent” user message when the prompt is empty, whitespace-only, or not known yet. A shared hasSubagentPromptText guard is used in the ACP, Codex, Cursor, and Claude adapters; Claude additionally emits that opening message only when prompt text first becomes non-empty (e.g. after task_progress before task_started).

Claude adapter changes tighten how subagents are registered and how wake-buffer frames are handled: registration work is consolidated inside session state updates with an emitPromptMessage flag, wake messages for failed or unknown tasks are dropped earlier (with cleanup on stale task_notifications), and tool results for Agent launches resolve subagents by task id / launch aliases, buffer unresolved launches, and skip results tied to failed wake drains.

A replay fixture and unit tests cover blank prompts and late prompt arrival.

Reviewed by Cursor Bugbot for commit ac5be27. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep Claude child work on the child thread, gate empty subagent prompts

  • Adds shared hasSubagentPromptText in SubagentProjection.ts and uses it across ACP, Codex, Cursor, and Claude adapters so blank or whitespace-only prompts no longer emit empty opening user messages or turn items
  • Reworks registerSessionSubagent in ClaudeAdapterV2.ts to preserve prior task state across updates, support reopen semantics (clearing stale results and tool calls), emit the opening prompt at most once, and maintain extra bookkeeping (taskIdByToolUseId, pending resume IDs, terminal item ID sets, generation)
  • Rewrites bufferWakeMessage to attribute wake evidence to known, non-failed subagent or background tasks per native thread, and rewrites the tool_result handling loop to correctly resolve subagents by tool_use_id or task_id, buffer messages for unregistered Agent launches, and skip failed-successor tasks
  • Adds replay fixture claude_subagent_empty_prompt covering a blank prompt, a whitespace-only prompt, and a late-arriving prompt
  • Behavioral Change: subagent opening prompts are now emitted at most once and only when non-whitespace text first becomes available; tool results and wake messages for unknown or failed tasks are now suppressed rather than processed

Macroscope summarized ac5be27.

@coderabbitai

coderabbitaiBot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7340cd12-4409-4cc1-b8b5-91ab73df863b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6eCompareAugust 7, 2026 12:10
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 0e1b4fe to 1598863CompareAugust 8, 2026 18:43
@macroscopeapp

macroscopeappBot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR changes production subagent lifecycle, wake/replay, resume attribution, and child-thread projection behavior across multiple adapters. Its stateful Claude changes are broad, and unresolved concerns remain around registry persistence, continuation attribution, reopen handling, and launch-result replay.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1ccCompareAugust 10, 2026 17:05
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from 1598863 to b5f1b94CompareAugust 11, 2026 13:38
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115CompareAugust 12, 2026 23:19
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from b5f1b94 to 9c18ee2CompareAugust 13, 2026 21:26
@mwolsonmwolson changed the title fix(orchestrator): Skip blank subagent opening messagesfix(orchestration): Keep Claude child output attributed after settleAug 13, 2026
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 519c42a to 4c55679CompareAugust 17, 2026 10:28
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch 2 times, most recently from ea1bb95 to 4c2c69cCompareAugust 19, 2026 18:05
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts Outdated
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@t3dotggt3dotgg added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 24, 2026
@mwolsonmwolson changed the title fix(orchestration): Keep Claude child output attributed after settlefix(orchestrator): Keep Claude child work on the child threadAug 27, 2026
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from a110e68 to 81c6ac9CompareAugust 29, 2026 00:13
juliusmarmingeand others added 17 commits August 31, 2026 21:33
Keep the original cursor owner through ancestor traversal and preserve the history budget across empty intermediate forks. Verify exact paged history against the complete nested projection.
Finding: P01 nested lineage
Model: GPT-5.6 Sol via Codex
Retain pending admission after transient status failures and use one generation-owned retry worker. Ignore stale timers and duplicate evidence so older prompts cannot finish newer steering.
Finding: R14 status reconciliation
Model: GPT-5.6 Sol via Codex
Keep hidden local and inherited rows from consuming history pages. Preserve stop-request dependencies, source-run cutoffs, and imported history while loading related metadata from the selected cohort and using indexed watermark lookups.
Finding: P01 bounded history visibility
Model: GPT-5.6 Sol via Codex
Adapt grouped tool summaries and the floating working timer to V2 run, attempt, and queue state. Bring over the composer, keyboard, and disclosure transitions while retaining the V2 activity inspector and queue controls.
Keep OV2 web composer and grouping behavior intact; share only the existing command label parser with mobile.
Restores main features dropped by the policy replay: pingdotgg#8569 theme wiring,
pingdotgg#8850 composer banner follow-ups, pingdotgg#8855/pingdotgg#8904 composer fixes, pingdotgg#8831
settings search rework, pingdotgg#8803 workspace-mutation refresh (v2-adapted),
pingdotgg#8840 circle-alert, pingdotgg#8584 codex artifact templates, pingdotgg#8688/pingdotgg#8807/pingdotgg#8936
video + image previews (web and mobile, v2-adapted), pingdotgg#8862 Expo glass,
and the round's docs. Timeline thinking rows (pingdotgg#8984) stay on the v2
work-live system.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch from a6e0049 to 50a57b6CompareSeptember 1, 2026 05:36
juliusmarmingeand others added 4 commits September 1, 2026 00:24
The v2 equivalents of main's pingdotgg#8984 and pingdotgg#8922: a "Working for ..." header
anchors the active run, the trailing live tool row survives between
actions in past tense instead of vanishing, and a shimmering Thinking
row marks reasoning gaps. During workspace preparation the header shows
"Setting up worktree..." (driven by the local dispatch flag or the v2
run's preparing status, so remote viewers see it too), the composer
footer span is gone, and draft promotion waits until the run starts or
startup fails instead of navigating mid-preparation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A provider-native subagent could open its child thread with an empty or
whitespace-only user message, which renders as an empty bubble under the
"Sent by another agent" label. The Claude adapter emitted the opening
prompt whenever the subagent was new, and a task_progress frame can
register a subagent before any frame carries its prompt, so the message
was emitted with the "" default and never rewritten when the real prompt
arrived on a later task_started.
A shared hasSubagentPromptText guard now gates every subagent opening
message. The Claude adapter emits it the first time the task prompt
actually has text rather than on first registration, so a late prompt
still opens the child thread exactly once. Codex's existing length check
becomes trim-aware, and Cursor and ACP pick up the same guard.
@mwolson
mwolsonforce-pushed the fix/claude-subagent-empty-prompt-message branch from ed223fe to ac5be27CompareSeptember 1, 2026 23:26
@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 1, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac5be27. Configure here.

Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment threadapps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@juliusmarminge
juliusmarmingeforce-pushed the t3code/codex-turn-mapping branch 4 times, most recently from 9eeed8c to 8af5734CompareSeptember 4, 2026 18:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@mwolson@t3dotgg@PixPMusic@juliusmarminge@nsxdavid@Yusuf007R@maria-rcks