Skip to content

fix(cursor): inbound stream-health watchdog fails silent/heartbeat-only turns at the transport - #2337

Merged
lidge-jun merged 1 commit into
devfrom
codex/cursor-stream-health-watchdog
Aug 22, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/cursor-stream-health-watchdog

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

T04 from the round-2 roadmap (devlog 110, senpi #1062 second half): an inbound stream-health watchdog in the live Cursor transport. After the first decoded frame, 30s of total inbound-frame silence — or 90s of heartbeat/checkpoint-only traffic — fails the turn with a typed stall error instead of waiting for the 300s bridge stall watchdog. Addresses the #2210 stall class.

Design points:

  • Resets happen on DECODED AgentServerMessage frames, not raw chunks, so TLS keepalive noise cannot defeat the watchdog.
  • Liveness-only frames (server heartbeat, conversationCheckpointUpdate) refresh the silence clock but not the progress clock — a pinging-but-stuck server still fails at 90s.
  • Disarmed at turnEnded decode (the T03 grace close owns the socket from there — a watchdog shorter than the grace must not fail a completed turn), client-tool suspend (expectedClose), protocol complete, cancel, close, and every settle path via the terminal settler's clearTimer.
  • No arming before the first frame: the existing first-frame timeout still owns dial silence.
  • Test knobs streamSilenceFailMs / streamHeartbeatOnlyFailMs on CursorTransportFactoryInput mirror firstFrameTimeoutMs.

Verification

  • bun x tsc --noEmit clean.
  • New tests/cursor-stream-health.test.ts (5 cases): silence fail, heartbeat-only fail, meaningful-frame resets + clean turnEnded, turnEnded-disarm with held-open stream, first-frame-timeout ownership — 5 pass.
  • Adjacent focused suites green: cursor-eof-terminal, cursor-http1-transport, cursor-hardening, cursor-tool-continuation — 72 pass / 0 fail.
  • Full suite deferred to CI per maintainer instruction (no-verify push authorized).

Checklist

  • Targets dev
  • Focused regression test added next to the subsystem
  • No Node-only APIs introduced; Bun-native runtime respected
  • No logging of request bodies or credentials

Summary by CodeRabbit

  • New Features

    • Added configurable monitoring for silent or stalled live streams.
    • Streams can now fail when no inbound data arrives or when only heartbeat/checkpoint updates occur without meaningful progress.
    • Added timeout settings to customize these thresholds.
  • Bug Fixes

    • Improved cleanup when streams complete, close, are cancelled, or encounter failures.
  • Tests

    • Added coverage for silent streams, heartbeat-only traffic, ongoing progress, and stream completion scenarios.

…instead of the 300s bridge watchdog

T04 (devlog 260822_senpi_cursor_transfer/110, senpi #1062 second half):
after the first decoded frame, 30s of inbound-frame silence or 90s of
heartbeat/checkpoint-only traffic fails the turn with a typed stall error.
Decoded frames reset the silence clock; only non-liveness frames reset the
progress clock, so TLS keepalive noise cannot defeat the watchdog and a
pinging-but-stuck server still fails at 90s. Disarmed by turnEnded (the T03
grace close owns the socket from there), client-tool suspend, protocol
complete, and every settle path. Addresses the #2210 stall class.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 22, 2026 03:46
@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 22, 2026
@github-actions

github-actions Bot commented Aug 22, 2026 •

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed.

@github-actions
github-actions Bot marked this pull request as draft August 22, 2026 03:47
@coderabbitai

coderabbitai Bot commented Aug 22, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ce50dc91-28bb-4fe5-87c3-2a0bd38ae23c

📥 Commits

Reviewing files that changed from the base of the PR and between 764ef32 and 994e5ba.

📒 Files selected for processing (3)
  • src/adapters/cursor/live-transport.ts
  • src/adapters/cursor/transport.ts
  • tests/cursor-stream-health.test.ts

📝 Walkthrough

Walkthrough

The Cursor transport adds configurable watchdogs for inbound-frame silence and heartbeat-only traffic. It tracks decoded frames, fails stalled turns, cleans up watchdogs across terminal paths, and adds HTTP/2 integration coverage.

Changes

Cursor stream health

Layer / File(s) Summary
Watchdog contract and transport state
src/adapters/cursor/transport.ts:32-41, src/adapters/cursor/live-transport.ts:94-105, src/adapters/cursor/live-transport.ts:436-446
Adds optional timeout settings and state for inbound-frame and meaningful-progress timestamps.
Watchdog execution and lifecycle cleanup
src/adapters/cursor/live-transport.ts:1197-1210, src/adapters/cursor/live-transport.ts:786-852, src/adapters/cursor/live-transport.ts:867-939, src/adapters/cursor/live-transport.ts:1063-1066
Classifies liveness-only frames, re-arms watchdog deadlines, fails stalled turns, closes active connections, and clears monitoring during completion, cancellation, close, and turnEnded paths.
HTTP/2 watchdog integration tests
tests/cursor-stream-health.test.ts:1-210
Adds protocol builders, transport helpers, and tests for silent streams, heartbeat-only traffic, recurring meaningful frames, turnEnded, and silence before the first frame.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HTTP2Server
  participant LiveTransport
  participant StreamHealthWatchdog
  participant TurnFailureCallback
  HTTP2Server->>LiveTransport: Send decoded server frame
  LiveTransport->>StreamHealthWatchdog: Update silence and progress timestamps
  StreamHealthWatchdog->>LiveTransport: Detect expired deadline
  LiveTransport->>TurnFailureCallback: Fail stalled turn
  LiveTransport->>HTTP2Server: Close active connection
Loading

Suggested reviewers: ingwannu

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/cursor-stream-health-watchdog

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lidge-jun
lidge-jun marked this pull request as ready for review August 22, 2026 03:47
@lidge-jun
lidge-jun merged commit 94c1dc2 into dev Aug 22, 2026
24 of 26 checks passed
@lidge-jun
lidge-jun deleted the codex/cursor-stream-health-watchdog branch August 22, 2026 03:47
agentHits pushed a commit to agentHits/opencodex that referenced this pull request Sep 17, 2026
…health-watchdog

fix(cursor): inbound stream-health watchdog fails silent/heartbeat-only turns at the transport
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant