Skip to content

fix: preserve compaction progress and use a 600s stall budget - #3736

Closed
Hylouis233 wants to merge 5 commits into
lidge-jun:devfrom
Hylouis233:fix/compaction-progress-watchdog
Closed

fix: preserve compaction progress and use a 600s stall budget#3736
Hylouis233 wants to merge 5 commits into
lidge-jun:devfrom
Hylouis233:fix/compaction-progress-watchdog

Conversation

@Hylouis233

@Hylouis233 Hylouis233 commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Primary work delivered — superseded

Content-free compaction progress shipped through #3792. The global 600-second default is an unadopted separate proposal; the released default remains 300 seconds. Both the main delivery and its retained scope are documented in the closure comment. Released in v2.46.0.

Summary

Buffered Responses compaction accumulates text until EOF without reporting upstream progress. The stall watchdog can therefore cancel a response even while text or reasoning deltas continue to arrive.

  • Emit content-free progress events for non-empty text and reasoning deltas while preserving buffered output and the authoritative completed snapshot. Gateway comments, empty deltas, and malformed deltas do not reset the watchdog.

  • Increase the default stall budget from 300 to 600 seconds while preserving explicit finite overrides.

  • Add compaction regressions, register them in both test-layout maps, and synchronize documented defaults across all eight locales.

Verification

  • Regression-first check: the original adapter failed all three active-progress cases; the corrected adapter passed all eight focused tests, including the timeout-default checks.

  • Affected-module run: 309 passed, 0 failed across compaction, Responses passthrough, bridge lifecycle, cancellation, timeout resolution, and test-layout guards:

    bun scripts/test.ts --parallel=2 tests/lib/stall-timeout.test.ts tests/responses/compaction-progress.test.ts tests/responses/openai-responses-passthrough.test.ts tests/responses/responses-compaction.test.ts tests/responses/responses-compaction-routing.test.ts tests/adapters/bridge-lifecycle.test.ts tests/responses/passthrough-abort.test.ts tests/test-layout.test.ts tests/test-layout-tooling.test.ts

  • bun run typecheck — passed.

  • bun run privacy:scan — passed.

  • cd docs-site && bun run build — passed; 425 pages built.

  • Offline installed-source probes on Windows and macOS passed for active-progress completion and comment-only expiry. Both installations were restarted with an explicit 600-second setting.

  • Independent behavior and privacy reviews passed. The behavior review found missing test-layout entries; both entries were added and the finding was rechecked.

  • Incomplete broad run: bun scripts/test.ts --changed=origin/dev exceeded the wrapper's 900-second suite limit (exit 124). No complete per-test result was produced, so this run is not claimed as passing. The affected-module run above completed successfully afterward.

  • Follow-up review fixes: use the shared test-budget cleanup helper, update derived web-search defaults to 630 seconds while retaining explicit overrides, correct stale architecture statements, and normalize the Japanese table delimiter. 78 tests passed, 0 failed across the updated compaction, web-search, Cursor stream-health, and timeout checks; typecheck, privacy scan, and the 425-page documentation build also passed.

  • The follow-up diff passed independent behavior and privacy audits. All three actionable inline discussions from the first review round have been addressed in code and resolved.

  • The standard local full-suite retry reached the 900-second parallel-lane limit (exit 124) after recording test failures; local CI readiness is not confirmed. Required upstream workflows are awaiting repository-administrator approval. Supplemental fork workflow 34009533322 finished with 23 successful jobs. Windows shard 1/6 failed in the existing Desktop client-lifecycle test fixture (ClientStateProbeError, child_failed), causing the aggregate CI failure. That bare-test startup failure is addressed by the follow-up below; fork results do not replace the required upstream checks.

Checklist

  • Scope stays focused and avoids unrelated cleanup.

  • Docs or release notes were updated when needed.

  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • New Features

    • Streaming Responses now recognize non-empty output and reasoning updates as upstream progress.
    • Buffered progress remains hidden until the completed response is ready.
    • Added coverage for compaction progress, keepalives, and stalled streams.
  • Bug Fixes

    • Increased the default upstream stall timeout from 5 to 10 minutes.
    • Empty updates and keepalive comments continue to leave stalled-provider detection active.
    • Updated web-search timeout calculations to reflect the longer default.
  • Documentation

    • Updated architecture and server configuration references across supported languages with the new default and timeout behavior.

