{"content":"IDBots Co-Worker 运行时 Steer 规格审查修复日志\n\nCommit: 7a19f184e02e87f3ccd0f8c43abaf8d34a7584e4\nfix: harden cowork steer runtime lifecycle\n\n本次针对 Task 3 规格审查的两个 P1 finding 完成独立修复。\n\nFinding 1:Runner Stop 原先调用 CoworkSteerChannel.abort(Error)。真实 Claude Agent SDK 的 query() 会以 detached 方式调用 streamInput(prompt),streamInput 只吞 SDK AbortError;普通 Error 从 AsyncIterator reject 可能形成未处理 Promise rejection。修复后保留 abort(error) 的原有显式异常语义(delivery reject + iterator reject),另增 runner 专用 stop(error):所有尚未交付的 in-flight/pending delivery Promise 仍会 reject,供上层标记 cancelled;但 SDK input iterator 被唤醒并正常返回 done,不再向 detached streamInput 抛普通 Error。Runner 随后照常 abort AbortController,停止 query。fake SDK 同步收紧为真实规则,不再因为 controller aborted 而吞普通 iterator Error。\n\nFinding 2:ActiveSession 创建到 runClaudeCodeLocal 打开 channel 前存在 async setup 窗口,旧状态 none 会允许 concurrent continueSession 启动第二个 runner。修复新增 localTurnState=starting,并从 ActiveSession 创建时立即生效;Continue 在 local starting/open/closing 均明确拒绝。判断仍采用显式状态枚举,因此既有 retained-active 测试夹具的 undefined 状态不会被误判,跨会话历史兼容保持。\n\nTDD:先新增 channel stop 契约测试,RED 为 channel.stop 不存在;新增 setup-race 测试冻结 runClaudeCode setup,RED 观测 concurrent runCalls=2。GREEN 后 channel 测试覆盖 in-flight 与 queued delivery 均拒绝、iterator 正常 done;runner 测试使用不吞普通 Error 的 fake SDK 验证 Stop 无 iterator rejection/unhandled path,并验证 setup 期间只有一次 runner 调用。\n\n最终验证:compile:electron exit 0;coworkSteerChannel、coworkRunnerSteer、coworkCrossSessionRunner、privateChatScopedMemory 共 34/34 通过;限定 ESLint exit 0;npm run build exit 0(仅既有 Vite chunk 与 dynamic-import warnings)。未 push。","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}