#13720: fix: emit single lifecycle start/end pair for model fallback chain
commands
agents
stale
## Problem
When the primary model (e.g., Claude) fails with rate limit/auth error and falls back to a secondary model (e.g., Ollama), the TUI shows "\(no output\)" even though responses are generated correctly and saved to the session file.
## Root Cause
Each model attempt emitted its own `lifecycle:start/end` pair. When Claude failed, its `lifecycle:end` caused the gateway to close the `chatLink`, so subsequent Ollama responses were ignored by the TUI because `finalizedRuns.has(runId)` was already true.
## Solution
Move lifecycle event emission from the per-attempt subscription handler to the outer command layer, wrapping the entire fallback chain in a single `lifecycle:start/end` pair.
### Changes
1. **`pi-embedded-subscribe.handlers.lifecycle.ts`**: Remove `emitAgentEvent()` from `handleAgentStart`/`handleAgentEnd` (keep internal callbacks only)
2. **`agent-runner-execution.ts`**: Emit `lifecycle:start` before `runWithModelFallback` loop, `lifecycle:end/error` after completion
3. **`agent.ts`, `followup-runner.ts`, `agent-runner-memory.ts`, `isolated-agent/run.ts`**: Same pattern for other entry points
## Visual Explanation
```
BEFORE (broken):
┌─ Claude attempt ─┐
│ start → fail → end │ ← Gateway closes here
└──────────────────────┘
┌─ Ollama attempt ─┐
│ start → ok → end │ ← TUI ignores this
└──────────────────────┘
AFTER (working):
┌─────────────────────────────────┐
│ start │
│ ┌─ Claude ─┐ │
│ │ fail │ (no events) │
│ └──────────┘ │
│ ┌─ Ollama ─┐ │
│ │ ok │ (no events) │
│ └──────────┘ │
│ end │ ← Gateway closes here
└─────────────────────────────────┘
```
## Testing
Tested by temporarily invalidating the Anthropic API key to force auth error, confirmed Ollama fallback responds correctly without "\(no output\)".
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR changes lifecycle event emission so each agent run (including model fallback retries) produces a single `lifecycle:start` + terminal `lifecycle:end/error` pair, instead of emitting per-attempt lifecycle events inside the embedded subscription handler. This is intended to prevent the gateway from finalizing a run after the first failed attempt, which previously caused downstream UIs to show “(no output)” despite successful fallback responses.
The main remaining concern is in the auto-reply runner’s CLI-provider path: assistant text is emitted in a Promise `.then()` while `lifecycle:end` can be emitted immediately afterward, which can still lead to the gateway finalizing the run before the assistant text arrives (dropping output).
<h3>Confidence Score: 3/5</h3>
- This PR is close to mergeable but has one ordering bug that can still drop output for CLI providers.
- Lifecycle events are now correctly consolidated across fallback chains, matching the gateway’s finalize-on-end/error behavior. However, in `runAgentTurnWithFallback` the CLI-provider branch emits the assistant text in a Promise `.then()` while emitting `lifecycle:end` outside that continuation, allowing `lifecycle:end` to arrive first and causing the gateway to finalize before the assistant delta is buffered.
- src/auto-reply/reply/agent-runner-execution.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#16949: fix(gateway): deliver chat:final even when sessionKey is unresolved (…
by ekleziast · 2026-02-15
79.5%
#13658: fix: silent model failover with fallback notification
by taw0002 · 2026-02-10
78.8%
#13191: pi-embedded: enable failover when per-agent fallbacks are configured
by zesty-clawd · 2026-02-10
77.7%
#8390: feat: notify user when fallback model is used (#8182)
by Glucksberg · 2026-02-04
77.4%
#22072: Fix responsePrefix {model} to use runtime model metadata
by graysurf · 2026-02-20
76.6%
#8598: fix: emit agent events for CLI agents targeting webchat
by dbottme · 2026-02-04
76.6%
#4462: fix: prevent gateway crash when all auth profiles are in cooldown
by garnetlyx · 2026-01-30
76.5%
#16838: fix: include configured fallbacks in model allowlist
by taw0002 · 2026-02-15
76.4%
#11349: fix(agents): do not filter fallback models by models allowlist
by liuxiaopai-ai · 2026-02-07
76.0%
#9163: Fix: Save Anthropic setup token to config file
by vishaltandale00 · 2026-02-04
76.0%