Skip to content

test(responses): assert the stream completed, not that it lacks the digits 502 - #4860

Merged
lidge-jun merged 1 commit into
devfrom
codex/2580-sse-error-oracle
Sep 17, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/2580-sse-error-oracle

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Summary

Windows shard 4/9 of run 35180376537 went red on a turn that had succeeded perfectly:

182 |       expect(text).not.toContain("502");
error: expect(received).not.toContain(expected)
Expected to not contain: "502"
Received: ...,"id":"chatcmpl-05021785ecf5440c96ca31be","object":"chat.completion.chunk",...

The relay stamps every chunk with a random chatcmpl-<hex> id. This run drew chatcmpl-05021785ecf5440c96ca31be, the assertion searched the whole stream for the three characters 502, found them inside that id, and failed.

tests/images/loop.test.ts already retired the identical assertion for "504" and measured the rate: roughly one id in 137 contains a given three-digit string, which reddened about one run in 69 for no reason at all.

The assertion could not do its job either. This relay's failure mode carries an error frame and ends the turn; the number 502 never appears in the body, so a real failure would have slipped straight past it. It was simultaneously flaky and blind — which is the worst combination a test can have, and exactly the pattern this round has been removing.

It now asserts the terminal shape: the stream reached [DONE] and carried no error frame. That detects the failure the case was written for and cannot be moved by a random identifier.

Verification

No local suite, focused test, typecheck, build, or install was run; this lane is hosted-CI-only by task contract. Verification is static plus exact-head hosted CI.

Static checks:

  • A repository-wide search for the same oracle shape (not.toContain on a bare 4xx/5xx number) found three other sites. Two are in tests/adapters/anthropic/anthropic-pool-toggle-copy.test.ts and assert that UI copy strings do not mention 429 — those operate on short authored strings, not on payloads carrying random ids, so they are sound and untouched. The third is the already-fixed comment in tests/images/loop.test.ts. This was the last live instance.
  • The mock upstream's streaming frames are fully deterministic; the only random content in the response is the id the relay itself adds, which confirms the mechanism.
  • git diff --check clean.

Ablation: a relay failure emits an error frame and no [DONE], so both new assertions go red on the behaviour the case exists to catch — which the old assertion did not.

Checklist

  • Root cause fixed; the oracle now measures the behaviour rather than a digit sequence
  • No timeout widened, no retry added, no test skipped
  • No production behaviour changed
  • Targets dev

Summary by CodeRabbit

  • Tests
    • Updated streaming deferred-tool validation to confirm streams end with the expected completion marker.
    • Improved checks to ensure completed streams do not include an error payload.
    • Added context explaining the updated validation approach.

…igits "502"

Windows shard 4/9 of run 35180376537 went red on a turn that had succeeded
perfectly. The relay stamps every chunk with a random chatcmpl-<hex> id, and this
run drew chatcmpl-05021785ecf5440c96ca31be. expect(text).not.toContain("502")
searched the whole stream, found those three characters inside the id, and failed.

tests/images/loop.test.ts already retired the identical assertion for "504" and
measured it: roughly one id in 137 contains a given three-digit string, which
reddened about one run in 69 for no reason at all.

The assertion could not do its job either. This relay's failure mode carries an
error frame and ends the turn; the number 502 never appears in the body, so a real
failure would have slipped straight past it. It was simultaneously flaky and blind.

Assert the terminal shape instead: the stream reached [DONE] and carried no error
frame. That detects the failure the case was written for and cannot be moved by a
random identifier.

No local suite, focused test, typecheck, build, or install was run.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 17, 2026 04:28
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T04:30:44.969118Z c5e9bc8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). label Sep 17, 2026
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b0bf90fd-ded9-4a4b-8fbc-47b358c5a9a1

📥 Commits

Reviewing files that changed from the base of the PR and between 121405b and c5e9bc8.

📒 Files selected for processing (1)
  • tests/responses/chat-completions-deferred-tools.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The deferred-tool streaming relay test replaces a broad "502" text search with assertions for data: [DONE] and the absence of "error".

Changes

Deferred-tool stream validation

Layer / File(s) Summary
Validate terminal stream output
tests/responses/chat-completions-deferred-tools.test.ts
The test now verifies the stream ends with data: [DONE] and does not contain "error". A comment explains why the previous "502" assertion was fragile.

Priority: ⬇️ Low

Estimated code review effort: 1 (Trivial) | ~3 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to c5e9b

This test-only change improves detection of relay failures without changing production behavior.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change in tests/responses/chat-completions-deferred-tools.test.ts: it replaces the fragile absence-of-"502" assertion with validation that the stream completes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/2580-sse-error-oracle

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 commented Sep 17, 2026

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 77 / 80

이 PR은 tests/responses/chat-completions-deferred-tools.test.ts 한 파일만 고칩니다. 바꾸는 테스트는 relays undeclared function call when client streams with partial tools declared 입니다. 예전에 스트림 전체 글자열에 숫자 502가 들어 있지 않은지 검사했는데, 이제는 스트림이 끝까지 갔는지와 에러 프레임이 없는지를 검사합니다.

왜 바꿨는지가 분명합니다. Windows shard 4/9 실행 (Actions run 35180376537)에서 이미 성공한 턴이 빨개졌습니다. 릴레이가 청크마다 chatcmpl-<hex> 아이디를 붙이는데, 그 아이디 안에 0502…처럼 502 세 글자가 우연히 들어갔습니다. expect(text).not.toContain("502")는 그 아이디까지 검색해서 실패했습니다. 같은 종류의 함정은 tests/images/loop.test.ts에서 "504" 검사로 이미 한 번 치웠고, 대략 아이디 137개 중 하나에 세 자리가 들어가 실행 69번 중 한 번쯤 헛실패한다고 적혀 있습니다.

더 큰 문제는 이 검사가 진짜 실패도 못 본다는 점입니다. 이 릴레이가 실패할 때는 본문에 502 숫자가 아니라 에러 프레임을 넣고 턴을 끝냅니다. 그래서 예전 검사는 헛실패도 하고, 진짜 실패도 놓치는 최악의 조합이었습니다. 지금 dev 방향(#4846 행동으로 계약 검사, #4859 잠금 대기 마커, loop.test.ts 터미널 이벤트 검사)과 정확히 같은 줄입니다. 소스 모양이나 우연한 글자열이 아니라, 관측 가능한 끝 모양을 봅니다.

새 검사는 두 줄입니다. expect(text).toContain("data: [DONE]")로 SSE가 정상 종료했는지 보고, expect(text).not.toContain("\"error\"")로 에러 프레임이 없는지 봅니다. chat completions 스트림이라 loop.test.ts의 event: response.completed / response.failed와는 이벤트 이름이 다르지만, 같은 생각입니다. 프로덕션 코드는 안 건드리고, 타임아웃 늘리기·재시도·스킵도 없습니다.

현재 dev HEAD는 121405b53(#4859 lock-child DB 격리)이고 패키지는 2.58.0입니다. 이 PR은 그 위에 얹히는 테스트 전용 수정이라 충돌 위험이 거의 없습니다. types.ts/config.ts 분할 캠페인과도 무관합니다. 호스티드 CI만으로 검증하기로 한 계약이라 로컬 스위트는 돌리지 않았고, 이 시점 CI는 hygiene/enforce-target 등은 통과, Linux/macOS/Windows 테스트 레그는 아직 pending입니다. 플레익이 Windows shard에서 났으니 Windows exact-head가 초록인지가 핵심 확인입니다.

라인 196 - not.toContain("\"error\"")는 따옴표 포함 부분 문자열이라, 도구 인자나 본문에 우연히 "error"가 들어가면 또 헛실패할 수 있다. 지금 mock 업스트림은 결정적이라 당장 위험은 낮지만, loop.test.ts처럼 이벤트 타입(event: …)이나 JSON 키 경로를 더 좁히면 더 단단하다.
라인 195 - data: [DONE] 포함 검사는 chat completions SSE에는 맞고, 실제 실패 모드(에러 프레임 + DONE 없음)와도 맞다. 다만 DONE만 보고 error를 안 보면 안 되므로 두 줄이 한 세트라는 점을 유지해야 한다.
경로 tests/responses/chat-completions-deferred-tools.test.ts - 파일 상단 주석(#4735 deferred tool relay)과 이번 오라클 교체는 잘 맞는다. 비스트림 형제 테스트는 JSON status로 이미 다른 경로라 손대지 않은 선택이 맞다.

메인테이너의 판단이 필요한 지점

  • "error" 부분 문자열을 더 좁은 터미널 마커로 바꿀지, 지금 mock 결정성에 맡기고 머지할지
  • Windows 9-shard exact-head가 초록이 된 뒤에만 머지할지(플레익 재현 레그), 아니면 Linux 통과만으로 충분한지
  • 저장소에 남은 not.toContain("429") UI 카피 검사는 짧은 작성 문자열이라 건드릴 필요 없다는 PR 본문 주장이 맞는지(동의 가능)

너의 추천

이 댓글은 grok-bot이 작성했습니다

@lidge-jun
lidge-jun merged commit 7a29e7b into dev Sep 17, 2026
29 checks passed
@lidge-jun
lidge-jun deleted the codex/2580-sse-error-oracle branch September 17, 2026 04:39
agentHits pushed a commit to agentHits/opencodex that referenced this pull request Sep 17, 2026
…igits "502" (lidge-jun#4860)

Windows shard 4/9 of run 35180376537 went red on a turn that had succeeded
perfectly. The relay stamps every chunk with a random chatcmpl-<hex> id, and this
run drew chatcmpl-05021785ecf5440c96ca31be. expect(text).not.toContain("502")
searched the whole stream, found those three characters inside the id, and failed.

tests/images/loop.test.ts already retired the identical assertion for "504" and
measured it: roughly one id in 137 contains a given three-digit string, which
reddened about one run in 69 for no reason at all.

The assertion could not do its job either. This relay's failure mode carries an
error frame and ends the turn; the number 502 never appears in the body, so a real
failure would have slipped straight past it. It was simultaneously flaky and blind.

Assert the terminal shape instead: the stream reached [DONE] and carried no error
frame. That detects the failure the case was written for and cannot be moved by a
random identifier.

No local suite, focused test, typecheck, build, or install was run.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant