Skip to content

fix: cross-provider history corruption — subagent text emitted as primary + canonical text_done overwrites #82

Description

@saucam

Summary

Two related bugs corrupt the canonical turn history that feeds cross-provider switching: (1) subagent assistant text is emitted as primary assistant text, and (2) the canonical accumulator keeps only the last text_done of a turn instead of concatenating.

Location

  • src/daemon/providers/claude/index.ts:495-504 (assistant branch emits text_done unconditionally, ignoring parent_tool_use_id)
  • src/daemon/providers/claude/index.ts:508-537 (stream_event branch never inspects parent_tool_use_id)
  • src/daemon/providers/canonical.ts:268-270 (case "text_done": this.#currentText = event.content — assign, not append)
  • consumed in production at src/daemon/session.ts:154

Root cause

(1) ProviderEvent.text_delta/text_done carry no parent field, so Session cannot filter subagent output downstream — yet the emit path already reads parent_tool_use_id for usage splitting (isPrimary, :491) and could gate on it. (2) Claude emits one text_done per assistant SDK message; a normal agentic turn is text → tool → text → tool → final text, so assigning drops every block but the last.

Failure scenario

Agent spawns a Task subagent and does interleaved commentary across 5 tool calls. Canonical history records only the final "done" utterance (or the subagent's last line), with all intermediate reasoning gone but the tool calls it referenced still present. On provider switch, Gemini/OpenAI receive a misleading, truncated history.

Fix

Add a parentToolUseId/isPrimary field to the text provider events and drop non-primary text before it reaches the canonical accumulator; change text_done handling to append (reset at turn/message boundaries, not per SDK message).

Metadata

Metadata

Assignees

No one assigned

    Labels

    auditSurfaced in a code auditbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions