fix(runtime-host): project authoritative live run state - #3079
Conversation
Generated-by: Codex
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (21)
🚧 Files skipped from review as they are similar to previous changes (17)
Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review. 📝 WalkthroughSummaryThis PR fixes stale and incomplete session run indicators. Runtime Host projects authoritative live-run state through the versioned protocol, Desktop IPC, renderer merges, and the session-list UI. It extends the existing session catalog source of truth. It does not create a parallel execution-state path. Local renderer streaming remains an optimistic signal for local runs, while Runtime Host state identifies remote runs. The solution is the smallest coherent path across the affected layers. Known-empty and unknown states distinguish “no run exists” from “run state is unavailable.” Renderer merge helpers preserve live-run state when metadata mutation responses omit it. Protocol limits and validation protect the protocol boundary. No safe code or test deletion is apparent. Removing the state distinctions, merge behavior, or coverage would weaken required behavior or regression protection. Complexity delta
The added complexity is required to preserve the authority boundary and the distinction between known-empty and unknown state. Total maintenance complexity stays justified by the required behavior and regression coverage. ValidationThe change includes coverage for:
The supplied objectives report lint, formatting, build, typecheck, Runtime Host, Runtime, Desktop, UI, Storybook, and diff checks. Direct results for the current PR are not available here. Required check status remains unverified. Review-relevant risks
WalkthroughThe change adds versioned live-run state to Runtime Host session catalog projections. Runtime reports running turn IDs. Desktop preserves known state during metadata updates. Renderer and UI logic normalize and display session activity. ChangesLive-run state authority
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: 🟡 Moderate · up to The change can misrepresent an active session when its projected turn data exceeds the protocol limit, causing live-run indicators or session state to fall back incorrectly; merge should wait for this boundedness issue to be fixed or explicitly accepted by the owner. Sequence Diagram(s)sequenceDiagram
participant Runtime
participant RuntimeHost
participant Desktop
participant SessionHistory
Runtime->>RuntimeHost: Report runningTurnIds
RuntimeHost->>Desktop: Return liveRunState in catalog projection
Desktop->>Desktop: Merge live state with incoming summaries
Desktop->>SessionHistory: Provide normalized session summary
SessionHistory->>SessionHistory: Resolve remote and local activity
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR makes Runtime Host the authoritative source of “live run” state for sessions (including a strict distinction between unknown vs known-empty), and wires that through the protocol, Desktop IPC, and UI so running indicators reflect remote/bot/other-window runs while keeping renderer-local optimistic streaming.
Changes:
- Add a versioned
liveRunStateprojection to the Runtime Host session catalog protocol and bump compatibility epoch. - Project/merge live run state through Runtime Host coordinator → Desktop main IPC → renderer state, preserving “absent vs known-empty” semantics across mutation responses.
- Update UI indicators (Host live runs OR local streaming) and add tests + Storybook coverage for the new states.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/ui/stories/session-list-panel.stories.tsx | Adds Storybook coverage for unknown/known-empty/remote-running/local-streaming states. |
| packages/ui/src/session-history-list.tsx | Updates row signal logic to OR Host live runs with local streaming and treat persisted running as fallback only when live state is unknown. |
| packages/ui/src/tests/session-history-row-actions.test.tsx | Adds UI tests covering Host live runs and known-empty behavior. |
| packages/runtime/src/session-manager.ts | Ensures listSessions() projects runningTurnIds even when empty (known-empty). |
| packages/runtime/src/tests/session-manager.test.ts | Adds regression test for preserving known-empty live run state from listSessions(). |
| packages/runtime-host/src/server/session-catalog-coordinator.ts | Projects liveRunState from Runtime authority into catalog query results. |
| packages/runtime-host/src/protocol/session-catalog.ts | Defines liveRunState schema + bounds; decodes it without collapsing absent vs known-empty. |
| packages/runtime-host/src/protocol/index.ts | Bumps RUNTIME_HOST_COMPATIBILITY_EPOCH for the new catalog live-run projection. |
| packages/runtime-host/src/tests/session-catalog-two-client-uds.test.ts | Updates integration expectations to include known-empty liveRunState in catalog reads. |
| packages/runtime-host/src/tests/session-catalog-protocol.test.ts | Adds protocol-level tests for live-run decoding + validation bounds. |
| packages/runtime-host/src/tests/session-catalog-coordinator.test.ts | Verifies catalog queries project known-empty/running state and mutation responses omit live state. |
| packages/runtime-host/src/tests/protocol.test.ts | Updates epoch assertion for the new compatibility epoch. |
| packages/runtime-host/src/tests/authenticated-websocket.test.ts | Updates WS integration expectations to include known-empty liveRunState. |
| packages/core/src/session.ts | Updates SessionSummary.runningTurnIds contract to distinguish known-empty vs unknown. |
| apps/desktop/src/renderer/use-app-shell-session-list.ts | Preserves live-run state across list merges and mutation upserts in renderer state. |
| apps/desktop/src/renderer/settled-session-transients.ts | Adjusts transient-settlement rules to respect known-empty vs unknown running state. |
| apps/desktop/src/renderer/session-status-presentation.ts | Normalizes/merges session summaries to clear stale persisted running only when live state is known-empty. |
| apps/desktop/src/main/runtime-host-session-catalog-ipc-main.ts | Maps Runtime Host liveRunState into Desktop SessionSummary.runningTurnIds without collapsing absent vs known-empty. |
| apps/desktop/src/main/tests/runtime-host-session-catalog-ipc-main.test.ts | Adds unit coverage for the IPC mapping and absent vs known-empty semantics. |
| apps/desktop/src/main/tests/app-shell-session-ui-state.test.ts | Adds tests for renderer merge/normalize semantics and updates settlement expectations. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: cd8784e0-f5e8-4507-9368-2aea13e1c68d
📒 Files selected for processing (20)
apps/desktop/src/main/__tests__/app-shell-session-ui-state.test.tsapps/desktop/src/main/__tests__/runtime-host-session-catalog-ipc-main.test.tsapps/desktop/src/main/runtime-host-session-catalog-ipc-main.tsapps/desktop/src/renderer/session-status-presentation.tsapps/desktop/src/renderer/settled-session-transients.tsapps/desktop/src/renderer/use-app-shell-session-list.tspackages/core/src/session.tspackages/runtime-host/src/__tests__/authenticated-websocket.test.tspackages/runtime-host/src/__tests__/protocol.test.tspackages/runtime-host/src/__tests__/session-catalog-coordinator.test.tspackages/runtime-host/src/__tests__/session-catalog-protocol.test.tspackages/runtime-host/src/__tests__/session-catalog-two-client-uds.test.tspackages/runtime-host/src/protocol/index.tspackages/runtime-host/src/protocol/session-catalog.tspackages/runtime-host/src/server/session-catalog-coordinator.tspackages/runtime/src/__tests__/session-manager.test.tspackages/runtime/src/session-manager.tspackages/ui/src/__tests__/session-history-row-actions.test.tsxpackages/ui/src/session-history-list.tsxpackages/ui/stories/session-list-panel.stories.tsx
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
I’ve resolved the conflicts with the latest The failing Since this is a |
Generated-by: Codex
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
Merge conflicts have been resolved by merging the latest |
|
Thanks for the rework (and sorry for the slow response on the @-mention) — the architecture direction is right and I verified it: live-run truth belongs in the Runtime Host kernel ( Conclusion: PASS with no P0/P1 — but the PR is currently DIRTY and needs rebase, and there are three P2s; two of them must be resolved as part of the rebase, not mechanically. P2-1 — P2-2 — dual authority on Desktop P2-3 — mutation-path merge can resurrect a finished live state. P3 (optional): the AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on 中文摘要(AI 辅助审查)结论:PASS(无 P0/P1)但当前 DIRTY 需 rebase,3 个 P2 里两个必须在 rebase 时做设计决策而非机械解冲突。方向正确:live-run 唯一权威是 Runtime Host 内核 activeRuns(持久化 header 可被 crash 残留、observer 是下游投影、本地 streaming 只覆盖单窗口),以版本化可选字段 liveRunState 投影进既有 catalog 协议(known-empty vs unknown 区分)是扩展现有单一事实源而非并行路径;epoch bump 与 64 上限已接线;测试覆盖面广。P2-1(本 PR 引入的 UI 回归):waiting_for_user/blocked 会话被标为 Responding(脉动 active dot 当 signals[0])——run 从 reserveGenerationRun 到 finalize 都在 activeRuns,权限等待(agent-run.ts:859)时 runningTurnIds 非空;主打场景(远程/第二窗口权限确认)下用户等输入却显示"正在处理",attention dot(明确定义"waiting on a person")被贬到 signals[1]。修复:OR 条件 gate status!=='waiting_for_user'&&!=='blocked' 或加 UI 测试。P2-2(关键):与已合并 #3189 在 Desktop runningTurnIds 双 authority——#3189 observer 投影 obsatruningTurnIds(空时省略)与本 PR 的 Host liveRunState(known-empty 也映射)写同一字段,合并后"observer 非空时覆盖 Host、known-empty 仅 observer 空时保留",settledSessionTransients 两处读取方都会消费;auto-merge 后还保留 #3189 注释"组件不仲裁来源"而逻辑已在仲裁——作者必须裁决该字段归属(Host 内核 vs observer)并补组合测试。其余冲突机械(epoch 23→24、#3159 的 decodeSessionStatus、#3165 的 page() 签名)。P2-3:mutation 路径 merge 会复活已结束 live 状态(incoming.runningTurnIds===undefined 时保留 current),turn 结束(下次 catalog 报 known-empty)与刷新之间任何 mutation(改名/改模型/read-marker)复活 ['turn-live'],markSessionReadLocally 类不走 refresh 的路径窗口无界——加"mutation 省略不复活"测试或显式接受窗口并保证每次 mutation 必刷。P3(可选):projectCatalogLiveRunState 的 Set 去重冗余(内核已去重,协议边界防御可留可删);>64 个唯一 running turns 时整字段静默降级 unknown(行为有界但"截断 vs 省略"应显式决定);renderer 单测放进了 main-process 测试文件;SessionManager 列表 known-empty 投影在生产 Desktop 基本不生效但契约一致性好。 |
|
Follow-up after your rebase — re-verified on head
But P2-1 is still open with no deferral statement, and it's user-visible: Per the review contract this needs one of: (a) a one-line gate — Holding the merge on that one item — everything else is green (epoch 25 chain is clean, schema decode tests pass, 16/16 CI, CLEAN/mergeable). P3 (optional): the 'status-waiting' story doesn't inject AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on 中文摘要复评(head e609776)结论:P2-2/P2-3 已解决,但 P2-1 未修且无显式延后——不能按现状合并。P2-2(双 authority):冲突解决把 #3189 的替换语义改写为并集(runtime-host-session-catalog-ipc-main.ts:366-373),deps 注释明确了归属:Host 内核拥有 known-empty/known-running 语义,Desktop observer 只能追加非空本地观测,不能删除或覆盖 Host 状态;known-empty 映射 [] 后只能被并集追加、永不会塌缩;有稳定性序并集测试 + unknown/known-empty/running IPC 三态测试锁定。P2-3(mutation 复活):保留语义是显式意图 + 3 个新测试钉死边界(mutation 不复活也不清除 in-flight;权威 known-empty 替换陈旧 running 并清 status;列表边界 metadata 替换保留 live authority),handleSessionChange 每次 sessions:changed 都刷新保证陈旧窗口有界——可接受。P2-1(等待用户被标 Responding)still open:session-history-list.tsx:742 仍把 streaming OR runningTurnIds.length>0 推为 signals[0] 无 status gate;权限等待(本 PR 主打场景)时行显示脉动"Responding"而实际在等用户,attention 语义("waiting on a person")被贬到 signals[1];我已用真实组件渲染 {status:'waiting_for_user', runningTurnIds:['turn-1']} 得到 aria-label="Responding";PR 前停车等待行显示 attention dot——这是本 PR 引入的回归。按契约需二选一:(a) 一行 gate(status!=='waiting_for_user'&&!=='blocked')+ UI 测试断言 attention cue 仍首位 + story 'status-waiting' 注入 runningTurnIds;或 (b) 在 PR 中显式声明"等待用户时显示 Responding 是接受的行为"及理由。两者皆无则不能 approve。其余全绿(epoch 25 链干净、schema decode 测试过、16/16 CI、CLEAN)。P3(可选):status-waiting story 未注入 runningTurnIds(与 UI 测试同缺口);缺字面"Host known-empty [] + observer 非空"组合测试(语义已被并集分支覆盖,字面用例更稳);projectCatalogLiveRunState 的 Set 去重冗余;>64 个唯一 running turns 整字段静默降级 unknown("截断 vs 省略"值得显式决定)。 |
Generated-by: Codex
|
@Astro-Han Resolved in |
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for moving the session rail away from durable status: running as its primary execution signal. I reviewed the current head with two independent @reviewer slices plus a read-only ollama-cloud/deepseek-v4-flash:high pass.
The problem is correctly defined: Runtime live turns are ephemeral facts and must come from Runtime/Host state, while the persisted header is only a fallback when live state is unavailable. The implementation keeps that authority in RuntimeKernel.runningTurnIds, projects a known-empty list explicitly, and suppresses “Responding” when the session is waiting for the user or blocked.
I specifically rechecked the apparent Host/observer conflict. The Desktop observer is not a second execution authority inferred from durable state; it is another Host subscription snapshot used for the short synchronization window before the catalog refresh lands. The union is intentional and covered, while terminal attention states take precedence in the UI. I could not establish a concrete stale-state failure that survives the observer's terminal snapshot handling, so I am not promoting that concern to P2.
I found no concrete P0–P2 issue on this head, and current CI is green. A future simplification could version the two live snapshots or eliminate the Desktop supplement once catalog freshness is sufficient, but that is not required for this fix.
No local test suite was run during this review; conclusions are based on source, test, and current CI inspection. Codex coordinated the independent passes and performed the final adjudication; external-model output was treated as unverified until checked against the code.
中文摘要
感谢把 session rail 从持久化的 status: running 迁移到真正的 live execution fact。问题定义正确:Runtime live turns 是瞬时事实,应来自 Runtime/Host;持久化 header 只在 live state 不可用时作为 fallback。
我重点复核了 Host 与 Desktop observer 可能冲突的问题。Desktop observer 不是从 durable state 推断出的第二权威,而是另一个 Host subscription snapshot,用于 catalog refresh 到达前的短同步窗口;union 是有意设计且有测试,waiting/blocked 也会在 UI 中优先。没有找到能越过 terminal snapshot 清理并持续存在的具体 stale failure,因此不将其升级为 P2。
当前 head 未发现具体 P0–P2,CI 全绿。未来如果 catalog freshness 足够,可以给两份 snapshot 加版本或删除 Desktop supplement,但这不是本修复的必要条件。
本次未运行本地测试套件;结论来自源码、测试和当前 CI 检查。Codex 协调了独立审查并完成最终判断,外部模型输出在核对代码前均视为未验证输入。

Summary
Fixes #3059
Verification
npm run lintnpm run format:checknpm run buildnpm run typechecknode-pty-write-lifecycle.test.jscaused by its exact file-descriptor reuse assumptiongit diff --checkVisual evidence: Storybook
LiveRunAuthorityStatescovers local streaming, remote running, known-empty, and unknown fallback states.AI use
Select exactly one:
Tool(s) and scope: Codex implemented the protocol, Runtime Host, Desktop, renderer, UI, Storybook, and test changes; it also ran verification and code review. The human contributor reviewed the issue scope and chose to submit the result.
Checklist
Does this PR entail a change in behavior?