@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Review 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: Team

Run ID: de06c6da-8c9b-44cc-826b-6d5777f2af63

📥 Commits

Reviewing files that changed from the base of the PR and between 7bd3b17 and 0aeb199.

📒 Files selected for processing (2)
  • scripts/test-run-lock.ts
  • tests/preload.ts

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


📝 Walkthrough

Walkthrough

The Responses bridge now emits heartbeats for non-empty output and reasoning deltas during compaction. The default upstream stall timeout changes from 300 to 600 seconds. Tests, timeout calculations, structure documents, localized references, and Windows test-lock propagation reflect the changes.

Changes

Responses stall handling

Layer / File(s) Summary
Compaction progress heartbeats
src/adapters/openai-responses.ts, tests/responses/compaction-progress.test.ts
Non-empty output and reasoning deltas emit heartbeat events. Tests cover buffered progress, ignored empty or malformed deltas, stall timeouts, and completed snapshots.
Default stall timeout
src/stall-timeout.ts, tests/lib/stall-timeout.test.ts, structure/01_runtime.md, tests/providers/cursor/cursor-stream-health.test.ts
The default changes from 300 to 600 seconds. Undefined and non-finite inputs resolve to 600, while finite-value handling and the 2-second sampling tick remain unchanged.
Timeout-dependent behavior
tests/web-search/*, structure/04-transports-and-sidecars.md
Web-search timeout expectations use the updated default and resulting 630- and 930-second budgets. Transport documentation records typed heartbeat frames and the updated watchdog calculation.
Localized and reference documentation
docs-site/src/content/docs/**/reference/architecture.md, docs-site/src/content/docs/**/reference/configuration/server.md
Architecture and server configuration references document the 600-second stallTimeoutSec default. The default-language architecture reference also documents compaction progress and gateway comment keepalives.
Test layout registration
scripts/test-layout/layout.json, tests/fixtures/test-layout-expected.json
The compaction progress test is assigned to the responses test domain and added to the expected layout fixture.

Windows test lock propagation

Layer / File(s) Summary
Nested test lock inheritance
scripts/test-run-lock.ts, tests/preload.ts
The Windows preload resolves wrapped-run lock paths, passes validated paths to lock acquisition, and exports lock information for nested fixtures. The related JSDoc is updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 0aeb1

Responses compaction now records non-empty text and reasoning deltas as progress without exposing buffered output, and the default stall timeout is extended to 600 seconds. No concrete current-head merge-blocking risk remains.

Sequence Diagram(s)

sequenceDiagram
  participant ResponsesStream
  participant ResponsesPassthroughAdapter
  participant StallWatchdog
  ResponsesStream->>ResponsesPassthroughAdapter: send non-empty output or reasoning delta
  ResponsesPassthroughAdapter->>StallWatchdog: emit heartbeat
  StallWatchdog-->>ResponsesPassthroughAdapter: keep compaction active
  ResponsesStream->>ResponsesPassthroughAdapter: send empty or malformed delta
  StallWatchdog-->>ResponsesPassthroughAdapter: emit upstream_stall_timeout after deadline
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 9 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes both primary changes: preserving Responses compaction progress and increasing the default stall budget to 600 seconds. It is concise, specific, and consistent with the …
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

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

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (1/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 1/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

1/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 74 / 80

이 PR은 Responses 버퍼 컴팩션이 업스트림에서 글자·추론 델타를 계속 받는데도, 브릿지 스톨 감시가 “침묵”으로 보고 응답을 끊는 문제를 고칩니다. 지금 dev(HEAD af344a28e, 패키지 2.44.0, macOS serial CI #3727/#3726 직후)에서 src/adapters/openai-responses.ts의 패스스루 파서는 컴팩션 모드일 때 텍스트 델타를 버퍼에만 쌓고 클라이언트로는 보내지 않습니다. 그런데 스톨 타이머를 다시 켜 주는 쪽은 어댑터 이벤트(또는 하트비트)에 의존합니다. 델타가 버퍼에만 들어가면 감시기는 아무 일도 없다고 생각하고, 기본 stallTimeoutSec 300초가 지나면 upstream_stall_timeout으로 response.incomplete를 냅니다. 긴 요약·추론이 실제로 진행 중인데도 끊기는 구멍입니다.

고치는 방법은 두 갈래입니다. 첫째, createResponsesPassthroughAdapter의 SSE 파싱에서 response.output_text.delta / response.reasoning_summary_text.delta / response.reasoning_text.delta이고 delta가 비어 있지 않은 문자열이면, 버퍼 내용은 그대로 두면서 { type: "heartbeat" }만 yield 합니다. 게이트웨이 SSE 주석, 빈 델타, 깨진 델타는 하트비트를 내지 않아서 “가짜 생존”으로 스톨을 가리지 않습니다. 둘째, src/stall-timeout.tsDEFAULT_STALL_TIMEOUT_SEC를 300에서 600으로 올리고, 문서 8개 로케일과 tests/lib/stall-timeout.test.ts를 맞춥니다. resolveStallTimeoutSec의 유한 override·최소 1 동작은 그대로입니다. 새 회귀 tests/responses/compaction-progress.test.ts는 활성 진행이 스톨을 피하는지, 주석/빈/깨진 델타만으로는 스톨이 나는지, 버퍼 텍스트가 와이어에 새지 않고 completed 스냅샷이 권위인지까지 확인합니다. layout.json과 fixture에도 등록했습니다.

우선순위 74인 이유다. 컴팩션·장시간 추론은 실제 Codex 사용 경로이고, HEAD의 Responses 패스스루/브릿지 불변식과 정면으로 맞닿아 있습니다. 코드 변경은 어댑터 하트비트 한 덩어리 + 기본값/문서/테스트라 머지 비용이 낮습니다. 다만 기본 스톨을 두 배로 늘리는 정책 변경이라 운영 영향(진짜 죽은 스트림이 더 오래 남는 것)은 메인테이너가 한 번 짚고 가야 합니다. 본문에 affected-module 309통과·typecheck·privacy:scan·docs 빌드는 적혀 있으나, --changed=origin/dev 전체는 900초 한도로 incomplete라고 스스로 밝힌 점, 그리고 draft + review readiness 체크리스트가 비어 있는 점은 머지 전에 채워야 합니다. types.ts/config.ts 대분할 close-don't-rebase 대상은 아닙니다.

라인 2550 근처 (PR diff src/adapters/openai-responses.ts) - 비어 있지 않은 text/reasoning 델타에서만 heartbeat yield. 버퍼 출력·completed 스냅샷은 그대로
경로/심볼 - src/stall-timeout.ts DEFAULT_STALL_TIMEOUT_SEC - 300 → 600. 명시적 유한 설정은 유지
경로 - docs-site/.../architecture.mdconfiguration/server.md (en+7 locales) - 문서 기본값 600으로 동기화
경로 - tests/responses/compaction-progress.test.ts - 활성 진행 3종·주석/빈/깨진 델타 스톨·버퍼 미노출 회귀
경로 - scripts/test-layout/layout.json / tests/fixtures/test-layout-expected.json - compaction-progress를 responses 레인에 등록
경로/심볼 - PR 본문 Verification - affected 309 통과는 주장하나 broad --changed는 exit 124 incomplete. draft이며 readiness 체크박스 미체크

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

  • 기본 스톨 600초가 제품 기본값으로 맞는지, 아니면 하트비트 수정만 머지하고 기본값은 300에 둘지
  • draft + incomplete broad suite를 머지 전에 어떻게 닫을지 (affected만으로 충분한지)
  • heartbeat를 text_delta 이벤트로 올리지 않고 별도 heartbeat로 두는 설계를 다른 어댑터 컴팩션 경로에도 같은 규칙으로 펼칠지

너의 추천
하트비트 쪽은 맞고 테스트가 핵심 회귀를 잡습니다. 기본값 600 정책만 한 줄 확정한 뒤, draft 해제·체크리스트 채우고 dev에 머지하세요. types/config 대분할로 close-don't-rebase 할 이유가 없습니다. 미리보기 배포 없음.

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

@Hylouis233
Hylouis233 marked this pull request as ready for review September 6, 2026 02:51
Copilot AI lite review requested due to automatic review settings September 6, 2026 02:51
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 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-06T05:45:19.896325Z 0aeb199 Draft marked ready
ℹ️ 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.

Copilot AI 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.

🟡 Changes recommended

The new test harness leaks a TranslatorBudget and the Japanese server configuration doc table row is malformed (missing a trailing |).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR improves reliability of the Responses bridge during buffered compaction by treating certain upstream deltas as progress (without leaking buffered content) and by increasing the default upstream stall watchdog budget to 600 seconds, with documentation and regression tests updated accordingly.

Changes:

  • Treat non-empty response.*.delta (text + reasoning) frames as upstream liveness during buffered compaction by yielding adapter heartbeat events, while still keeping the completed snapshot authoritative.
  • Increase the default stall timeout from 300s → 600s and update unit tests accordingly.
  • Add compaction progress regression tests, register them in test-layout maps, and synchronize docs defaults across locales.
File summaries
File Description
tests/responses/compaction-progress.test.ts Adds regressions ensuring buffered compaction stays alive on real deltas and still hides buffered content.
tests/lib/stall-timeout.test.ts Updates assertions for the new 600s default and non-finite fallback behavior.
tests/fixtures/test-layout-expected.json Registers the new compaction progress test under the responses domain.
scripts/test-layout/layout.json Registers the new compaction progress test under the responses domain.
src/stall-timeout.ts Raises DEFAULT_STALL_TIMEOUT_SEC to 600 and updates explanatory comments.
src/adapters/openai-responses.ts Emits adapter heartbeats for non-empty text/reasoning deltas so the stall watchdog sees progress during buffered compaction.
docs-site/src/content/docs/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/reference/architecture.md Documents buffered-compaction progress semantics and the 600s default.
docs-site/src/content/docs/fr/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/fr/reference/architecture.md Updates documented default stall deadline to 600.
docs-site/src/content/docs/ja/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/ja/reference/architecture.md Updates documented default stall deadline to 600.
docs-site/src/content/docs/ko/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/ko/reference/architecture.md Updates documented default stall deadline to 600.
docs-site/src/content/docs/ru/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/ru/reference/architecture.md Updates documented default stall deadline to 600.
docs-site/src/content/docs/tr/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/tr/reference/architecture.md Updates documented default stall deadline to 600.
docs-site/src/content/docs/zh-cn/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/zh-cn/reference/architecture.md Updates documented default stall deadline to 600.
docs-site/src/content/docs/zh-tw/reference/configuration/server.md Updates documented default stallTimeoutSec to 600.
docs-site/src/content/docs/zh-tw/reference/architecture.md Updates documented default stall deadline to 600.
Review details
  • Files reviewed: 22/22 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/responses/compaction-progress.test.ts
Comment thread docs-site/src/content/docs/ja/reference/configuration/server.md Outdated

@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: 723348c33d

ℹ️ 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/stall-timeout.ts
@github-actions
github-actions Bot marked this pull request as draft September 6, 2026 03:28
@Hylouis233
Hylouis233 marked this pull request as ready for review September 6, 2026 05:41
@github-actions
github-actions Bot marked this pull request as draft September 6, 2026 05:41
zigzag-007 pushed a commit to zigzag-007/opencodex that referenced this pull request Sep 6, 2026
Carry the progress portion of lidge-jun#3736 and adapt lidge-jun#3744 to release listener idle protection only after a complete valid request body. Preserve the 300-second default and existing encrypted output.

Local validation deferred to the final hosted CI by maintainer instruction.

Co-authored-by: mashfromband <matsumoto.yukuhashi@gmail.com>
Co-authored-by: Hylouis233 <88263959+Hylouis233@users.noreply.github.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Thank you for the compaction progress fix. Closing this PR as superseded by #3792 (823ffeb77125dc098fa20dbb1295f0ad60b1e114), included in released v2.46.0. The main fix forwards content-free progress from meaningful text/reasoning deltas without treating empty deltas or keepalive comments as progress; original attribution is retained.

The proposed global 600-second default was not adopted. src/stall-timeout.ts still defaults to 300 seconds, and explicit overrides remain available. That separate policy proposal should not keep the completed progress-fix PR open.

If a default change is still needed, please open a narrowly scoped proposal/PR with:

  • Evidence of a legitimate request timing out after the shipped progress fix, separating active upstream progress from actual silence.
  • The default/override contract in src/stall-timeout.ts, corresponding cases in tests/lib/stall-timeout.test.ts, and the derived web-search timeout in src/web-search/index.ts.
  • Tests preserving explicit finite overrides and keepalive-only expiry, plus consistent default documentation.

Do not recarry the already shipped compaction-progress implementation. A new default requires its own review; this closure does not approve 600 seconds.

@lidge-jun lidge-jun closed this Sep 7, 2026
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.

3 participants