Tracked as a follow-up to #4319 (F1) review thread — pre-existing bug in cli/src/serve/httpAcpBridge.ts that was preserved verbatim by the F1 lift into @qwen-code/acp-bridge/bridge. Filing here so the lift PR stays mechanical and the fix gets its own scope + tests.
Symptom
Both closeSession (now packages/acp-bridge/src/bridge.ts:~2127) and killSession (now ~3145) capture const ci = channelInfo — the module-scoped current attach target. Other session methods in the same file (setSessionApprovalMode at ~2617, requestSessionStatus at ~1255) correctly use channelInfoForEntry(entry), which searches aliveChannels for the entry's actual channel.
Failure mode
During channel overlap (A dying, B freshly spawned as channelInfo), closing a session on A:
- Skips
ci.sessionIds.delete() because B.channel !== entry.channel — the entry stays in A's sessionIds
- Calls
ci?.client.markSessionClosed() on B's client instead of A's
- Evaluates the kill condition against B — if B has
sessionIds.size === 0, B gets killed unnecessarily, forcing a third spawn
Why now
Pre-existing in httpAcpBridge.ts since the channel-overlap (BkUyD) bookkeeping landed. F1 just moved the code. But:
- F1 makes the buggy method public API of
@qwen-code/acp-bridge. Channels (packages/channels/base/AcpBridge.ts) and the VSCode IDE companion will consume it directly.
- The inconsistency within the same file (some methods use
channelInfoForEntry, two don't) is a maintenance trap.
Fix sketch
Two-line change in packages/acp-bridge/src/bridge.ts:
```diff
-
const ci = channelInfoForEntry(entry);
```
at both closeSession and killSession sites. The deferred follow-up needs:
- The two-line change.
- A new test for the channel-overlap scenario (A dying + B fresh) that fails on the buggy version and passes on the fix.
- Verify the existing 174
httpAcpBridge.test.ts tests still pass (the bug only manifests during the narrow overlap window, so 99% of existing tests should be unaffected).
Refs
🤖 Generated with Qwen Code
Tracked as a follow-up to #4319 (F1) review thread — pre-existing bug in
cli/src/serve/httpAcpBridge.tsthat was preserved verbatim by the F1 lift into@qwen-code/acp-bridge/bridge. Filing here so the lift PR stays mechanical and the fix gets its own scope + tests.Symptom
Both
closeSession(nowpackages/acp-bridge/src/bridge.ts:~2127) andkillSession(now~3145) captureconst ci = channelInfo— the module-scoped current attach target. Other session methods in the same file (setSessionApprovalModeat~2617,requestSessionStatusat~1255) correctly usechannelInfoForEntry(entry), which searchesaliveChannelsfor the entry's actual channel.Failure mode
During channel overlap (A dying, B freshly spawned as
channelInfo), closing a session on A:ci.sessionIds.delete()becauseB.channel !== entry.channel— the entry stays in A'ssessionIdsci?.client.markSessionClosed()on B's client instead of A'ssessionIds.size === 0, B gets killed unnecessarily, forcing a third spawnWhy now
Pre-existing in
httpAcpBridge.tssince the channel-overlap (BkUyD) bookkeeping landed. F1 just moved the code. But:@qwen-code/acp-bridge. Channels (packages/channels/base/AcpBridge.ts) and the VSCode IDE companion will consume it directly.channelInfoForEntry, two don't) is a maintenance trap.Fix sketch
Two-line change in
packages/acp-bridge/src/bridge.ts:```diff
```
at both
closeSessionandkillSessionsites. The deferred follow-up needs:httpAcpBridge.test.tstests still pass (the bug only manifests during the narrow overlap window, so 99% of existing tests should be unaffected).Refs
81747bd0f)🤖 Generated with Qwen Code