Skip to content

Latest commit

 

History

History
340 lines (238 loc) · 12.1 KB

File metadata and controls

340 lines (238 loc) · 12.1 KB

OpenCode XK Workflow Stability PRD

文档信息

  • 状态:Draft
  • 目的:作为本地 opencode 维护 fork 后续开发与修复的统一执行依据
  • 适用范围:session / workflow / recovery / retry / task / notification / sync

一、背景

当前仓库是本地维护的 opencode fork,目标不是追求功能扩张,而是维持 opencode-xk 在真实使用中的工作流稳定性。

现状有三个事实:

  1. 本地 fork 与上游存在明显分叉,且核心差异集中在工作流稳定性链路。
  2. 本地已经形成一套有价值的补丁体系,重点覆盖 session/controlprompt_async 交接、global-syncnotificationrecovery
  3. 上游近期仍在持续修复 retry / session / task / notification / TUI lifecycle,说明当前问题不是个别 fork 私有问题,而是产品主线问题。

本 PRD 的目标不是重写架构,而是在保留本地有效补丁的前提下,持续吸收上游有价值修复,并补齐本地仍未根治的问题。

二、产品目标

2.1 总目标

把本地 opencode fork 稳定在“多轮会话不漂移、异步提示可可靠接管、重试边界正确、子任务不中断主流程、通知不过载、恢复不误伤”的状态。

2.2 具体目标

  1. prompt_async 在 idle 与 busy 两种状态下都能可靠接管会话。
  2. 保证异步注入消息不会覆盖会话当前 active agent/model。
  3. 保证 retry 只发生在真正可恢复的错误上。
  4. 保证 wrapped provider error 与 stream 中断可以进入正确的 retry 边界。
  5. 保证非法 task_id 不会卡死 subagent 创建流程。
  6. 保证 session 恢复、列表刷新、消息同步、通知派发之间状态一致。

三、非目标

  1. 不在当前阶段推动大规模架构重写。
  2. 不以“同步上游全部功能”为目标。
  3. 不为了代码整洁而删除本地已验证有效的 workflow 补丁。
  4. 不优先处理与当前主线无关的新功能需求。

四、核心问题定义

当前需要持续解决的问题分为六类:

  1. 会话控制问题

    • 旧任务继续执行
    • 最新用户意图被历史 handoff 或 reminder 覆盖
    • todo / task summary 干扰当前回合
  2. 异步交接问题

    • prompt_async 返回成功但会话未真正起跑
    • 前端 optimistic message 与后端真实接管不同步
    • 外部调用方无法确认会话是否已接受消息
  3. retry 边界问题

    • 非瞬时额度限制被无限重试
    • wrapped responses 错误未进入 retry 链路
    • Bun stream 中断直接打断 session
  4. 子任务问题

    • 非法 task_id 直接导致 subagent 创建失败
    • 子任务结果回灌与主任务 handoff 关系复杂
  5. 同步与恢复问题

    • session 列表、消息、todo、diff、status 出现陈旧覆盖
    • 历史 session 打开时出现 Session not found
    • 恢复逻辑可能误伤正在运行的 session
  6. 通知与界面状态问题

    • 多窗口重复通知
    • idle / error / abort / completion 事件串扰
    • TUI 页面切换后的订阅泄漏风险

五、用户价值

该项目的直接用户价值不是“多一个功能”,而是:

  1. 用户发出的最新指令能被当前会话正确执行。
  2. 会话在长时间运行、重试、恢复、切换页面后仍然可控。
  3. 子任务、工具调用、通知、恢复链路不会相互放大错误。
  4. 用户可以稳定地用本地 opencode-xk 做真实工作,而不是被工作流问题打断。

六、必须保留的本地资产

以下能力属于本地 fork 的核心资产,后续吸收上游修复时默认保留,不得被覆盖式回退。

6.1 后端控制层

关键文件:

  • packages/opencode/src/session/control.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/session/recovery.ts

核心职责:

  • 最新真实用户消息优先
  • 区分 redirect / pure_continue / mixed_continue / new_request
  • 清理旧 reminder 对新回合的污染
  • 决定 assistant 完成后的 continue / reconcile / exit
  • 仅在安全状态下执行 recovery

6.2 前端异步交接层

关键文件:

  • packages/app/src/components/prompt-input/submit.ts
  • packages/app/src/components/prompt-input/pending-state.ts

核心职责:

  • prompt_async 增加 handoff / acceptance 确认
  • 管理 optimistic message
  • 管理提交中的 pending 状态

6.3 同步与恢复层

关键文件:

  • packages/app/src/context/global-sdk.tsx
  • packages/app/src/context/global-sdk-stream.ts
  • packages/app/src/context/global-sync.tsx
  • packages/app/src/context/global-sync/event-reducer.ts
  • packages/app/src/context/sync.tsx

核心职责:

  • SSE 重连与事件缓冲
  • part delta 合并
  • revision 防止旧数据覆盖新状态
  • session list / message / todo / diff / status 一致性维护

6.4 通知层

关键文件:

  • packages/app/src/context/notification.tsx
  • packages/app/src/context/notification-helpers.ts

核心职责:

  • 去重
  • 延迟确认 idle
  • 避免 error / abort / completion 串扰

七、当前已确认的根因与判断

7.1 已确认未根治的问题

  1. prompt_async 的前端补偿逻辑仍然存在,但不能替代服务端语义保证。
  2. notification / multi-window / TUI listener lifecycle 仍需持续监控是否有新回归。

7.2 当前判断

后续开发必须坚持以下原则:

  1. 优先修工作流正确性,再谈结构收敛。
  2. 上游修复只吸收正确部分,不覆盖本地稳定性补丁。
  3. retry.tsmessage-v2.ts 视为高风险区域,所有修改都必须配测试。

八、开发优先级

P0:低冲突高收益修复

P0-1 非法 task_id 兜底

  • 状态:已完成并验证

  • 目标:无效 task_id 不再阻止 subagent 启动

  • 参考上游:PR #19328

  • 主要文件:

    • packages/opencode/src/tool/task.ts
    • packages/opencode/test/tool/task.test.ts
  • 要求:

    • 在复用 session 前先校验 task_id
    • 无效时直接走创建新 session 分支
    • 不破坏当前本地 task metadataTaskResult 结构

P1:修正 retry 停止条件

P1-1 停止重试非瞬时额度错误

  • 状态:已完成并验证

  • 目标:weekly/monthly/quota exhausted 等错误直接停止 retry

  • 参考上游:PR #24013

  • 主要文件:

    • packages/opencode/src/session/retry.ts
    • packages/opencode/test/session/retry.test.ts
  • 要求:

    • 只吸收判断逻辑,不覆盖本地已有 retry 补丁
    • 保留本地对 shell interrupt 与 workflow 相关的行为修正

P2:修正 retry 进入条件

P2-1 wrapped responses server error 进入 retry 链路

  • 状态:已完成并验证

  • 目标:provider 返回 wrapped server_error 时进入正常 retry 流程

  • 参考上游:PR #22022

  • 主要文件:

    • packages/opencode/src/session/message-v2.ts
    • packages/opencode/test/session/processor-effect.test.ts
    • packages/opencode/test/lib/llm-server.ts
  • 要求:

    • 不破坏本地 toolOutput()active messagetail() 等自定义逻辑

P2-2 Bun stream 中断进入 retry 链路

  • 状态:已完成并验证

  • 目标:stream 连接异常视为瞬时错误

  • 参考上游:PR #24076

  • 主要文件:

    • packages/opencode/src/session/message-v2.ts
    • packages/opencode/src/session/retry.ts
  • 要求:

    • 和 P2-1 同一轮收口
    • 统一错误映射与 retryable 模式,不各自叠补丁

P3:服务端补齐 prompt_async 根因

P3-1 保留当前 active agent/model

  • 状态:已完成并验证

  • 目标:异步注入消息不覆盖会话当前 agent/model

  • 参考问题:Issue #21728

  • 主要文件:

    • packages/opencode/src/session/prompt.ts
  • 要求:

    • prompt_async 未传 agent/model 时,优先读取会话最近有效上下文
    • 不再默认落回默认 agent 配置

P3-2 提升 idle session 唤醒可靠性

  • 状态:已通过真实 HTTP 服务回归验证,当前不需要额外代码修复

  • 目标:prompt_async noReply=false 能稳定拉起 idle session

  • 参考问题:Issue #21524

  • 主要文件:

    • packages/opencode/src/server/instance/session.ts
    • packages/opencode/src/session/run-state.ts
    • packages/opencode/src/session/prompt.ts
  • 要求:

    • 提高服务端侧的“接收成功 = 实际接管成功”一致性
    • 不只依赖前端补偿逻辑

P4:TUI 生命周期修补

P4-1 组件卸载时清理事件订阅

  • 状态:已完成并通过类型检查

  • 目标:避免 TUI 切换页面或 session 后 listener 泄漏

  • 参考上游:PR #24053

  • 主要文件:

    • packages/opencode/src/cli/cmd/tui/app.tsx
    • packages/opencode/src/cli/cmd/tui/context/*
    • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
  • 要求:

    • 仅在确认存在 TUI 长时运行问题时推进
    • 不优先于 P0-P3

九、实现约束

  1. 默认采用最小充分变更,不做无关重构。
  2. 吸收上游修复时优先“手工并入逻辑”,不要直接覆盖本地关键文件。
  3. retry.tsmessage-v2.tsprompt.tsglobal-sync.tsxsubmit.ts 属于高风险文件,改动必须带针对性测试。
  4. 不移除本地 control.ts,除非上游已经提供等价且经过验证的控制层能力。
  5. 不把前端补偿当作服务端根修;凡是 API 语义问题,最终都应落回服务端处理。

十、验收标准

10.1 功能验收

  1. 传入非法 task_id 时,subagent 仍能创建并返回有效 task_id
  2. 遇到 weekly/monthly/quota exhausted 类错误时,session 停止 retry,并向用户暴露明确错误。
  3. 遇到 wrapped responses server_error 时,session 进入 retry 流程,而不是直接落成 UnknownError。
  4. 遇到 Bun stream 中断时,session 自动重试,而不是直接终止。
  5. prompt_async 未指定 agent/model 时,下一轮 assistant 使用当前会话 active agent/model。
  6. idle session 收到 prompt_async noReply=false 后能实际开始 assistant turn,而不只是返回 204。
  7. TUI 组件卸载后不会继续保留旧事件订阅与定时器引用。

10.2 回归验收

以下本地能力不得回退:

  1. 最新用户消息优先于旧 handoff
  2. todo reconcile 提醒仍然生效
  3. optimistic message 与真实消息能正确对账
  4. 多窗口通知不出现明显重复回归
  5. session route recovery 仍能处理 Session not found

十一、测试要求

开发完成后,按最小相关范围先跑针对性测试,再补类型检查。

推荐顺序:

  1. packages/opencode 内相关单测
  2. packages/app 内相关单测
  3. bun typecheck(在对应 package 目录执行)

最低测试要求:

  • test/tool/task.test.ts
  • test/session/retry.test.ts
  • test/session/processor-effect.test.ts
  • test/session/prompt.test.ts
  • test/server/session-flow-routing.test.ts
  • packages/app/src/components/prompt-input/submit.test.ts
  • packages/app/src/context/notification.test.ts
  • packages/app/src/context/global-sync*.test.ts

十二、风险与注意事项

  1. 当前工作区关键文件可能存在并行未提交改动,后续开发必须以“读当前文件实际内容”为准,而不是只依赖历史结论。
  2. retry.tsmessage-v2.ts 同时涉及上游待吸收修复和本地未提交改动,冲突概率高。
  3. prompt_async 的前端补偿逻辑目前有价值,但不能掩盖服务端根因问题。
  4. app-runtime 历史上存在一组 layer 裁剪与回补提交,这部分属于技术债,不应在当前阶段继续扩大范围。

十三、后续开发执行顺序

按以下顺序推进:

  1. 维持已完成项的回归稳定性
  2. 持续关注 prompt_async 与 notification 相关真实使用回归
  3. 如有新的 TUI 长时运行问题,再扩展 #24053 同类清理点

十四、成功定义

当以下条件同时满足时,可认为当前阶段 PRD 达成:

  1. 本地 fork 的关键 workflow 不再频繁出现“旧任务漂移、假成功、错误重试、恢复误伤”。
  2. 上游高价值修复被吸收后,没有破坏本地已有稳定性补丁。
  3. 后续新增问题可以稳定收敛到少数关键文件,而不是在整条链路上随机发散。