Skip to content

control-plane gate 投递的两个健壮性缺口:codex 引擎收不到 gate 回复;resolveGate 投递失败仍返回成功 #40

Description

@stablehunter-dev

背景

#37 / #38 落地的 control-plane([DEVLOG_STAGE] / [DEVLOG_GATE] stdout 协议 + resolveGate)我们在 fork 上接了一层 Linear 中转、用真实 issue 全链路跑了多轮。协议本身工作得很好;但在「把人工回复投递回 agent」这一段,发现两个健壮性缺口,都在核心层:

缺口 1:codex(plain-stdin 引擎)收不到 gate 回复

一个 codex session 触发 gate 后,回复没有任何可达路径:

  1. 活进程写不进:codex 启动即 stdin.end(prompt)(一次性),writeGateResponse 的守卫发现 writableEnded直接丢弃回复,只记一条 warning;
  2. 重生不是恢复:resolveGate 对死进程走 ensureProcess 重生,但 codex 的启动参数是 codex exec --json … -,没有任何 resume 参数 —— 重生的进程是全新会话,丢失全部上下文;
  3. 想恢复也没料:sp.claudeSessionId = event.session_id 只在 claude-stream-json 解析路径里赋值,codex 事件解析器从不捕获 codex 自己的 thread/session id。

建议方向:捕获 codex 的 session/thread id(它的 JSON 事件流里有)→ 增加 codex exec resume <id> 启动路径 → plain-stdin 的 gate 投递改成「等进程退出 → 带回复 resume 重生」。

缺口 2:resolveGate 投递失败仍返回成功,且先清 gate 后验投递

resolveGate 的顺序是:resolveControlPlaneGate(先清掉 gate_status)→ 找/重生进程 → writeGateResponse。两种失败都会被吞掉并返回 {ok:true}:

  • ensureProcess 返回 null(重生失败)→ 跳过投递,照样返回成功;
  • writeGateResponse 写 stdin 失败(已关闭/异常)→ 只记 warning,照样返回成功。

结果:人的回复被消费、gate 已清、agent 永远没收到 —— 调用方完全无感。

建议方向(我们 fork 已这样修,可参考 loop2zero/DevLog@96ce529):先取得可用进程再清 gate;writeGateResponse 返回 boolean;投递失败时把 gate_status 原样恢复(sessions+tasks)并返回 {ok:false},让上层可以重试。

复现要点

任何 gate 流程 + 让原进程在 gate 期间死亡(或直接用 codex 引擎),然后调 resolveGate:观察返回值为 ok 但 agent 无任何动作。

来自 fork(loop2zero/DevLog,在 #37 协议之上做 Linear 中转)的真实运行发现。两个缺口都愿意出 PR,如果你对方向有偏好请说。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions