Skip to content

fix(responses): normalize SSE terminal tails and policy failures (rebase of #2488) - #2581

Merged
lidge-jun merged 20 commits into
devfrom
codex/sse-terminal-2488
Aug 25, 2026
Merged

fix(responses): normalize SSE terminal tails and policy failures (rebase of #2488)#2581
lidge-jun merged 20 commits into
devfrom
codex/sse-terminal-2488

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Summary

Rebase of #2488 (by @AiriDea) onto current dev — 19 commits, no conflicts — plus a
regression for the review's nested-envelope finding.

The change normalizes Responses SSE terminal tails and policy failures. Two review
blockers were raised; both were re-checked against the rebased head:

  1. adapterFailureFromEvent overwriting the classified policy code before testing it.
    Already fixed on the author's branch: src/bridge.ts now tests
    isCyberPolicyCode(error.code) || isCyberPolicyCode(event.code) and forces HTTP 400,
    so a conflicting-code policy failure can no longer stay 502/retryable.
  2. A generic outer envelope hiding a nested cyber_policy. I wrote the regression the
    review asked for, and it passes on the current code: consumeComboFailure classifies
    on the full display-safe text as well as the extracted code, so a nested policy body
    already resolves to a non-retryable 400.

I did not change the normalizer for (2). I had a patch that narrowed candidate
selection to policy-bearing envelopes first, then drove it red to check it was load-bearing
— it was not, so I reverted it and kept only the test. The test still earns its place: it
fails if a future refactor narrows detection to the first field-bearing candidate, which is
exactly the retry-across-a-safety-boundary the review was guarding against.

Closes #2488.

Verification

$ bun test tests/cyber-policy-error-fidelity.test.ts
 17 pass, 0 fail

$ bun test tests/cyber-policy-error-fidelity.test.ts tests/passthrough-abort.test.ts tests/bridge-sse.test.ts
 54 pass, 0 fail, 218 expect() calls

# AGENTS.md requires this gate for anything touching core.ts / src/lab
$ bun test tests/core-lab-boundary.test.ts
 13 pass, 0 fail

$ bun x tsc --noEmit
(clean)

Checklist

  • Targets dev
  • Rebased onto the current dev head (19/19, no conflicts)
  • Core/lab boundary gate green
  • Typecheck clean
  • Original authorship preserved in the commit history
  • No secrets or account identifiers in the diff

Summary by CodeRabbit

  • Bug Fixes

    • Improved Responses streaming termination, including clean EOF, premature [DONE], malformed terminal data, and incomplete responses.
    • Prevented duplicate terminal markers and unsafe success completion when terminal data is truncated.
    • Improved handling of upstream read and relay failures.
  • Security

    • Cyber-policy errors now use consistent error details, HTTP 400 responses, secret redaction, and non-retryable behavior.
    • Prevented retries or request replay after a response has begun.
  • Documentation

    • Added proxy-format guidance in English, Chinese, Japanese, Korean, and Russian.

Codex and others added 20 commits August 26, 2026 01:13
The review asked for a regression proving a nested cyber_policy is not hidden
by a generic outer envelope. Adding it showed the detection already holds:
consumeComboFailure classifies on the full display-safe text as well as the
extracted code, so the nested case resolves to a non-retryable 400 today.

Recording it as a test rather than changing the normalizer, so a future
refactor that narrows detection to the first field-bearing candidate fails
here instead of silently retrying across a safety boundary.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 25, 2026 16:16
@lidge-jun
lidge-jun merged commit d459659 into dev Aug 25, 2026
8 of 9 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@lidge-jun
lidge-jun deleted the codex/sse-terminal-2488 branch August 25, 2026 16:17
@github-actions github-actions Bot added the bug Something isn't working label Aug 25, 2026
@coderabbitai

coderabbitai Bot commented Aug 25, 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: adcdbf79-4e44-4c95-8a23-0ca729f4e2b1

📥 Commits

Reviewing files that changed from the base of the PR and between 342911f and 2e8fe53.

📒 Files selected for processing (40)
  • docs-site/src/content/docs/ja/reference/proxy-formats.md
  • docs-site/src/content/docs/ko/reference/proxy-formats.md
  • docs-site/src/content/docs/reference/proxy-formats.md
  • docs-site/src/content/docs/ru/reference/proxy-formats.md
  • docs-site/src/content/docs/zh-cn/reference/proxy-formats.md
  • src/bridge.ts
  • src/chat/outbound.ts
  • src/lab/fabric/producer-child.ts
  • src/lib/errors.ts
  • src/server/chat-completions.ts
  • src/server/chat-native-sse.ts
  • src/server/chat-native.ts
  • src/server/relay-eager.ts
  • src/server/relay.ts
  • src/server/request-log.ts
  • src/server/responses-terminal-repair.ts
  • src/server/responses/core.ts
  • src/server/responses/passthrough-error.ts
  • src/server/sse-frame-buffer.ts
  • structure/04_transports-and-sidecars.md
  • tests/chat-completions-endpoint.test.ts
  • tests/cli-restore-back.test.ts
  • tests/codex-app-server-processes.test.ts
  • tests/codex-composed-acceptance.test.ts
  • tests/codex-inject-write-lock.test.ts
  • tests/codex-retained-root-serialization.test.ts
  • tests/codex-sync-api.test.ts
  • tests/cyber-policy-error-fidelity.test.ts
  • tests/helpers/owned-service-home-preload.ts
  • tests/helpers/owned-service-home.ts
  • tests/helpers/windows-power-shell-fixture.ts
  • tests/lab-fabric-task.test.ts
  • tests/multi-agent-compat.test.ts
  • tests/owned-service-home.test.ts
  • tests/passthrough-abort.test.ts
  • tests/relay-eager.test.ts
  • tests/request-log.test.ts
  • tests/responses-terminal-repair.test.ts
  • tests/sse-failed-tail.test.ts
  • tests/terminal-guard-server.test.ts

📝 Walkthrough

Walkthrough

Changes

The PR normalizes Responses terminal handling and cyber_policy errors across relays, HTTP/SSE paths, request logs, and tests. It adds redaction, non-retryable policy responses, EOF handling, delimiter-less terminal handling, Windows service test seams, bounded child-process tests, and awaited producer execution.

Responses terminal and policy handling

Layer / File(s) Summary
Policy error normalization
src/lib/errors.ts, src/bridge.ts, src/chat/..., src/server/...
Cyber-policy errors now preserve credible upstream types, redact secrets, return status 400, disable retries, and suppress Retry-After.
Terminal relay and EOF handling
src/server/relay.ts, src/server/relay-eager.ts, src/server/responses-terminal-repair.ts
Relays defer premature [DONE], preserve valid terminal tails, synthesize adapter_eof on clean terminal-less EOF, and fail closed for unsafe repair candidates.
Logging, documentation, and validation
src/server/request-log.ts, docs-site/src/content/docs/**, structure/04_transports-and-sidecars.md, tests/*
Request logs, documentation, and tests cover terminal precedence, policy normalization, redaction, overflow, reader failures, rewrite failures, and replay behavior.

Windows and CI lifecycle validation

Layer / File(s) Summary
Windows service test infrastructure
tests/helpers/owned-service-home*.ts, tests/helpers/windows-power-shell-fixture.ts
Windows child processes can load a service-probe preload, and shared deterministic PowerShell fixtures support Windows and POSIX tests.
Child-process test wiring
tests/cli-restore-back.test.ts, tests/codex-*.test.ts, tests/multi-agent-compat.test.ts, tests/owned-service-home.test.ts
Child processes receive shared service-manager environments and preload arguments. Tests use shared fixtures and stronger cleanup assertions.
Bounded process and producer lifecycle
tests/codex-inject-write-lock.test.ts, tests/lab-fabric-task.test.ts, src/lab/fabric/producer-child.ts
Process tests use timeouts and reaping. The producer child awaits harness completion before exit.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Provider as Upstream provider
  participant Relay as Responses relay
  participant Log as Request log
  participant Client as Client
  Provider->>Relay: SSE terminal, DONE, EOF, or error
  Relay->>Relay: Parse terminal and normalize policy failure
  Relay->>Client: Terminal event and one DONE frame
  Relay->>Log: Record terminal status and error code
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/sse-terminal-2488

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e8fe53c9f

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/server/relay.ts
Comment on lines +197 to +201
} else if (!pendingDone) {
// Do not expose a sentinel before a Responses terminal. If EOF
// follows, the synthetic incomplete path owns the one sentinel;
// if a terminal arrives later, this pending frame is emitted then.
pendingDone = { block: outboundBlock, delimiter: frame.delimiter };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bound waits after a terminal-less DONE

When a Responses-compatible upstream emits data: [DONE] without a preceding Responses terminal and keeps the response body open, this branch retains the sentinel and emits nothing; both native relay loops then remain blocked on the next reader.read(), so the client, request log, and turn cleanup can hang indefinitely because the EOF synthesis path is never reached. Treat a lone DONE as an incomplete terminal or start a bounded wait before synthesizing that failure.

AGENTS.md reference: src/AGENTS.md:L15-L19

Useful? React with 👍 / 👎.

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.

2 participants