Skip to content

⚡ fix(sidecar): agent-runtime IO 批次——终态回写 O(N²) 消除/总线读增量化/后台恢复死路 (#411) - #457

Merged
CavinHuang merged 4 commits into
mainfrom
fix/411-runtime-io-batch
Aug 22, 2026
Merged

⚡ fix(sidecar): agent-runtime IO 批次——终态回写 O(N²) 消除/总线读增量化/后台恢复死路 (#411)#457
CavinHuang merged 4 commits into
mainfrom
fix/411-runtime-io-batch

Conversation

@CavinHuang

Copy link
Copy Markdown
Owner

三项修复(#411

① settleToolCall 每 tool_result 全量重写 → append-only 侧车行

  • run-state-store.ts: settleToolCall 不再整文件 JSON.parse+重写(长 run 下 O(N²) IO),改为追加一行 tool_settled 侧车记录(O(1))
  • 读取投影 projectSettledItems 物化终态回 tool_call 行;无侧车行时零分配快路
  • compactModelStreamItems(finalize)一次重写完成 model_stream 裁剪 + 侧车物化,文件回归纯净形态
  • countItems 排除侧车行;孤儿侧车行(目标 tool_call 不存在)投影时静默丢弃,与原语义一致
  • 运行中行为不变:【BUG】【运行数据】tool_call 永久 pending 且 runId 与 token 统计口径不一致 #256 终态契约测试(observer 端到端)保持通过

② 事件总线读路径全量扫描 → 头部判定 + 字节水位增量读

  • hasEvents:定位读头部 64KB 判首条非空行;头部无定论回退全量,F4 分叉截断语义严格一致
  • read(afterSeq):ThreadState 记录 readOffset/maxSeqSeen 字节水位,afterSeq 不早于水位时只读新字节段(openSync/readSync 定位读);早于水位或 releaseThread 后回退全量——任意 afterSeq 语义不变
  • 毒行截断、残尾延迟可见(宁晚不毒)与既有 readFile 截断语义对齐

③ waiting_background checkpoint 崩溃恢复死路

  • 崩溃后 live 终态监听已不在,checkpoint 永停 waiting_background;恢复横幅出现但 RESUME_RUN 命中 no-op 分支,文案声称"已重新附着"实际无任何动作
  • LumeResumeService 注入可选 resolveBackgroundNotification(rpc 组装点从 transcript 取 background-process-recovery 落盘的终态通知):有通知则与 live handleAsyncEvent 同形转换(ready_to_resume + syntheticToolResult)真正续跑;无通知则任务可能仍活着(durable 跨重启),如实返回等待态

验证

  • bun run typecheck 6 包全绿
  • runner/events/interruption 分域单跑全绿(含新增 5 个测试:侧车行投影/countItems/compact 收敛/增量 read 水位/waiting_background 两态)
  • rpc 域与组合跑的 fail 经 main 基线对照确认为既有噪声,与本 PR 无关

Closes #411

… O(N²) IO (#411①)

每条 tool_result 触发的整文件 JSON.parse+原子重写在长 run 下是 O(N²) IO。
改为追加 tool_settled 侧车行(O(1)),get() 投影时物化回 tool_call 行,
finalize compactModelStreamItems 一次重写完成裁剪+物化收敛;countItems
排除侧车行。运行中语义不变(#256 终态契约测试保持通过)。
hasEvents 读全量只为看首行:改为定位读头部 64KB,头部无完整非空行时
回退全量判定,F4 分叉语义不变。GET_EVENTS 每次 afterSeq 增量轮询仍整文件
读+parse:ThreadState 记录字节水位(readOffset/maxSeqSeen),afterSeq 不早于
水位时只读新字节段;早于水位或 releaseThread 后回退全量,任意 afterSeq
语义保持。毒行截断与残尾处理与 readFile 严格一致。
③)

崩溃后 live 终态监听(run.handleAsyncEvent)已不在,checkpoint 永停
waiting_background;恢复横幅出现但 RESUME_RUN 命中 no-op 分支,文案谎称
"已重新附着"实际什么都没做。现经注入的 resolveBackgroundNotification 查
background-process-recovery 落盘的终态通知:有则与 live 同形转换
(ready_to_resume + syntheticToolResult)真正续跑,无则如实返回等待态。
@CavinHuang
CavinHuang merged commit 683bb41 into main Aug 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P2][sidecar/runtime] agent-runtime IO 批次

2 participants