Runtime 会话的一致性
Wework 的会话内容归共享会话 Store 所有。任务是否运行、Goal 是否继续和输入框草稿是独立状态,不能用展示消息是否存在来推断历史损坏,也不能在面板里维护另一份可写的会话。
协议与顺序
历史页可能同时包含更早的轮次与当前实时轮次,却缺少本地已经观察到的 Goal 续接轮次。轮次合并与条目合并共用相邻身份锚点插入逻辑,将缺失轮次放回已观察的相邻轮次之间;不能简单追加到实时轮次后面。加载期间为增量补齐前提时也必须使用同一合并入口,避免把拼接顺序登记成原生顺序。尚未绑定原生身份的乐观输入保留在末尾。
诊断快照仅导出设备身份、状态和路由等明确允许的字段,不导出原始云设备或远程连接配置。
当前锁定的 Codex 0.163.0-alpha.5 提供 thread/timeline/list:返回内容按原生 rollout 的 position 排列,首次请求读取最新窗口,nextCursor 向更早的位置分页。单次原生请求最多返回 100 条 timeline entry。执行器普通读取最多组合五页;显式完整导出才遍历剩余历史。cursor 始终视为不透明值,不解析原生 cursor 来推断位置。
thread/items/list 的数组顺序可用,但其 entry 和实时通知都不提供同一个历史位置或快照版本。实时事件的接收顺序、时间戳、工具完成时间和字符串内容都不能作为持久化历史的排序依据。
执行器将 timeline entry 的 position 传到规范化 turn/item;一个源 item 产生多个展示块时保留共同的源位置和稳定的块身份。历史分页、实时更新和重复读取按 item 身份更新,已确认的位置按原生位置排序。相同文本的不同原生 item 必须保留;新增量不含位置时,也不能按文本去重删除缓存中已有原生位置的条目。只有尚未持久化的实时输出可以没有位置,作为临时内容显示;历史页之外的已完成实时缓存不能追加进该页。
原生 threadId 界定位置的有效范围。切换分支或恢复时原生 thread 改变,旧分支的缓存不能与新分支的位置合并;仍在途中的旧 thread 请求必须失效。普通任务切换不清除对应任务的共享会话。
同一 turn 可以跨多个原生页。只有包含其用户 item 或 turn-start 边界的页面拥有合成用户提示的资格;游标携带的 turn 元数据不能把这个归属带到另一页。
持久化条目按原生位置排序;没有位置的运行态条目保留在已观察到的相邻原生身份之间。最新来源明确观察到某项位于最后一个原生边界之后时,该尾部关系必须替换旧缓存中的前置锚点;不含任何原生边界的增量不能抹掉已有锚点。相邻关系只从合并前的各来源序列提取;联合数组中新插入的历史项不能反过来被视为实时输出曾观察到的邻居。历史页缺少某项不代表删除,后台命令和待答问题可能尚未写入 timeline。执行器先将尚未落盘的当前实时条目叠加到原生历史,再一次性投影 turns 和 messages,保证两种接口视图包含相同的当前内容。已完成历史缓存不能参与该叠加。独立的 runtimeTurns 仅承载仍在运行的后台命令及输出,并使用本次原生页中的相邻项作为顺序锚点,不回放缓存文本;前端以原生历史为底、运行态为叠加层,统一按身份归并。只有显式 supersededTurnIds 才会删除旧轮次,并阻止迟到事件复活。用户消息通过同一轮次内唯一的原生用户 item 与宿主发送身份绑定,避免乐观消息重复。
轮次生命周期与未落盘条目相互独立。原生 turns/list 可以在运行态观测尚未同步时合成 interrupted 状态;对于执行器仍持有同一活跃轮次、且 timeline 尚无 turnCompleted 边界的页面,投影必须保持运行,即使实时缓冲区为空或全部条目已经落盘。真实终止边界具有优先权,其标记随分页游标保留,不能被活跃缓冲区重新打开。
用户回答异步问题时,Codex 可以抢占正在生成的正文,并在同一轮继续执行。被抢占的半句可能只有实时条目,没有落盘位置。执行器叠加该条目时,仍须保留实时缓冲区中已完成条目的身份作为相邻锚点,将半句放在后续引导输入之前;不能因为不复制已完成正文就同时丢失这些顺序锚点,也不能把旧半句追加到新进度之后。原生条目之间的既定顺序和位置保持不变。streaming-content 桌面检查点用真实 Codex、异步问题选项点击及模型流抢占覆盖运行中、刷新恢复和最终完成后的顺序与展示。
turn 与 item 使用同一套位置和相邻身份排序规则。最新历史页之外、尚无原生位置的缓存轮次保留在其已观察到的下一原生轮次之前,不能统一追加到会话末尾;否则旧轮次会遮住当前 Goal 输出,并被误认为当前活跃回复。仍在进行的新轮次在尚未观察到后继原生身份时保持在尾部。分页合并不得使用合并后的数组为旧缓存制造新的相邻关系。
用户消息的轮次身份必须使用所属 turn 的规范 ID,不能保留请求阶段的旧别名。编辑或重试替换轮次时,执行器根据已保存的原生映射同时记录请求别名和原生 ID 的 supersession,保证乐观缓存、原生历史和刷新后的历史都移除同一旧轮次。
数据流和恢复
后端通过仅含状态的 Runtime 快照确认执行完成时,在同一次终态事务内保留已绑定轮次的对账标记。随后到达的最终正文只有在执行、项目、任务和轮次一致,执行根记录仍为完成状态,且事件序号更新时才能补齐;补齐正文不能重复推进业务流程。带有执行关联但找不到执行记录的活动必须拒绝补写。
Goal 通知属于线程,可以在续接请求启动时携带上一请求的轮次身份。它们不得更新当前执行的轮次绑定、租约或运行状态;执行生命周期由当前轮次的响应事件推进,避免旧轮次快照提前完成新执行。
历史规范化和展示消息从同一次处理产生。原生位置决定条目顺序,展示分组则使用明确的用户边界:首条普通用户输入开启同一回复,输入前的上下文压缩等处理不会额外生成助手回复;runtimeGuidance 标记的引导输入建立新的展示分段。引导消息可以把一轮拆成多个展示段,但文件变更等轮次级信息必须从整轮汇总,不能只取末段。原生主流程不能从展示 messages 反向拼回 turns。其他运行时和 legacy 历史的既有适配保持明确的协议边界。
源位置登记仅遍历当前展示段中尚未登记的条目身份,不构造或复制其正文 JSON。每个身份最多登记一次;首次有位置的事件为此前尚无位置的条目提供位置,重复身份保留首次位置。展示段结束后清空登记进度。仅在输出展示段时物化完整 runtimeItems,避免长轮次逐条重建累积历史造成平方级开销。单元回归覆盖 4,000 个带位置、含 2 KiB 正文的事件,并保留宽松的调试构建耗时上限。
编辑或重试产生的 superseded turn 标记在规范化前过滤原生 turn,保证两种视图一致。元数据读取复用既有启动重试,只重试协议明确的暂未就绪错误,永久错误仍向调用方报告。
切换任务、连接恢复和生命周期协调通过 synchronizeRuntimeConversation 读取:相同请求合并,同一会话的竞争读取串行提交,不同会话独立推进。请求取消或任务归档后,迟到结果不能重新创建会话。只读取导航元数据不应冻结或改写会话。
读取期间仍立即发布实时更新,同时记录用于提交的更新集合。工具输出等追加增量先基于已观察的状态形成结果,再与原生历史合并,避免对已包含该增量的历史重复追加。文本更新按稳定 item 身份协调;保留原生快照已经包含的完整前缀。该策略没有宣称上游提供了不存在的原子版本或水位。
子线程查看是只读投影,不采纳为父任务的新 thread,也不更新父任务上下文用量。父任务的恢复写入与子代理面板的读取必须分开。
已发送消息的技能目录读取按实际工作目录绑定。无关任务快照更新不得改变读取回调身份并清空已加载目录;工作目录切换和插件目录变更仍须使对应读取失效。
共享缓存立即处理结构与文本更新;React 订阅按动画帧合并视图通知,避免大量 item 完成事件触发逐项同步渲染。订阅不持有另一份消息状态。
历史快照、实时块创建和块更新共用同一块归并入口。晚到的块不能用较短输出覆盖已经观察到的命令输出,也不能删除同一子线程已观察到的子项;追加增量先物化,再执行该归并。
实时动作仅在到达时发布一次。水合完成或终止只发布快照变化,不能再次回放动作给订阅者,否则会重复触发副作用。
运行态计时表示本机观察到的生命周期区间:沿用已展示的起点,在实时事件或恢复快照首次确认结束时,使用同一本机墙钟冻结结束时刻与时长。重复完成通知和后续原生快照保留已经冻结的区间。首次读取就已完成的历史保留原生时长。Codex 的开始、结束时间按秒提供,而 duration 按毫秒计算,不能用秒级起点加毫秒时长来重建精确结束时刻,也不能在运行中和完成后切换计时来源。
发送确认仅为乐观轮次绑定原生身份,保留从待发送阶段开始的观察起点。任务标题独立于消息内容:手动改名与自动命名共用保存、发布标题事件的入口,让已经订阅的工作台同步收到元数据变化。
已结束轮次的延迟运行快照不能确认尚未接受的发送请求;发送失败后,任务必须能回到空闲。只有发送已接受时,才允许尚未更新轮次 ID 的运行快照清除异步等待状态。带有真实新轮次 ID 的快照可以先于发送确认到达,并保留已经确认的执行。
已加载的原生历史由分页和会话缓存生命周期控制,不得再被实时临时块的数量限制截断。临时输出仍受原有的大小与数量限制。Goal 只投影执行状态;事件缺失、连接恢复等明确的恢复原因由同步层处理。
阅读位置
底部跟随保存的是跟随意图。阅读历史时,快照保存 message/item 身份、可用的文本偏移及视口位置;恢复时先提供初始虚拟位置,再由滚动控制器定位相同内容。内容暂时未挂载时保留待恢复快照,在布局提交后继续定位。展示段使用 item 身份作为 React key,不能用数组下标承载展开状态或阅读身份。
验证
锁定二进制已在隔离的 Codex Home 中验证 510 个合成 item 的六页读取:身份唯一,位置单调,原生单页上限为 100。该协议验证只使用隔离合成数据库;产品通过公开 RPC 读取历史,不读取 Codex 内部数据库。
自动化回归包括:已有错误顺序的修正、重叠分页的不同到达顺序、重复读取、相同内容的不同身份、历史和工具增量的竞态、超过 500 条历史后的实时更新、归档期间的迟到结果、thread 替换和任务快照切换。
桌面回归 streaming-conversation-switching 已注册到共享 checkpoint 和 CI 套件。它只模拟模型响应,使用真实执行器产生超过 500 个 item,在任务切换期间继续输出,验证恢复后身份与顺序不变且内容不重复。按仓库执行策略,只有明确要求时才运行桌面 E2E 和 ai:verify;注册覆盖不等于已执行验证。