Skip to content

fix(auto-reply): wire get-reply-run.ts queue-mode gates to session-run-registry #2342

@alexey-pelykh

Description

@alexey-pelykh

Summary

src/auto-reply/reply/get-reply-run.ts is the hot path for every inbound auto-reply. After the pi-embedded gut (b27cecc795, #76/#77) and the v2026.3.7 sync regression (9ef1894, #2298), four pi-embedded function imports were reintroduced at lines 5-9 and now silently operate on no-op stubs. This collapses every user-configured queue mode gate to the "no run active" branch, breaking interrupt / steer / steer-backlog / collect semantics.

Tracked from the ChannelBridge compatibility audit on #2089 as the highest-severity regression discovered.

Current regressed state

// src/auto-reply/reply/get-reply-run.ts (lines 402-412)
const sessionLaneKey = resolveEmbeddedSessionLane(sessionKey ?? sessionIdFinal);  // → "default"
const laneSize = getQueueSize(sessionLaneKey);                                    // → 0 (no producer)
if (resolvedQueue.mode === "interrupt" && laneSize > 0) {                         // → unreachable
  const cleared = clearCommandLane(sessionLaneKey);
  const aborted = abortEmbeddedPiRun(sessionIdFinal);                             // → no-op stub
  logVerbose(`Interrupting ${sessionLaneKey} (cleared ${cleared}, aborted=${aborted})`);
}
const queueKey = sessionKey ?? sessionIdFinal;
const isActive = isEmbeddedPiRunActive(sessionIdFinal);                           // → false (stub)
const isStreaming = isEmbeddedPiRunStreaming(sessionIdFinal);                     // → false (stub)
const shouldSteer = resolvedQueue.mode === "steer" || resolvedQueue.mode === "steer-backlog";

Downstream, isActive and isStreaming are passed to runReplyAgent in agent-runner.ts. With both false, the branch at agent-runner.ts:197-204 (shouldSteer && isStreaming → queueEmbeddedPiMessage) is dead, and the active-run queue action resolver in agent-runner.ts:206-216 always picks the "not active" path regardless of whether a ChannelBridge CLI subprocess is actually running.

Impact

Any user who sets queue.mode to interrupt, steer, steer-backlog, or collect in their config gets silently downgraded behavior — the mode is honored only for the "no run active" case, which is the least interesting case. The configured interrupt mode never actually interrupts.

Proposed fix

  1. Drop the four pi-embedded imports at lines 5-9 of get-reply-run.ts.
  2. Wire isActive to session-run-registry:
    import { isSessionRunActive } from "../../agents/session-run-registry.js";
    // ...
    const isActive = isSessionRunActive(sessionKey ?? sessionIdFinal);
  3. Remove isStreaming from get-reply-run.ts entirely. ChannelBridge CLI runtimes don't expose a "streaming" state distinct from "active"; the closest equivalent is binary. Also remove isStreaming from the runReplyAgent params contract in agent-runner.ts:68,71,100,102 and delete the shouldSteer && isStreaming dead branch at agent-runner.ts:197-204.
  4. Remove the sessionLaneKey / laneSize / clearCommandLane block (lines 402-408). The command-queue.ts lanes are main/cron/subagent/nested (from src/process/lanes.ts); there is no session-keyed lane that the current code populates. This block is dead whether or not pi-embedded stubs exist.
  5. Wire "interrupt" queue mode to killSessionRun if the intent is still to stop the running subprocess when a new interrupt-mode message arrives:
    import { killSessionRun } from "../../agents/session-run-registry.js";
    // ...
    if (resolvedQueue.mode === "interrupt" && isActive) {
      killSessionRun(sessionKey ?? sessionIdFinal);
    }
    Alternatively, if the decision is that interrupt-mode should abort+restart at a higher level, document that and remove this gate entirely.

Acceptance Criteria

  • get-reply-run.ts no longer imports anything from pi-embedded.js
  • isActive uses session-run-registry.isSessionRunActive
  • isStreaming and shouldSteer && isStreaming dead branch removed from agent-runner.ts
  • interrupt queue mode either calls killSessionRun or has documented rationale for no-op
  • pnpm check passes
  • Existing queue-mode tests updated (they currently mock isEmbeddedPiRunActive / isEmbeddedPiRunStreaming — see reply.directive.* and agent-runner.*.test.ts files)
  • Verification: git grep -n "isEmbeddedPiRunActive\|isEmbeddedPiRunStreaming\|resolveEmbeddedSessionLane" src/auto-reply/ returns zero production hits

Out of Scope

  • Deletion of pi-embedded.ts stub barrel itself — tracked under audit: review all Pi engine stub replacements for ChannelBridge compatibility #2089 parent issue as a cascade sweep.
  • steer mode abort+restart implementation — separate design discussion; this issue fixes only the gating regression.
  • Other pi-embedded consumers (abort.ts, sessions.ts, server-reload-handlers.ts, subagents-tool.ts, action-kill.ts, action-send.ts, commands-session.ts) — separate sub-issues.

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions