Skip to content

Agent Mode wait steering should include the steered message in the interrupt payload #384

Description

@provencher

Summary

When a user steers an Agent Mode run while an agent_run.wait caller is blocked, RepoPrompt wakes the wait as interrupted_by_steering but does not include the user's steered message in that interrupt/wake payload. The UI looks correct because the user bubble is appended immediately, but the provider/agent can resume before the underlying harness has delivered the actual user text.

This is especially visible with Codex: the interrupt fires, the waiting harness wakes, and the model may go back to waiting because it did not yet see the user's steered message.

Expected behavior

Visually, steering should appear exactly the same to the user. Internally, the interrupt/wake that reaches the waiting agent should include the user's steered message directly, instead of relying on a later harness follow-up to pass the message.

Actual behavior

  • agent_run.wait wakes with result: "interrupted_by_steering" and guidance to call agent_run.wait again.
  • The wake result does not carry the steered message.
  • Provider-specific message delivery remains separate from the wake/interrupt path.
  • If the interrupt is observed before the harness delivers the user text, the model can continue as if no user input arrived and return to waiting.

Relevant code surfaces

MCP wait wake/result plumbing:

  • Sources/RepoPrompt/Infrastructure/MCP/Agent/AgentRunSessionStore.swift
    • WakeReason.steeringRequested
    • wakeCurrentWaiters(...)
  • Sources/RepoPrompt/Infrastructure/MCP/Agent/AgentRunMCPToolService.swift
    • interrupted_by_steering single-wait and multi-wait result shaping
    • _meta.wake_reason = steering_requested

Agent Mode steering dispatch:

  • Sources/RepoPrompt/Features/AgentMode/ViewModels/AgentModeViewModel.swift
    • active MCP dispatch planning for Claude/ACP/Codex
    • wakeMCPWaitersForActiveDispatch(...)
    • queued Claude/ACP interrupt handling
  • Sources/RepoPrompt/Features/AgentMode/Runtime/AgentModeRunService.swift
    • queued steering drain around MCP wait scopes

Provider-specific surfaces:

  • Sources/RepoPrompt/Features/AgentMode/Runtime/Claude/ClaudeAgentModeCoordinator.swift
  • Sources/RepoPrompt/Infrastructure/AI/Providers/ClaudeCode/SDK/ClaudeNativeProcessSessionController.swift
  • Sources/RepoPrompt/Features/AgentMode/Runtime/Codex/CodexAgentModeCoordinator.swift
  • Sources/RepoPrompt/Infrastructure/AI/Providers/Codex/AppServer/CodexNativeSessionController.swift
    • Codex turn/steer carries user text, while turn/interrupt and thread/resume do not carry a pending user message today.

Acceptance criteria

  • A run blocked in agent_run.wait receives an interrupt/wake payload that includes the user's steering message.
  • The visible Agent Mode UI remains unchanged: the optimistic user bubble and interaction flow should look the same.
  • Claude/ACP/Codex do not double-deliver the same steering message if the interrupt payload carries it.
  • Codex active turn/steer ACK-gated behavior remains intact.
  • Tests cover single-wait and multi-wait steering interruption payloads, plus provider-specific duplicate-delivery prevention.

Suggested regression coverage

Existing nearby tests to extend or mirror:

  • Tests/RepoPromptTests/MCP/AgentRunMCPToolServiceWaitTests.swift
  • Tests/RepoPromptTests/MCP/AgentRunMCPToolServiceWaitAnyTests.swift
  • Tests/RepoPromptTests/MCP/AgentRunWaitDrainIntegrationTests.swift
  • Tests/RepoPromptTests/AgentMode/Codex/CodexAgentModeCoordinatorLivenessTests.swift
  • Tests/RepoPromptTests/AgentMode/Codex/CodexSteerAckTrackerTests.swift
  • Tests/RepoPromptTests/AgentMode/Codex/CodexFallbackFIFOTests.swift

Risks / implementation notes

  • Avoid duplicate delivery if both the interrupt payload and the existing follow-up prompt path include the same message.
  • Be careful with privacy/logging: the steering text would become part of the MCP wait payload, so diagnostics should avoid unnecessary raw-text logging.
  • Preserve provider-specific semantics. Codex, Claude-compatible, and ACP steering paths do not currently share identical interrupt/message-delivery mechanics.

Related issues

No direct duplicate found. Related but broader lifecycle/wait issues include:

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:agent-modeAgent Mode runtime and interfacearea:mcpMCP server, clients, and connection visibilitybugSomething isn't workingprovider:codexCodex-specific integration behavioruxUser experience and interaction design

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions