Skip to content

fix(server): a Claude /goal no longer reads as complete while a background subagent runs - #16598

Open
Jreevo wants to merge 1 commit into
pingdotgg:mainfrom
Jreevo:fix/claude-goal-background-subagent
Open

Jreevo wants to merge 1 commit into
pingdotgg:mainfrom
Jreevo:fix/claude-goal-background-subagent

Conversation

@Jreevo

@Jreevo Jreevo commented Oct 6, 2026 •

Copy link
Copy Markdown

Problem

On a Claude thread, a /goal shows Goal complete when a turn ends while a background subagent (Agent with run_in_background) is still running, even though Claude has not checked the goal. Claude Code skips the goal check while background work runs and checks again on a later turn, so the goal is still set in Claude; only T3's status is wrong. The goal row then offers only Clear, which invites the user to drop a goal that is still working.

Seen on T3 Code Nightly 0.0.46-nightly.20261006.2735 (macOS), Claude Code 2.1.292. To reproduce: start a background subagent, then send /goal <condition> while it runs. Claude acknowledges, ends the turn to wait for the subagent, and the goal row turns to "Goal complete".

Change

#15592 infers Claude goal completion in finalizeActiveTurn: the goal was active, the model replied this turn, the turn ended normally, and the background-task roster is empty. The roster holds only local_bash work; subagents are deliberately kept off it, so a running background subagent never blocked the inference.

The check now also requires that the live process runs no background work of a type Claude waits on. It reuses liveProcessRunsBackgroundWork, which already skips subagents orphaned by an earlier process and ones whose completion is already buffered. A forGoalCheck option makes it ignore task types Claude does not wait on. The model-switch and query-replacement gates are unchanged.

Which types defer the check comes from Claude Code 2.1.292 itself. Its Stop handler runs Aa(taskRegistry.all()) and skips the goal evaluation when that returns anything. Aa keeps non-terminal local_agent, remote_agent, in_process_teammate, local_workflow and local_bash tasks, regardless of ambient. So CLAUDE_GOAL_DEFERRING_TASK_TYPES lists the four subagent-path types, and a task_started with any other task_type (for example mcp_task or monitor_ws) goes into an add-only goalExemptTaskIds set. A missing task_type stays deferring. Claude's other exclusions (observer agents, main-session, idle teammates, long-running remote agents) are not visible in SDK frames; for those T3 keeps the goal active, which is the safe direction.

Once the background work ends and a later turn passes the check, the goal completes as before.

Scope and approval

Fixes #16611 (filed for tracking; not yet triaged). This is a small, focused fix for an obvious bug: the UI reports a goal as complete when the provider has not evaluated it, which contradicts Claude Code's documented behavior and the rule the existing code comment states. One gate in one adapter changes, plus tests. Codex goals, contracts and clients are untouched.

Verification

  • Live capture. I drove Claude Code 2.1.292 through the Agent SDK with this scenario: launch a background subagent, then /goal. In the captured frames, the root result arrives while the subagent still runs, with no Stop hook feedback, so Claude skipped the check. Then come the task_notification, a wake turn (init), and a final result with no feedback, so the goal passed. Replaying those exact frames through the adapter:

    • On main, the goal is marked complete right after the goal turn, which is the bug.
    • With this patch, it is active after the goal turn and complete after the wake turn.
  • New tests in native goals:

    • defers goal completion while a background subagent runs follows the captured frame order (Agent call, background_tasks_changed, backgrounded task_started, async ack, reply, result, then notification, wake, result). It asserts active, then complete.
    • treats a running $taskType … as goal $status asserts that mcp_task gives complete, an ambient skip_transcript local_agent gives active, and a missing type gives active.
    • Each case fails against the code it guards (main, or the intermediate designs I tried). 147/147 pass in ClaudeAdapterV2.test.ts.
  • tsc --noEmit in apps/server passes. vp fmt --check is clean. vp lint on the two files reports only an existing warning elsewhere in the file.

  • Reviews. The fix went through three review rounds by GPT-6.1 Sol and Claude Opus 5.5. They checked foreground, nested and resumed subagents, in-turn completion, stop and failure, process replacement, buffered and live wake turns, and Claude's own deferral predicate in the CLI binary. No open findings remain.

  • Seen in a real thread (Nightly 0.0.46-nightly.20261006.2735): the goal row reads "Goal complete" while the background subagent is still coding and no review round has started.

    Goal complete row while a background subagent still runs
  • Not checked: a packaged T3 build running this patch end to end.

Made with Claude Code (Claude Opus 5.5).

🤖 Generated with Claude Code

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Oct 6, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at c9f9a64

Macroscope's review found this PR approvable — This is a narrowly scoped server bug fix that prevents Claude goals from being marked complete while a background subagent is still running, with targeted regression coverage. Existing completion behavior remains unchanged once background work has settled.

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

@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b8890b1a-3c7d-4038-9c6f-c76bd72f20bc
📥 Commits

Reviewing files that changed from the base of the PR and between c9f9a64 and 98d67c1.

📒 Files selected for processing (2)
  • apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts
  • apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Claude goal completion now checks active background work in the matching live query. Four task types defer the goal check. Other defined subagent task types do not block completion. Tests cover task launch, wake continuation, and expected goal statuses.

Changes

Claude goal completion

Layer / File(s) Summary
Track goal-exempt task types
apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Claude defines four task types that defer goal checks. It records IDs for started subagent tasks with other defined task types.
Apply task types to goal completion
apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts, apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts
Goal completion is blocked by active background work that defers goal checks. Tests cover a background Agent lifecycle and expected statuses for running task types.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 98d67

No actionable merge-blocking issue remains after normal checks.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to 98d67

The change makes goal completion more conservative while background work runs. It does not add permissions, expose a new interface, or weaken the protection against replacing a process that still has active work.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The demonstrated effect is on goal status projected onto the provider thread within an opened session. The new check is restricted to a matching native thread and does not grant tool authority or expand process-replacement eligibility.

Trust Boundaries and Controls

  • observed — Task classification consumes system lifecycle messages from the existing query-session stream. Existing goal tracking distinguishes root synthetic goal signals from ordinary assistant output, and query policy remains derived from the turn's runtime policy rather than task exemption state.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Approvability ✅ Passed PASS. The pull request changes only ClaudeAdapterV2.ts and its test file. The adapter change is a focused fix to Claude goal-completion inference while background work runs. The test adds cases for …
Title check ✅ Passed The title is concise and clearly identifies the main change: preventing Claude goals from appearing complete while a background subagent runs.
Description check ✅ Passed The description covers the problem, change, scope and approval rationale, and focused verification. It also states that a packaged T3 build was not checked.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

…round subagent runs

Claude Code skips a goal's Stop hook check while background work runs and
checks again on a later turn. The adapter inferred completion from a
normal turn end plus an empty roster, but the roster leaves subagents
out, so a turn that ended while a background Agent ran marked the goal
complete.

The completion check now also requires that the live process runs no
background work of the types Claude Code 2.1.292 waits on: local_agent,
remote_agent, in_process_teammate and local_workflow on the subagent
path (local_bash is already on the roster). Tasks of other types, such as
mcp_task and monitor_ws, are exempt, as they are in Claude.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Claude /goal shows complete while a background subagent is still running

1 participant