fix(protocols): relay heartbeat keepalives from the direct encoders - #5847
Conversation
#5806 made the Chat converter answer typed heartbeats with an SSE comment; the direct Chat encoder still only ensured the role frame, so direct and bridged streams diverged. Keepalives also stop counting as relayed events, matching the bridge's uncounted heartbeat. Parity tests now compare comment-only blocks and cover heartbeats on both wires.
Record that direct encoders deliver the converters' keepalive frames without counting them.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
✅ Deterministic PR hygiene checks passed. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: lidge-jun/opencodex/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe direct Chat encoder emits wire-silence heartbeats as SSE comments. Keepalive frames are delivered but excluded from relayed-event counts. Tests compare direct and legacy heartbeat behavior for Chat and Messages. ChangesHeartbeat emission and accounting
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~12 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to No actionable heartbeat issue remains; the PR is mergeable after normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Opt-in direct streams will send keepalives consistently with the existing stream path, without counting those keepalives as relayed events. No security boundary bypass was identified, but the change affects client-visible streaming behavior. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 4 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
리뷰 · 우선순위 63 / 80답이 잠깐 조용할 때, 채팅 줄은 살아 있다는 표시로 이 PR은 직접 채팅 인코더가 역할 프레임 뒤에 같은 주석을 넣게 해요. 그 주석과 메시지 쪽 침묵 ping은 전달된 이벤트 수에 안 넣어요. 테스트는 주석만 있는 블록을 남긴 채 양쪽 줄을 비교하고, 침묵 중 신호가 가는지 확인해요. 직접 인코더는 기본으로 꺼져 있어요. 켠 설치에만 빠졌던 바이트가 채워지고, 깨진 테스트는 모두의 CI에 있었어요. tests/responses/protocol-direct-encoders-messages.test.ts:325 - 주석은 릴레이 횟수가 핑을 무시해야 한다고 적혀 있어요. 368행의 핑은 3개예요. 369행은 프레임 수에서 2만 빼요. 처음 message_start가 emit으로 보내는 핑은 횟수에 남아요. 366행 주석이 그 뜻을 적고, 325행은 더 넓게 읽혀요. 메인테이너의 판단이 필요한 지점 #5846도 같은 빨간 테스트를 고쳐요. 그 PR은 주석 블록을 비교에서 빼서 테스트를 초록으로 만들어요. 직접 인코더가 주석을 보내게 하는 코드는 #5846에 없어요. 두 PR이 tests/responses/protocol-direct-encoders-chat.test.ts의 normalizeFrames를 같이 고칩니다. 너의 추천 #5847을 머지하세요. #5846은 머지하지 말고 닫으세요. 325행 주석은 message_start의 첫 핑은 세고, 그 뒤 침묵 ping 두 개는 세지 않는다고 고치면 369행과 맞아요. 주석 한 줄 때문에 머지를 늦출 필요는 없어요. 이 댓글은 grok-bot이 작성했습니다 |
|
Maintainer integration (MAINTAINERS.md, 2026-09-06 rule) by the owner. Exact-head evidence for
|
Summary
devat76db92a4cdfailstests/responses/protocol-direct-encoders-chat.test.ts> "stall watchdog fails the turn like the bridge". Each parent passed CI on its own head; the defect is their union:: opencodex heartbeat(ADR-5805).heartbeattoensureRoleonly, so on wire silence it sent no byte after the role frame.The parity test's frame normalizer then parsed the bridge's comment block as JSON and threw. Every PR based on current
devinherits the failure (#5835, #5837, #5838, #5826, #5836 fail only on this test).This change:
src/protocols/encoders/chat.ts);src/protocols/encoders/adapter-events.ts); the Messages encoder'spingkeepalive was over-counted the same way;structure/data-planes/protocol-paths.mdandstructure/transports/responses.md.The direct encoders are off by default (
protocols.rollout.directEncoders), so only opted-in installs saw the missing keepalive; the red test affected everyone's CI.Maintainer integration: this is a maintainer PR landed by the owner under the MAINTAINERS.md 2026-09-06 rule once its exact-head checks are green; the exact-head evidence is added as a comment before merge.
Verification
bun test ./tests/responses/protocol-direct-encoders-chat.test.ts ./tests/responses/protocol-direct-encoders-messages.test.tspasses (93 pass, 0 fail).bun run typecheckexit 0;bun run structure:checkpassed;./tests/test-layout.test.tsand./tests/ci-workflows/file-size-ratchet.test.tspass.bun run test:changed(import graph againstdev) on the same commit; result added below once complete. The full suite is left to CI because this host runs several concurrent worktrees.src/chat/outbound.ts:615-623): byte order matches, the onlyactivity=falseenqueue isemitKeepalive, real-frame accounting is unchanged.Checklist
Summary by CodeRabbit