Skip to content

[Track] Codex app-server 协议支持追平:底层 carrier 先行,产品展示分阶段承接 #689

Description

@kxn

背景

我们需要把 openai/codex 最新 app-server 协议面和本仓库的 relay / Feishu Remote / headless 能力重新对齐。

当前判断:产品展示可以分阶段,但底层协议 carrier 不能长期只依赖 VS Code 透传。 透传能保证 native client 不坏,但不等于 daemon、relay、Feishu Remote、headless 已经理解这条状态机。

本 issue 是 parent tracker,用于把协议追平工作调研到可拆计划、可恢复、可执行的程度。它不直接承诺一次性实现所有协议面,也不要求所有能力立刻做成 Feishu 卡片或菜单。

目标

  1. 建立当前 upstream app-server method surface 与本仓库支持状态之间的稳定对照,不再靠人工记忆判断“是否支持”。
  2. 把每个协议面明确分类到目标层级:pass-through-onlycanonicalizedstate-onlyproduct-visibleheadless-drivenunsupported-fail-closed
  3. 优先补齐重要 passive notification / server request 的底层 carrier,使 relay / daemon / Feishu Remote / headless 能保真识别协议事实。
  4. 明确哪些能力暂不产品化,只要求 wrapper / native path 不破坏。
  5. 产出可执行子 issue 拆分、依赖顺序、验证面和收尾标准,避免形成一个不可交付的巨型 PR。
  6. 单独建立 high-frequency streaming / delta 策略:飞书 Remote 不做 typewriter client;能等 final item 或 snapshot 的事件默认走 final-onlylatest-onlycoalesced,不把 raw delta 直接变成飞书 patch。

范围

本 parent issue 覆盖协议追平的调研、分类、拆分和总调度,不直接承载生产实现。

纳入范围:

  • upstream app-server ServerNotification / ServerRequest / 关键 ClientRequest method coverage。
  • wrapper pass-through 与 relay/headless canonicalization 边界。
  • passive notification carrier、server request policy、state-only carrier 的拆分计划。
  • 后续产品投影 issue 的输入条件和非目标。

不纳入范围:见 非目标

非目标

  • 不在本 parent issue 内直接实现所有子项。
  • 不一次性开放所有 app-server ClientRequest 主动驱动。
  • 不把 realtime、fs watch、fuzzy search、plugin marketplace、file-system RPC 等 native-heavy 能力硬塞进 Feishu 聊天主链。
  • 不为飞书实现逐 token / 逐 chunk 的打字机效果;除非后续有单独产品方案、频控预算和降级路径,否则高频 delta 不进入 product-visible patch。
  • 不用永久 raw JSON 替代 typed carrier;raw-safe carrier 只能作为受控过渡或诊断用途。
  • 不静默吞掉不认识的 server request。
  • 不把“VS Code 透传可用”写成“Feishu Remote/headless 已支持”。

完成标准

作为 parent tracker,本 issue 完成时应满足:

  • current upstream app-server method coverage manifest 或等效 drift test 已落地,能发现新增/未分类 method。
  • coverage manifest 需要记录 cadenceauthoritativeFinalfeishuProjectionPolicyheadlessOptOutCandidate,确保新增 method 不会默认进入飞书高频刷新。
  • 当前 upstream 的 ServerNotificationServerRequest、关键 ClientRequest 都有明确支持策略分类。
  • 第一批重要 passive notification 已进入 canonical carrier 或 state-only carrier,并有 translator 单测证明关键字段未丢失。
  • 未产品化协议面有明确 policy:pass-through-onlystate-onlyunsupported-fail-closedlater-product
  • 未支持 server request 不会被静默吞掉;要么继续透传给 native client,要么 fail-closed 并可审计。
  • docs/inprogress/codex-app-server-state-machine-audit.mddocs/general/relay-protocol-spec.md 或后续确定的 canonical docs 已同步。
  • 子 issue 的结果已回卷到本 parent issue,总调度表显示全部完成或明确剩余后续。
  • parent close 前需要独立 verifier pass,除非当时明确记录跳过理由。

当前确认基线

调研日期:2026-07-12。

上游 Codex:

  • 仓库:openai/codex
  • 本地核对路径:/tmp/openai-codex-latest
  • HEAD:9e552e9d15ba52bed7077d5357f3e18e330f8f38
  • 时间:2026-07-11T21:03:12Z
  • subject:Use available width for skill names in the toggle view (#32485)

本次提取到的 upstream method surface:

  • ServerNotification:69 个 method。
  • ServerRequest:10 个 method。
  • common.rs client/server/notification 总 method surface:197 个 method 定义。

当前 VS Code 扩展邻接事实:

相关文档

  • docs/general/codex-mcp-app-server-protocol.md
  • docs/inprogress/codex-app-server-state-machine-audit.md
  • docs/draft/app-server-third-batch-product-directions.md
  • docs/general/relay-protocol-spec.md
  • docs/general/remote-surface-state-machine.md
  • docs/general/feishu-card-ui-state-machine.md
  • docs/general/feishu-card-api-constraints.md
  • docs/draft/plan-mode-feishu-support-design.md
  • upstream:/tmp/openai-codex-latest/codex-rs/app-server-protocol/src/protocol/common.rs
  • upstream:/tmp/openai-codex-latest/codex-rs/app-server-protocol/schema/typescript/ServerNotification.ts
  • upstream:/tmp/openai-codex-latest/codex-rs/app-server-protocol/schema/typescript/ServerRequest.ts

涉及文件

预计涉及但不限于:

  • internal/adapter/codex/translator_observe_server.go
  • internal/adapter/codex/translator_observe_server_lifecycle.go
  • internal/adapter/codex/translator_observe_client.go
  • internal/adapter/codex/translator_commands.go
  • internal/adapter/codex/translator_helpers_request.go
  • internal/core/agentproto/types.go
  • internal/core/agentproto/*
  • internal/core/state/types.go
  • internal/core/orchestrator/service.go
  • internal/core/orchestrator/service_*.go
  • internal/app/wrapper/app_io.go
  • internal/app/wrapper/app_headless.go
  • testkit/mockcodex/*
  • docs/general/*
  • docs/inprogress/*

当前代码事实

wrapper / native path

internal/app/wrapper/app_io.go 的行为是:

  • parent stdin:translator 解析失败或未 suppress 时,原始帧继续转发给 Codex child。
  • child stdout:translator 未识别但 JSON 可解析时,通常不会 suppress,原始帧继续写回 parent stdout。
  • 结论:很多未知 upstream method 在 VS Code/native client 路径上“不坏”,但 relay/daemon 不会因此得到 canonical event。

headless / relay path

headless 已补 initialize -> initialized synthetic bootstrap,但只有 translator / agentproto / orchestrator 明确建模的 method 才能进入 remote/headless 状态机。

这说明当前关键风险不是“所有未知 method 都破坏 VS Code”,而是:Remote/headless 可能长期只看到自己认识的一小截协议面。

当前 Feishu 频控与 delta 使用事实

当前飞书约束不是抽象性能问题,而是产品边界:

  • docs/general/feishu-card-api-constraints.md 已固化当前基线:普通消息卡片 patch 单消息 5 QPS,CardKit 单卡 streaming/update 约 10 次/秒,同一用户/群消息发送也有 5 QPS 量级约束,卡片还受 30 KB200 元素等约束。
  • 当前 headless synthetic initialize 只设置了 optOutNotificationMethods: ["item/agentMessage/delta"]
  • wrapper 的 relayEventCoalescer 只做 relay 传输侧的短窗口合并(默认 75ms / 16KB),不是飞书产品可见策略。
  • orchestrator 的 trackItemDelta 会缓存文本 delta;completeItemitem/completedtext 时会用完整文本覆盖/替换 buffer;agent_message 最终仍等 completed item / turn final 后投影。
  • reasoning summary delta 当前只在可见 reasoning 的 verbosity 下展示,并按约 1s 窗口合并;这已经符合“不逐 delta patch 飞书”的方向。
  • turn/diff/updated 当前按 (threadId, turnId) 只保留最新 authoritative diff snapshot,最终挂到 final summary 上。
  • turn/plan/updated 当前按结构化 snapshot 去重;它不是逐 token delta,但仍可能多次产生产品卡,后续若噪声变高,应走 latest-only / bounded cadence,而不是逐 update patch。
  • 现有 plan mode 文档里把 item/plan/delta 说成“最终提案计划正文”的表述需要修正:upstream PlanDeltaNotification 注释明确说客户端不应假设拼接 delta 等于 completed plan item content。提案计划应优先使用 item/completed 的 plan item text

已较好支持,不应重复当成新增范围

  • 主 turn 链路:thread/start|resume|fork -> turn/start -> turn/started -> item/* -> turn/completed
  • turn/steer,包括 expectedTurnId 语义。
  • turn/interrupt -> turn/completed(status=interrupted)
  • thread/status/changed 已进入 thread.runtime_status.updated
  • thread/tokenUsage/updated
  • turn/plan/updated 和结构化 planSnapshot
  • turn/diff/updated 和 authoritative turn diff snapshot。
  • model/rerouted 已转成 turn.model_rerouted,保留 fromModel / toModel / reason,并更新 thread 当前有效模型。
  • 常见 item lifecycle / delta 的 parser 层识别:item/starteditem/completeditem/agentMessage/deltaitem/plan/deltaitem/reasoning/textDeltaitem/reasoning/summaryTextDeltaitem/commandExecution/outputDeltaitem/fileChange/outputDelta。但“translator 能识别 delta”不等于“飞书 product-visible 支持 delta”。
  • item/mcpToolCall/progress
  • request surfaces 主路径:command/file approval、item/permissions/requestApprovalmcpServer/elicitation/requestitem/tool/requestUserInputitem/tool/call 的 fail-closed unsupported 回写。
  • thread/compact/start 相关压缩路径。

高频流式事件策略

产品原则

飞书 Remote 不应实现 Codex native / IDE client 的 typewriter 效果。原因不是 UI 偏好,而是飞书消息、卡片 patch、CardKit streaming 都有单消息/单卡/单群维度频控和体积上限。

默认规则:

  • 如果 upstream 后续会发送 authoritative final item 或 authoritative snapshot,飞书侧不要把 raw delta 逐条投影;默认使用 final item、latest snapshot,或低频 coalesced progress。
  • 如果某个 streaming output 没有 final duplicate,不能简单 opt-out 或丢弃;在 Feishu Remote 未产品化前只能标 pass-through-only / native-only,不能 claim 支持。
  • wrapper/native VS Code 路径不应强加飞书 opt-out;VS Code 自己拥有打字机和 live terminal UX。
  • headless / cron synthetic initialize 可以按飞书产品策略使用 optOutNotificationMethods,但必须经过测试确认不会丢失最终语义。
  • 产品可见层的默认策略枚举:ignorefinal-onlylatest-onlycoalescedstate-onlypass-through-onlyproduct-visible

upstream 证据

  • initialize.params.capabilities.optOutNotificationMethods 是连接级精确 method 名 opt-out;未知 method 会被忽略;只作用于 app-server typed notifications,不作用于 requests / responses / errors。
  • app-server item 生命周期是 item/started -> zero or more item-specific deltas -> item/completed;README 明确要求把 item/completed 当作 authoritative execution/result state。
  • 当前 turn/completed.turn.items 仍可能为空;直到 upstream 修复前,canonical item list 不能只靠 turn/completed,仍要消费 item/completed
  • ThreadItem final 形状包含关键完整值:agentMessage.textplan.textreasoning.summary/contentcommandExecution.aggregatedOutput/status/exitCode/durationMsfileChange.changes/statusmcpToolCall.result/error
  • PlanDeltaNotification 是 experimental,并且 upstream schema 注释写明:不要假设拼接后的 plan delta 等于 completed plan item content。
  • turn/diff/updated 是 turn 级最新聚合 diff snapshot;turn/plan/updated 是结构化 plan snapshot。它们是 snapshot,不是 token delta,但可能重复更新,飞书侧仍应 latest-only / dedupe / bounded cadence。
  • command/exec/outputDeltaprocess/outputDelta 属于独立 process API;当 streaming 开启时,streamed bytes 不会在最终 response / process/exited 中重复。这类不能按 turn item delta 一样直接丢。
  • realtime transcript 有 thread/realtime/transcript/delta 与最终 thread/realtime/transcript/done;audio delta 是高频媒体流,且本身不属于 ThreadItem

策略矩阵

Method cadence authoritative final / snapshot Feishu projection policy headless opt-out 判断
item/agentMessage/delta stream-delta item/completedagentMessage.text final-only;不做打字机 patch;当前 headless 已 opt-out 已启用,保留
item/plan/delta stream-delta / experimental item/completedplan.textturn/plan/updated 只承接 checklist snapshot 不产品化 delta;提案计划应以 completed plan item 为准;delta 只可作为低置信兼容缓存 候选,但要先补“completed plan 覆盖 delta mismatch”回归测试
item/reasoning/summaryTextDelta stream-delta item/completedreasoning.summary 默认不单独刷屏;若用户开启可见 reasoning,只允许约 1s coalesced + final flush 候选配置项;默认是否 opt-out 取决于 chatty/verbose 产品承诺
item/reasoning/textDelta stream-delta item/completedreasoning.content Feishu 默认忽略;仅 debug/native 需要 raw reasoning text 候选
item/commandExecution/outputDelta stream-delta turn item final commandExecution.aggregatedOutput/status/exitCode/durationMs 不逐 delta patch;命令进度依赖 started/completed;若未来显示 live output,必须低频 coalesced 候选,但需先验证 final aggregatedOutput 覆盖当前需求
item/fileChange/outputDelta deprecated stream-delta server 已不再发;最终走 fileChange item / turn/diff/updated ignore / legacy compat 候选
item/fileChange/patchUpdated repeated snapshot item/completedfileChange.changes/status + turn/diff/updated latest-only state;不做实时 patch preview 卡 候选,前提是不做 live patch preview
turn/diff/updated repeated snapshot 事件自身就是最新 turn diff snapshot 保存 latest,最终挂到 final summary;不逐 update 发卡 暂不 opt-out
turn/plan/updated repeated snapshot 事件自身是结构化 checklist snapshot dedupe / bounded cadence;可产品展示“有意义变化”,但不是打字机 暂不 opt-out
thread/tokenUsage/updated repeated state latest thread usage state state-only / final summary;不单独发卡 暂不 opt-out
item/mcpToolCall/progress progress messages final mcpToolCall.result/error 不一定覆盖所有 progress 文案 可做 coalesced / dedup 进度;不按 raw progress 高频 patch 暂不 opt-out
model/safetyBuffering/updated transient state 不持久化到 rollout history state-only;后续如展示也应是低频状态说明 暂不 opt-out
thread/realtime/transcript/delta stream-delta thread/realtime/transcript/done.text Feishu 若未来支持 realtime,也应忽略 delta、消费 done 候选
thread/realtime/outputAudio/delta high-frequency media stream 无 Feishu 文本最终副本 native/pass-through-only;Feishu Remote 不支持音频流 候选
command/exec/outputDelta standalone process stream streaming bytes 不复制到 final response native/pass-through-only;除非另做 terminal 产品,否则 Feishu 不 claim 不默认 opt-out,避免未来主动发起 streaming command 时丢数据
process/outputDelta standalone process stream streaming bytes 不复制到 process/exited native/pass-through-only;Feishu 不 claim 不默认 opt-out,避免数据丢失

headless opt-out 建议

当前 headless 只 opt-out item/agentMessage/delta。建议后续单独做 P7:

  • 低风险保留:继续 opt-out item/agentMessage/delta
  • 低风险候选:item/fileChange/outputDeltathread/realtime/transcript/deltathread/realtime/outputAudio/delta,前提是 Feishu/headless 当前不 claim 对应 realtime/live patch 产品能力。
  • 需要代码审计后再启用:item/plan/deltaitem/commandExecution/outputDeltaitem/reasoning/summaryTextDeltaitem/reasoning/textDelta
  • 不应 opt-out:item/starteditem/completedturn/completed、approval / elicitation / request_user_input 等 server requests、serverRequest/resolvedthread/status/changed、warnings/errors。
  • 暂不应 opt-out:turn/diff/updatedturn/plan/updatedthread/tokenUsage/updated,因为当前已作为 authoritative latest snapshot / state 输入使用。
  • VS Code/native parent initialize 不应被 wrapper 注入这些 opt-out;native client 可能确实需要 live delta。

缺口矩阵

1. 优先补底层 carrier 的 passive notifications

这些不一定需要马上做 Feishu 产品 UI,但应进入 translator / agentproto / state 或可审计 event carrier。

分组 Upstream method 关键字段 / 语义 建议目标层级 产品展示结论
notices warning threadId?, message canonicalizedstate-only 高价值,可后续做最小 notice
notices guardianWarning threadId, message canonicalized 高价值,安全相关
notices deprecationNotice summary, details? state-only 先不默认刷屏
notices configWarning summary, details?, path?, range? canonicalized 高价值,可进入状态/诊断
model adjunct model/verification threadId, turnId, verifications[];当前枚举含 trustedAccessForCyber state-only 不等于已有 model/rerouted,先存后显
model adjunct model/safetyBuffering/updated threadId, turnId, model, useCases[], reasons[], showBufferingUi, fasterModel? canonicalizedstate-only 可解释当前 turn 行为,展示后置
execution transcript item/commandExecution/terminalInteraction threadId, turnId, itemId, processId, stdin canonicalized 用于命令 transcript 保真,不宜单独刷屏
reasoning structure item/reasoning/summaryPartAdded threadId, turnId, itemId, summaryIndex canonicalized 聚合边界,不是用户 notice
file change snapshot item/fileChange/patchUpdated threadId, turnId, itemId, changes[] state-only / latest-only 不做实时 diff 卡;最终用 item/completed / turn/diff/updated
thread lifecycle thread/archived threadId state-only 影响列表/选择
thread lifecycle thread/deleted threadId state-only 影响列表/选择,需清理选择态
thread lifecycle thread/unarchived threadId state-only 影响列表/选择
thread lifecycle thread/closed threadId state-only 不等同 detach;需按 upstream delayed close 语义处理
thread goal thread/goal/updated threadId, turnId?, goal{objective,status,tokenBudget,tokensUsed,timeUsedSeconds,...} state-only 产品化需单独设计任务目标
thread goal thread/goal/cleared threadId state-only 同上
thread settings thread/settings/updated threadId, threadSettings state-only 先存储,不默认展示
capability invalidation skills/changed empty payload;提示重新 skills/list state-only 状态/诊断页优先
MCP status mcpServer/startupStatus/updated threadId?, name, status, error?, failureReason? canonicalizedstate-only 高价值诊断
MCP auth mcpServer/oauthLogin/completed name, threadId?, success, error? state-only #670 关联
app list app/list/updated data[] state-only 状态/设置页优先
account account/updated authMode?, planType? state-only 不放 chat 主链
account account/rateLimits/updated sparse rateLimits state-only 状态页优先
account account/login/completed loginId?, success, error? state-only 账号流专项,不放本轮 UI
remote control remoteControl/status/changed status, serverName, installationId, environmentId? pass-through-onlystate-only 与本产品 remote 语义易混,需谨慎

2. 暂不产品化,先保持 pass-through-only 的 native / IDE-heavy notifications

分组 Upstream method 当前策略
realtime thread/realtime/* native-first;transcript delta 可等 done,audio delta 不进 Feishu;不 claim Feishu/headless 支持
fuzzy file search fuzzyFileSearch/sessionUpdated, fuzzyFileSearch/sessionCompleted 原生交互控件,暂不产品化
fs watch fs/changed 仅在实现 watch 产品面时再接
process/simple terminal process/outputDelta, process/exited, command/exec/outputDelta 与 turn 内 command item 不同;streamed bytes 不在 final 里重复,暂不 claim Feishu 支持,只保持 native/pass-through
external import externalAgentConfig/import/progress, externalAgentConfig/import/completed setup/migration 方向,后续单独设计
windows windows/worldWritableWarning, windowsSandbox/setupCompleted 平台专项,先不接主链
internals rawResponseItem/completed, turn/moderationMetadata, thread/compacted, hook notifications 除非后续明确需要,否则不产品化

3. ServerRequest policy 缺口

当前 upstream ServerRequest 共 10 个:

Method 当前判断 后续策略
item/commandExecution/requestApproval 已建模主路径 继续保持
item/fileChange/requestApproval 已建模主路径 继续保持
item/tool/requestUserInput 已建模 继续保持
mcpServer/elicitation/request 已建模 form/url/openai-form 方向 #668 关联,继续细化
item/permissions/requestApproval 已建模 #669 关联,继续细化
item/tool/call 已建模为 tool_callback,并 fail-closed unsupported 回写 后续如果 claim full support,需要 callback executor
account/chatgptAuthTokens/refresh 未策略化 不得 fake token;倾向 native-only 或 fail-closed visible
attestation/generate 未策略化 不得 fake attestation;倾向 fail-closed visible,除非明确实现
legacy applyPatchApproval 需确认是否仍会出现 若支持,走 legacy compat,不污染新 request abstraction
legacy execCommandApproval 需确认是否仍会出现 同上

4. Active ClientRequest 后续边界

这些存在于 upstream,不等于 Feishu Remote 现在应该主动开放:

  • thread lifecycle action:thread/archivethread/deletethread/unarchivethread/unsubscribe
  • goal/settings:thread/goal/set|get|clearthread/settings/update
  • memory/context:thread/memoryMode/setmemory/resetthread/inject_items
  • terminal/process:thread/shellCommandthread/backgroundTerminals/*command/exec*process/*
  • list/read/search:thread/loaded/listthread/turns/listthread/items/listthread/search
  • skills/plugin/marketplace/app/account/MCP/fs/realtime/windows sandbox 等管理面 request。

策略:本 parent 不直接开放这些 command;后续要做时单独过产品/状态机设计。

建议范围

#689 拆成 parent + child issues 推进。parent 保持 status:needs-plan,不作为直接编码单元;子 issue 达到 execution closure 后再标 status:implementable-now

建议第一轮拆 P0-P8:

  1. P0:coverage manifest / drift test,必须带 cadence / final-authority / Feishu projection policy。
  2. P1:protocol notice carrier。
  3. P2:model adjunct carrier。
  4. P3:execution / reasoning final-state carrier + delta suppression audit。
  5. P4:thread lifecycle / goal / settings carrier。
  6. P5:capability / account / app / MCP status state-only carrier。
  7. P6:server request policy hardening。
  8. P7:headless optOutNotificationMethods policy。
  9. P8:产品投影。

产品展示 issue 放到 P8+,等底层 carrier、delta 策略和 opt-out 策略稳定后再拆。

拆分结构

子项 目标 依赖 推荐状态 备注
P0 coverage manifest / drift test 建立 upstream method coverage 分类和 drift 检测 先开工 所有后续子项依赖它
P1 notice carrier warning / guardianWarning / deprecationNotice / configWarning P0 P0 后可开工 可先 state-only,Feishu 展示后置
P2 model adjunct carrier model/verification / model/safetyBuffering/updated P0 P0 后可开工 明确区别于已支持的 model/rerouted
P3 execution / reasoning final-state carrier + delta suppression audit terminalInteraction / summaryPartAdded,并审计 item/plan/delta、reasoning、command output delta 的 final 来源 P0 P0 后可开工 主要为 transcript / 聚合保真 + 防止误把 delta 当最终事实
P4 thread lifecycle / goal / settings carrier 接 archive/delete/unarchive/closed/goal/settings notifications P0 P0 后可开工 会触及 thread selection 状态,需 remote-state guardrail
P5 capability/account/app/MCP status carrier 接 skills/MCP startup/OAuth completed/app/account/rate limits P0 P0 后可开工 多为状态页/诊断页后续输入
P6 server request policy 明确 token refresh / attestation / legacy approvals 策略并实现 fail-closed/pass-through P0 P0 后可开工 不得 fake credentials/attestation
P7 headless optOutNotificationMethods policy 扩展/固化 synthetic initialize opt-out allowlist,并证明 native path 不受影响 P0、P3 P3 后开工 飞书不做 typewriter 的协议入口
P8 product projection Feishu notice/status page/thread goal 等产品展示 P1-P7 对应 carrier 后置 另行产品拍板

推荐顺序

  1. P0 先做,建立 coverage manifest、drift test 和 streaming/delta 分类字段。
  2. P1、P2、P3 可并行;其中 P3 优先处理 item/plan/delta final-authority 误判和 delta suppression。
  3. P4 在 P0 后做,但需要更谨慎,因为会影响 thread list/selection/attach 状态。
  4. P5 在 P0 后做,优先 state-only,不默认进入 chat 主链。
  5. P6 在 P0 后做,优先安全 fail-closed。
  6. P7 在 P3 审计后做,避免 opt-out 先行导致语义丢失。
  7. P8 等 carrier、delta 策略和真实需求稳定后再做产品展示。

可并行组

  • 并行组 A:P1、P2、P3。
  • 并行组 B:P5、P6。
  • P4 可与 A/B 并行,但验收要单独看 thread selection / remote state。
  • P7 依赖 P3 的 delta/final-authority 审计,不应提前。
  • P8 必须后置。

实现参考

P0 coverage manifest / drift test

建议:

  • 新增一个 repo 内 manifest,例如 internal/adapter/codex/protocol_coverage*.json|godocs/general/codex-app-server-coverage.md + 测试脚本。
  • manifest 至少包含:methoddirectiontargetLayerstatusownernotes
  • manifest 还必须包含 streaming 相关字段:cadenceevent|snapshot|stream-delta|high-frequency)、authoritativeFinalfeishuProjectionPolicyignore|final-only|latest-only|coalesced|state-only|pass-through-only|product-visible)、headlessOptOutCandidateoptOutBlockedBynativePassThroughRequired
  • drift test 从当前 vendored/checked-in upstream schema snapshot 或生成列表对比,不建议测试时依赖网络。
  • 如不引入 schema 文件,可先用手工列表 + 测试保护,后续再自动生成。

P1-P5 passive carrier

建议:

  • agentproto 新增少量 typed carrier,避免把所有东西塞进 Metadata
  • 对低价值/高变动面可用受控 ProtocolNotice / ProtocolState,但必须白名单 method,不能任意 raw passthrough。
  • translator_observe_server.go 识别 method,抽关键字段,设置 TrafficClass / Initiator 时沿用现有 turn/thread 归属规则。
  • orchestrator 默认 state-only 或 no-op 存储,不要默认刷 Feishu 消息。
  • 如果后续进入 Feishu 卡片,需另查 Feishu card limits,并触发 Feishu UI state-machine guardrail。

P3 / P7 delta suppression

建议:

  • P3 先证明每类 delta 是否有 authoritative final;没有 final duplicate 的 streaming output 只能 native/pass-through,不得在 Feishu claim 支持后丢弃。
  • item/plan/delta 不能再作为最终提案计划正文的权威来源;提案计划应优先使用 item/completed 的 plan item text,并加 delta 与 completed text 不一致的回归测试。
  • item/agentMessage/delta 当前 headless opt-out 可保留;orchestrator 仍需支持 completed agent message final render。
  • reasoning summary 如果保留可见进度,只能 coalesced + final flush;不能逐 delta patch。
  • item/commandExecution/outputDelta 只有在确认 completed aggregatedOutput 覆盖 Feishu 所需摘要后,才可加入 headless opt-out。
  • turn/diff/updatedturn/plan/updated 这类 repeated snapshot 应按 latest/dedupe/bounded cadence 处理,不应被当成 raw delta 流。
  • P7 只修改 headless / cron synthetic initialize 的 opt-out allowlist;不得注入 VS Code/native parent initialize。
  • P7 必须有 wrapper/headless tests 证明 opt-out 列表正确、native pass-through 不变、server requests/errors 不受影响。

P6 server request policy

建议:

  • account/chatgptAuthTokens/refresh:不要自动成功;如果无 native handler,应生成可审计 unsupported / auth-required 事件或明确 pass-through-only。
  • attestation/generate:不要伪造 token;无实现时 fail-closed。
  • legacy approvals:先用真实上游/测试确认是否仍会出现;如果支持,映射到现有 request abstraction,但保留 raw method。
  • unsupported request 必须可见于 debug/state,不允许 silent drop。

检查参考

每个子 issue 至少应覆盖:

  • translator unit tests:对应 upstream JSON frame -> canonical event/state carrier。
  • orchestrator tests:state-only 不刷屏、product-visible 只在明确设计时显示。
  • wrapper tests:未知帧 native pass-through 不被破坏。
  • headless initialize tests:optOutNotificationMethods allowlist 精确、只作用于 synthetic headless/cron,不污染 VS Code/native path。
  • delta suppression tests:agent/plan/reasoning/command delta 不触发飞书逐 delta patch;completed item / latest snapshot 仍能产出最终语义。
  • request policy tests:unsupported / fail-closed 不静默吞,不 fake sensitive response。
  • docs sync:更新 app-server audit / relay protocol spec / coverage manifest。

建议命令:

  • go test ./internal/adapter/codex
  • go test ./internal/core/orchestrator
  • go test ./internal/app/wrapper
  • go test ./...
  • bash scripts/check/go-file-length.sh

收尾参考

  • 子 issue 完成后必须把结果回卷到本 parent 的总调度表。
  • 如果触及 remote surface routing / attach / selected-thread / queue gate,运行 remote-state-machine-guardrail 并同步 docs/general/remote-surface-state-machine.md
  • 如果触及 Feishu card payload / callback / old-card / inline replace,运行 feishu-ui-state-machine-guardrail 并同步 docs/general/feishu-card-ui-state-machine.md
  • 如果触及 Feishu card payload 设计,按 docs/general/feishu-card-api-constraints.md 明确大小预算和降级路径。
  • parent close 前运行 independent verifier。

当前风险

  • P0 如果不先做,后续仍会回到人工盘点,下一次 upstream drift 继续漏。
  • P4 可能影响 thread list / attach / selected thread / old thread 状态,不能只当普通 notification。
  • P6 涉及 token refresh 和 attestation,不能用“自动 unsupported”掩盖产品/安全语义;必须明确 fail-closed 证据。
  • 如果过早做 P8 产品展示,容易把底层 carrier 和 Feishu UI 绑死,导致范围失控。
  • 如果 raw delta 被直接映射成飞书 patch,会快速撞上单消息/单卡更新频控,并把 typewriter UX 变成平台风险。
  • item/plan/delta upstream 已声明不等于 completed plan item content,现有 plan proposal 相关文档/测试需要以 completed item 为准重新校正。
  • command/exec/outputDelta / process/outputDelta 没有 final duplicate;如果未来 claim 支持这两类 process API,必须先设计 buffering/coalescing,否则 opt-out 会造成数据丢失。
  • native VS Code path 和 headless Feishu policy 不能混用;wrapper 不能替 native client 擅自关掉它需要的 live deltas。
  • thread/closed 上游语义是无 subscriber 且无 activity 一段时间后关闭,不应当成用户主动 detach。

执行决策

  • 是否拆分:必须拆分。
  • 拆分理由:本 issue 同时覆盖 coverage 基础设施、passive notifications、thread lifecycle、server request policy、docs/product projection,验证面和风险边界不同,单 worker 直做会形成巨大且难验收的 PR。
  • 当前执行单元:本 parent issue 只负责调研闭包、计划闭包、子 issue 调度和结果回卷。
  • 子 issue 策略:P0 先形成 execution closure;P1-P6 在 P0 后拆成可执行 worker 单元;P7 作为 headless opt-out / delta suppression 策略单元;P8 作为产品投影后置。
  • verifier:parent close 前需要 independent verifier;medium/large 子 issue 默认也需要 verifier。

总调度表

单元 类型 当前状态 依赖 可并行组 当前闭包等级 下一步建议 备注 结果回卷 verifier 状态 当前结论
#689 母 issue status:needs-plan - - 计划闭包 调度 #690-#698,等待子项回卷 本单不直接编码 未开始 parent close 前需要 调度中心
#690 P0 coverage manifest / drift test 子 issue close-out 中 前置 执行闭包 等待 commit/push/finish close 已落 repo 内 manifest、snapshot、drift/shape test;当前 upstream HEAD 315195492c80fdade38e917c18f9584efd599304,127/11/72 已回卷到审计文档 read-only pass 待记录 P0 基线已完成,#693/#696 可按 manifest 输入继续
#691 P1 notice carrier 子 issue close-out 中 #690 A 执行闭包 等待 commit/push/finish close warning / guardian / config / deprecation notice 已进入 protocol.notice state-only carrier 已回卷 pass P1 完成
#692 P2 model adjunct carrier 子 issue close-out 中 #690 A 执行闭包 等待 commit/push/finish close verification / safety buffering 已进入 typed state-only carrier,不重复 model/rerouted 已回卷 pass P2 完成
#693 P3 final-state carrier + delta suppression audit 子 issue close-out 中 #690 A 执行闭包 等待 commit/push/finish close carrier 与 delta suppression 已完成,P7 输入已产出 已回卷 read-only pass 待记录 P7 可在 #693 close 后开工
#694 P4 thread lifecycle / goal / settings carrier 子 issue close-out 中 #690 B 执行闭包 等待 commit/push/finish close lifecycle/goal/settings 已进入 state-only carrier;closed 不 detach,deleted 防误路由 已回卷 pass P4 完成
#695 P5 capability/account/app/MCP status carrier 子 issue close-out 中 #690 B 执行闭包 等待 commit/push/finish close capability/account/app/MCP status passive notifications 已进入 capability.state.updated;不替代 #670 已回卷 pass P5 完成
#696 P6 server request policy hardening 子 issue close-out 中 #690 B 执行闭包 等待 commit/push/finish close token refresh / attestation/currentTime fail-closed,legacy approvals compat 已回卷 pass P6 完成
#697 P7 headless optOutNotificationMethods policy 子 issue close-out 中 #690#693 C 执行闭包 等待 commit/push/finish close allowlist 已实现;只影响 headless/cron synthetic initialize,不污染 VS Code/native 已回卷 read-only pass 待记录 P7 完成,#696 可继续
#698 P8 product projection 产品规划 issue status:needs-plan #691-#697 后置 计划闭包 #701 已完成,等待 close-out;之后决定 P2 是否拆单 不直接编码;P2 status/diagnostic 后置待拆 #701 已回卷 parent close 前判断 P8 第一阶段完成
#688 VS Code app-server 前置全局参数兼容 独立 bug issue status:implementable-now 并行 执行闭包 可以并行开工 不属于 #689 carrier 主链,但影响最新 VS Code 实栈验证 未回卷 该 issue 自定 并行 ready
#668 MCP elicitation/OAuth 父单 相关父 issue status:needs-plan #669/#670 邻接 计划闭包 保持父单调度 #695/#670 与其重叠处需回卷 未开始 父单 close 前判断 邻接,不是 #689 worker
#669 MCP approval elicitation persist contract 相关子 issue status:needs-clarification 产品决策 邻接 决策门 需先拍板 persist=always 第一阶段策略 未决前不应开工 未开始 待定 不可当前开工
#670 MCP OAuth login lifecycle 相关子 issue status:needs-plan 入口/展示方案 邻接 计划闭包 需要单独计划化后再判断开工 #695 只承接 passive completion/status,不替代它 未开始 待定 还不可开工
#233 third-batch backlog umbrella 老 backlog status:needs-clarification 多子项 后置 backlog 闭包 后续按 #689/#695/#670 分流回卷 不作为当前 worker 部分分流 不适用 backlog 锚点

当前开工判断

当前执行点

恢复步骤

  1. 重新读取 [Track] Codex app-server 协议支持追平:底层 carrier 先行,产品展示分阶段承接 #689 body,确认 总调度表当前开工判断
  2. 重新确认本仓库 master 是否与 origin/master 同步;如未同步,先 fast-forward 到最新。
  3. 重新确认 upstream Codex 镜像 /tmp/openai-codex-latest 是否与 origin/main 同步;如已变化,先刷新 [Work][#689-P0] Codex app-server protocol coverage manifest 与 drift test #690 的 upstream snapshot 输入。
  4. 如果 [Work][#698-P1] Feishu 主链 P0/P1 app-server notice 主动短推送 #701 尚未关闭,优先完成 [Work][#698-P1] Feishu 主链 P0/P1 app-server notice 主动短推送 #701 close-out。
  5. 如果 [Work][#698-P1] Feishu 主链 P0/P1 app-server notice 主动短推送 #701 已关闭,再按 [Product][#689-P8] Codex app-server carrier 产品投影:Feishu notice/status/goal 后置设计 #698 判断是否拆 P2 status/diagnostic 子单。
  6. 每个子 issue 完成后,把结果、验证和 verifier 状态回卷到本 parent 的总调度表。

执行快照

子 issue 回卷:#690

子 issue #690 已完成并关闭,结果回卷如下:

子 issue 回卷:#693

子 issue #693 已完成并关闭,结果回卷如下:

  • 结果:final-state carrier 与 delta suppression audit 已完成,等待 [Work][#689-P3] Final-state carrier 与 delta suppression 审计 #693 close-out。
  • 交付物:item/commandExecution/terminalInteractionitem/reasoning/summaryPartAddeditem/fileChange/patchUpdated 进入 typed/state-only carrier;patchUpdated 只写 latest-only file-change snapshot;protocol coverage manifest 已同步。
  • Delta 策略结论:Feishu Remote 仍不做 typewriter;completed item / authoritative snapshot 优先。item/plan/delta 不再被当作最终提案正文,completed plan item text 优先。item/commandExecution/outputDelta 不生成 live Feishu patch。reasoning summary 继续 coalesced/final。
  • P7 输入:item/plan/deltaitem/reasoning/textDeltaitem/reasoning/summaryTextDeltaitem/commandExecution/outputDeltaitem/fileChange/outputDelta 可作为 headless opt-out 候选;item/fileChange/patchUpdated 不建议 opt-out;standalone command/exec/outputDelta / process/outputDelta 仍不建议 opt-out。
  • 验证:go test ./internal/adapter/codex ./internal/core/orchestrator ./internal/app/wrappergo test ./internal/adapter/feishu ./internal/app/daemon ./internal/core/control ./internal/core/orchestratorgit diff --checkbash scripts/check/go-file-length.sh 均通过。

子 issue 回卷:#697

子 issue #697 已完成并关闭,结果回卷如下:

  • 结果:headless/cron synthetic initialize 的 optOutNotificationMethods allowlist 已落地,VS Code/native path 不受影响。
  • 最终 allowlist:item/agentMessage/deltaitem/plan/deltaitem/reasoning/textDeltaitem/reasoning/summaryTextDeltaitem/commandExecution/outputDeltaitem/fileChange/outputDelta
  • 明确未加入:item/fileChange/patchUpdatedcommand/exec/outputDeltaprocess/outputDelta、requests/errors/completed/final snapshot。
  • 验证:go test ./internal/app/wrapper ./internal/adapter/codexgit diff --checkbash scripts/check/go-file-length.sh 均通过。
  • 对父单影响:P7 完成;后续仍可继续 [Work][#689-P6] ServerRequest policy hardening:token refresh / attestation / legacy approvals #696 server request policy 或其他 carrier 子项。

子 issue 回卷:#696

子 issue #696 已完成并关闭,结果回卷如下:

  • 结果:ServerRequest policy hardening 已完成;敏感 request 进入显式 unsupported_server_request fail-closed 自动回写,legacy approvals 保持 approval compat。
  • 交付物:account/chatgptAuthTokens/refreshattestation/generatecurrentTime/read 不再进入 generic request prompt;orchestrator 自动回写 structured failure,不 fake credentials/attestation;applyPatchApproval / execCommandApproval 继续映射为 approval 并保留 raw method / raw kind。
  • 文档:已同步 docs/inprogress/codex-app-server-state-machine-audit.mddocs/general/feishu-card-ui-state-machine.md
  • 验证:go test ./internal/adapter/codex ./internal/core/orchestrator ./internal/app/wrappergo test ./internal/adapter/feishu ./internal/app/daemon ./internal/core/control ./internal/core/orchestratorgit diff --checkbash scripts/check/go-file-length.sh[Work][#689-P6] ServerRequest policy hardening:token refresh / attestation / legacy approvals #696 issue lint 均通过。
  • 独立 verifier 结果:pass。
  • 对父单影响:P6 完成;[Track] Codex app-server 协议支持追平:底层 carrier 先行,产品展示分阶段承接 #689 后续可继续调度 P1/P2/P4/P5 或保持 P8 后置产品规划。

子 issue 回卷:#691

子 issue #691 已完成并关闭,结果回卷如下:

  • 结果:warning/config/guardian/deprecation passive notice carrier 已完成;四类 method 进入 protocol.notice,orchestrator 默认 state-only,不刷飞书消息。
  • 交付物:ProtocolNotice carrier;translator 支持 warningguardianWarningdeprecationNoticeconfigWarning;instance/thread 最近 notice state 记录;bounded state 测试。
  • 明确未做:windows/worldWritableWarning 未纳入本单,仍待确认上游 payload;Feishu notice center / 产品展示后置到 P8 或后续产品设计。
  • 文档:已同步 docs/general/relay-protocol-spec.mddocs/inprogress/codex-app-server-state-machine-audit.md、protocol coverage manifest。
  • 验证:go test ./internal/adapter/codex ./internal/core/orchestratorgo test ./internal/adapter/codex ./internal/core/orchestrator ./internal/app/wrappergit diff --checkbash scripts/check/go-file-length.sh[Work][#689-P1] Codex app-server warning/config/guardian notice carrier #691 issue lint 均通过。
  • 独立 verifier 结果:pass。
  • 对父单影响:P1 完成;[Track] Codex app-server 协议支持追平:底层 carrier 先行,产品展示分阶段承接 #689 后续可继续 P2/P4/P5 或保持 P8 后置产品规划。

子 issue 回卷:#692

子 issue #692 已完成并关闭,结果回卷如下:

  • 结果:model adjunct state carrier 已完成;model/verificationmodel/safetyBuffering/updated 进入 typed state-only carrier,不再混同 model/rerouted
  • 交付物:TurnModelVerification / TurnModelSafetyBuffering carrier;translator 字段抽取;orchestrator thread latest state-only 存储;protocol coverage manifest 标记 supported/state-only。
  • 明确未做:未新增 Feishu 用户可见消息或卡片;未实现 verification 流程;未把 safety buffering 当 final result/error;未改变 reroute/effective model。
  • 文档:已同步 docs/general/relay-protocol-spec.mddocs/inprogress/codex-app-server-state-machine-audit.md
  • 验证:go test ./internal/adapter/codex ./internal/core/orchestratorgo test ./internal/adapter/codex ./internal/core/orchestrator ./internal/app/wrappergit diff --checkbash scripts/check/go-file-length.sh[Work][#689-P2] Codex model verification / safety buffering state carrier #692 issue lint 均通过。
  • 独立 verifier 结果:pass。
  • 对父单影响:P2 完成;后续可继续 P4/P5 或保持 P8 后置产品规划。

子 issue 回卷:#694

子 issue #694 已完成并关闭,结果回卷如下:

  • 结果:thread lifecycle / goal / settings state carrier 已完成;7 个 thread-level notification 进入 typed state-only carrier。
  • 交付物:ThreadLifecycleUpdateThreadGoalUpdateThreadSettingsUpdate carrier;translator 字段抽取;orchestrator state-only 行为;protocol coverage manifest 标记 supported/state-only。
  • 关键行为:thread/closed 只标记 runtime notLoaded,不 detach、不清 selection;thread/deleted 会把命中 surface 清到 attached-unbound 并释放 thread claim,避免后续输入误路由;archived/unarchived 只影响列表可见性;goal/settings 只保存 latest state。
  • 明确未做:未开放主动 archive/delete/unarchive command;未设计 goal UI;未新增 Feishu 用户可见消息或卡片;未处理 account/app/MCP/realtime。
  • 文档:已同步 docs/general/relay-protocol-spec.mddocs/inprogress/codex-app-server-state-machine-audit.mddocs/general/remote-surface-state-machine.md
  • 验证:go test ./internal/adapter/codex ./internal/core/orchestratorgo test ./internal/adapter/codex ./internal/core/orchestrator ./internal/app/wrappergit diff --checkbash scripts/check/go-file-length.sh[Work][#689-P4] Thread lifecycle / goal / settings state carrier #694 issue lint 均通过。
  • 独立 verifier 结果:pass。
  • 对父单影响:P4 完成;后续可继续 P5 或保持 P8 后置产品规划。

子 issue 回卷:#695

子 issue #695 已完成并关闭,结果回卷如下:

  • 结果:capability/account/app/MCP status passive notification carrier 已完成;7 类 notification 进入 typed/state-only capability.state.updated
  • 交付物:CapabilityStateUpdate carrier;translator 支持 skills/changedmcpServer/startupStatus/updatedmcpServer/oauthLogin/completedapp/list/updatedaccount/updatedaccount/rateLimits/updatedaccount/login/completed / accountLoginCompleted;orchestrator 记录 instance/thread latest state;protocol coverage manifest 标记 [Work][#689-P5] Capability / account / app / MCP status state-only carrier #695 supported。
  • 关键行为:skills/changed 只作为 invalidation signal;mcpServer/startupStatus/updated.failureReason=reauthenticationRequired 保留;account/rateLimits/updated 按 sparse map 保留;mcpServer/oauthLogin/completed 有 pending /mcpoauth flow 时保持原 completion 事件,无 pending 时只记录 state-only,不广播到无关 chat。
  • 明确未做:未新增 Feishu 用户可见卡片或菜单;未实现账号管理 UI、app/skills 管理入口;未替代 [Follow-up] MCP OAuth login lifecycle:mcpServer/oauth/login -> oauthLogin/completed #670 的主动 MCP OAuth login lifecycle;未处理 realtime/fs/watch/windows/fuzzy search。
  • 文档:已同步 docs/general/relay-protocol-spec.mddocs/inprogress/codex-app-server-state-machine-audit.mddocs/draft/app-server-third-batch-product-directions.md
  • 验证:go test ./internal/adapter/codex -run 'TestProtocolCoverage|TestObserveServerCapabilityState|TestMCPOAuthLoginCompletedUsesProtocolCorrelation'go test ./internal/adapter/codex ./internal/core/orchestrator ./internal/app/wrappergit diff --checkbash scripts/check/go-file-length.sh 均通过。
  • 独立 verifier 结果:pass。
  • 对父单影响:P5 完成;[Track] Codex app-server 协议支持追平:底层 carrier 先行,产品展示分阶段承接 #689 底层 carrier 侧剩余后置主要是 [Product][#689-P8] Codex app-server carrier 产品投影:Feishu notice/status/goal 后置设计 #698 产品投影或其它明确后续项。

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:codexCodex protocol translation and wrapper integrationarea:daemonDaemon server, admin API, and runtime controlarea:feishuFeishu/Lark integration, gateway, projector, or previewarea:wrapperWrapper process, proxy handling, and child launch flowenhancementNew feature or requestmaintainabilityRefactors, code structure, and long-term maintainability workstatus:needs-planTechnical investigation is sufficient, but the staged plan is not yet execution-ready

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions