Skip to content

feat(runtime): stall observation + optional reconcile capability - #94

Open
qiankunli wants to merge 1 commit into
feat/tui-idle-statusfrom
feat/stall-reconcile
Open

feat(runtime): stall observation + optional reconcile capability#94
qiankunli wants to merge 1 commit into
feat/tui-idle-statusfrom
feat/stall-reconcile

Conversation

@qiankunli

Copy link
Copy Markdown
Collaborator

让 baton 感知并处理"上游静默悬挂"——进程活着、不报错、不退出、transport 不断,但 turn 卡在 in_progress 收不了口(现有终态契约只覆盖可观测退出,盖不到这类)。设计见 docs/provider-output-lifecycle.md §5(另一个 PR #93)。

两层机制

停滞观测:runtime 给每个活跃 turn 记进展时钟(onAdapterEvent 单点 stamp),低频扫描器发现静默超阈值 → 发一次 _baton_stall_notice(投影成 no response — may be stuck),活动恢复补 cleared绝不 finalize——不设固定 watchdog(interaction-design §4.1),收口仍只由真实终态 / reconcile / 用户 cancel 触发。

对账(可选能力):停滞时查 provider 侧真实运行态。

  • idle → provider 已结束、baton 漏了终态:合成 idle 走正常 finalize(自愈,含 summary)。最常见,用户无感
  • active / waiting_* / unknown / 探针失败 → 保留提示,交用户 Esc 取消。
  • Codex 实现:一个 thread/read 读 live thread.status(wire 形状从生成的 ThreadStatus.ts 核对)。
  • Claude 不声明能力,自动回落到纯停滞观测。

不变量(测试钉死)

  • 只有 idle 裁决才收口;不确定一律不动终态(悲观不静默判死)。
  • 能力门控:未声明 reconcile 就绝不调用(Claude reconcileCalls===0)。
  • 自愈走正常事件管线,不开旁路。
  • 扫描器懒启动 / 无活跃 turn 自停 / close 清理 / unref 不阻塞退出。

验证

bun run check:typecheck 干净 + 282 pass / 0 fail。新增 tests/stall.test.tstests/reconcile.test.ts

说明

  • Base 是 feat/tui-idle-status(本改动叠在其上,diff 即纯本次代码)。
  • 剩余 L3(stalled 卡片交互)未包含;调研结论:Codex 无此概念,倾向"折进状态行 + 复用 Esc"而非新建 modal。

🤖 Generated with Claude Code

Detect silently-hung turns (an active turn with no events past a threshold)
and surface them as a self-healing observed state, without ever force-
finalizing — the terminal-state contract stays owned by real terminals,
reconcile, or user cancel (no global watchdog).

Add an optional reconcile capability: on stall, query the provider's real
turn state. An "idle" verdict self-heals a missed terminal (routes a normal
idle → finalize + summary); active / waiting / unknown / probe-failure keep
the stall notice for the user to cancel. Codex implements reconcile via
thread/read's live status; Claude declares nothing and falls back to
stall-only observation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants