fix(tui): a Host-started Turn in /side makes the copied parent transcript visible again - #3885
Conversation
5edc261 to
8b5fa0b
Compare
…ript visible again A TUI side conversation is a Session copy that carries the parent's transcript; the driver hides it by recording `#hiddenTranscriptThroughTurnId` and filtering every transcript through `visibleTranscriptMessages()`. The Host-started Turn reattach path built its attached Turn from the raw `opened.messages`, so reconnecting while a Turn ran on the side Session replaced the visible transcript with the full parent conversation the user opened `/side` to leave. Route this path through the same filter every sibling uses (switchSession and the transcript-replacement subscriptions), so `/side` shows only what happened inside the side conversation. Add a regression test that starts a Host successor Turn on a side Session and asserts the copied parent transcript stays hidden; it fails without the one-line fix. Fixes apache#3881 Generated-by: Claude Code
8b5fa0b to
95008e7
Compare
Astro-Han
left a comment
There was a problem hiding this comment.
Approving.
What this PR does: a TUI /side conversation is a Session copy that carries the parent's transcript, hidden by recording #hiddenTranscriptThroughTurnId and filtering every transcript handed to the runner through visibleTranscriptMessages(). #reattachStartedTurn was the one path that built the attached Turn from raw opened.messages, so a Host-started Turn on the side Session — e.g. reconnecting while a Turn was running there — put the parent conversation back on screen in full. This routes that path through the same filter.
Verified against head:
- Every sibling really does apply the filter, so this was a gap and not a deliberate exception:
runtime-host-session-driver.ts:251(transcript-replacement subscription),:563(switchSession),:1243(the other subscription).:1155is the one that did not, and now does. - Ordering is right.
#hiddenTranscriptThroughTurnIdis assigned only inswitchSession(:555) and cleared only instartNewSession(:703);#adoptLoadedConfigurationdoes not touch it, so the value the reattach reads is the one the switch established for that same Session. The generation and channel guards run before the adopt, so a stale reattach bails out before reaching this line. visibleTranscriptMessages(messages, undefined)is a no-op, so ordinary (non-side) Sessions are unaffected.
The regression test drives a Host-started successor Turn on a side Session and asserts the copied parent transcript stays hidden, which is the actual reported path rather than a proxy for it.
AI use: Claude Code assisted with tracing the call sites and the field's lifecycle; the verification and conclusion are my own.
简体中文
Approve。
这个 PR 在做什么:TUI 的 /side 会话是带着父会话 transcript 的 Session 副本,靠 #hiddenTranscriptThroughTurnId 加 visibleTranscriptMessages() 过滤来隐藏。#reattachStartedTurn 是唯一漏掉过滤的路径,于是当 Host 在 side 会话上启动 Turn(例如那里正在跑 Turn 时重连),用户本来用 /side 想避开的父会话又整段冒出来。这个 PR 把该路径接回同一个过滤器。
已核对:另外三处调用点(:251 / :563 / :1243)确实都做了过滤,所以这是遗漏而非有意例外;该字段只在 switchSession:555 赋值、startNewSession:703 清空,#adoptLoadedConfiguration 不碰它,因此 reattach 读到的正是同一 Session 在 switch 时确立的值,且 generation/channel 守卫在 adopt 之前就会拦掉过期的 reattach;对非 side 会话该调用是 no-op,无影响。回归测试跑的是真实上报路径,不是替身。
Summary
A TUI side conversation (
/side) is a Session copy that carries the parent's transcript. The driver hides it by recording#hiddenTranscriptThroughTurnIdand filtering every transcript it hands the runner throughvisibleTranscriptMessages(). One path skipped that filter:#reattachStartedTurnbuilt the attached Turn for a Host-started Turn from the rawopened.messages. When a Host-started Turn arrived on the side Session (e.g. reconnecting while a Turn was running there),pi-tui-runnerreplaced the visible transcript with those unfiltered messages — so the parent conversation the user opened/sideto get away from reappeared in full.Every sibling already applies the filter (
switchSession, and the transcript-replacement subscriptions), so this was a gap rather than a deliberate exception. The fix routes this path through the same filter:Present since #3759, which introduced both sides of this path.
Fixes #3881
Verification
npm --workspace maka-agent run buildthennode --test dist/__tests__/runtime-host-session-driver.test.js— all 52 tests pass.hides the copied parent transcript when a Host starts the side successor turn) that drives a Host-started successor Turn on a side Session and asserts the copied parent transcript stays hidden. Confirmed it fails without the one-line fix (the parent transcript leaks back in) and passes with it.npx biome lintandnpx biome formatclean on both changed files;tsc -p packages/cli/tsconfig.json --noEmitpasses.AI use
Select exactly one:
Tool(s) and scope: Claude Code authored the one-line fix and the regression test; the affected commit carries a
Generated-by: Claude Codetrailer.Checklist
Does this PR entail a change in behavior?