Skip to content

feat(streaming): rebuild bounded result records on current main - #172

Merged
seonghobae merged 11 commits into
mainfrom
feat/result-streaming-rebuild-current-main
Aug 13, 2026
Merged

seonghobae merged 11 commits into
mainfrom
feat/result-streaming-rebuild-current-main

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Current-main replacement for #58

This PR rebuilds the bounded result-streaming slice from protected main rather than transferring #58's stale stack ancestry. No #58 checks, reviews, approvals, generated-merge evidence, or stale-base evidence transfer.

Test-first reconstruction

  • RED 86748e96968725509b343d67e09dbd6b42b1fc8f replayed realistic incremental result/error JSONL regressions and failed because the protected package had no BatchResultRecord / StreamingBatchAPIClient surface.
  • GREEN added the bounded streaming implementation and public exports while preserving the protected BatchAPIClient credential, timeout, retry, response-size, retention, lifecycle, and session-ownership contracts.
  • Integration exposed stale test assumptions around structured ValidationError evidence and the protected post-response-handoff no-replay contract; those were aligned without weakening production behavior.
  • Exact-head CI on ac8788c2e5d8e78b17c6ad6539505260218361d1 then found one genuine acceptance defect: the finite-return path of _reject_non_finite_float() was uncovered even though the exponent-overflow rejection path was covered.
  • Current head d163245a1cae534a5e1b574ae51716594ad1d2ae adds the narrow realistic finite JSON-float regression (1.25) so both finite acceptance and non-finite rejection are exercised.

The feature provides incremental result/error record parsing, strict UTF-8/JSON-object framing, duplicate-member and non-finite-number rejection, per-line/record/physical-line/download ceilings, batch-wide physical-line accounting, deterministic early close, and a no-replay boundary once a provider response has been handed to the consumer. It adds no schema, migration, credential, model, scheduler, package-version, or release authority.

Exact-head and live-base evidence

Protected main is c262d9d60e559855ac943a53f6ae084f406c6a40, and this PR remains mergeable against it. On current exact head d163245a1cae534a5e1b574ae51716594ad1d2ae, repository CI is GREEN including Python 3.10/3.12/3.14, exact owned production coverage/docstrings/package, lock freshness, and component/PostgreSQL container smokes; Release Acceptance is GREEN. Current exact-head CodeQL, OSV, Trivy, Semgrep OSS, and OpenCode evidence is also terminal-success.

The current exact-head Strix required workflow is still in progress, so this PR is not yet merge-eligible. Pending required evidence is not transferred from the predecessor source head. Final review-thread state and every live required workflow must be freshly rechecked after Strix becomes terminal.

Merge boundary

Merge only while exact head d163245a1cae534a5e1b574ae51716594ad1d2ae remains unchanged and mergeable against the then-live protected base, all live required workflows are terminal-success, and zero valid unresolved review findings remain. After protected integration, close #58 only after fresh comparison proves its unique bounded-streaming behavior is preserved, then rebuild #59 and downstream checkpoint/audit work from the protected result in dependency order.

Summary by CodeRabbit

  • 새로운 기능

    • 배치 결과 및 오류 파일을 스트리밍 방식으로 순차 처리할 수 있습니다.
    • 결과 레코드를 비동기 반복자로 제공하며 공개 API로 사용할 수 있습니다.
    • 조기 종료 시 스트리밍 응답을 안전하게 정리합니다.
  • 버그 수정

    • 완료되지 않은 배치, 잘못된 파일 응답, 손상된 UTF-8·JSON 및 비정상 레코드를 명확한 오류로 처리합니다.
    • 레코드·물리적 라인·라인 크기·다운로드 청크 제한을 적용합니다.
    • 중복 JSON 키와 비유한 숫자를 거부하며, 스트리밍 오류 시 중복 요청과 리소스 누수를 방지합니다.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

StreamingBatchAPIClient와 BatchResultRecord를 공개 API로 추가했습니다. 배치 결과와 오류 JSONL을 제한된 비동기 스트림으로 처리합니다. 엄격한 파싱, 오류 진단, 응답 종료, 재시도 동작을 검증하는 테스트를 추가했습니다.

Changes

배치 결과 스트리밍

Layer / File(s) Summary
공개 API와 제한 계약
pg_llm_batch/__init__.py, pg_llm_batch/result_streaming.py, tests/test_bounded_jsonl_result_streaming.py, tests/test_bounded_jsonl_physical_line_budget.py
StreamingBatchAPIClient와 BatchResultRecord를 공개 API로 노출합니다. JSONL 라인, 물리 라인, 레코드 제한과 생성자 검증을 추가합니다.
배치 파일 조회와 응답 인계
pg_llm_batch/result_streaming.py, tests/test_bounded_jsonl_result_streaming.py
완료 상태와 파일 식별자를 확인한 뒤 결과 파일과 오류 파일을 순서대로 스트리밍합니다. HTTP 상태, 콘텐츠 길이, 스트림 지원 여부를 검증합니다.
제한된 JSONL 파싱
pg_llm_batch/result_streaming.py, tests/test_bounded_jsonl_physical_line_budget.py, tests/test_bounded_jsonl_result_streaming.py, tests/test_bounded_jsonl_result_streaming_coverage.py, tests/test_result_streaming_numeric_contract.py
청크 단위 UTF-8 및 JSONL 파싱을 구현합니다. 빈 라인, CRLF, 물리 라인 예산, 다운로드 바이트, 중복 키, 비유한 숫자와 객체 형식을 검증합니다.
응답 종료와 전송 인계
pg_llm_batch/result_streaming.py, tests/test_bounded_jsonl_result_streaming_coverage.py, tests/test_streaming_transport_handoff.py
비동기 컨텍스트 관리자와 aclose()를 제공합니다. 소비자 오류, 취소, 페이로드 오류와 응답 종료 오류를 재시도 없이 전파하고 응답을 한 번만 종료합니다.

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

Mergeability Score: 🟡 Moderate · up to d1632

The new streaming client performs credential and provider access without an explicitly validated tenant scope, which could weaken tenant isolation or use an unintended scope. Merge should wait for scope validation and the related contract documentation.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant StreamingBatchAPIClient
  participant BatchAPIClient
  participant ProviderAPI
  Caller->>StreamingBatchAPIClient: iter_batch_records 호출
  StreamingBatchAPIClient->>BatchAPIClient: 배치 상태 조회
  BatchAPIClient->>ProviderAPI: 결과 파일 스트리밍 요청
  ProviderAPI-->>StreamingBatchAPIClient: JSONL 바이트 청크
  StreamingBatchAPIClient-->>Caller: BatchResultRecord 반환
  StreamingBatchAPIClient->>ProviderAPI: 오류 파일 스트리밍 요청
  ProviderAPI-->>StreamingBatchAPIClient: JSONL 바이트 청크
  StreamingBatchAPIClient-->>Caller: 오류 BatchResultRecord 반환
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed 구현과 테스트는 이슈 #58의 스트리밍, 제한, 엄격한 파싱, 결정적 종료 및 재생 방지 요구사항을 충족합니다.
Out of Scope Changes check ✅ Passed 변경 사항은 이슈 #58의 스트리밍 구현과 관련 회귀·계약 테스트 범위에 포함됩니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 현재 main 기준의 bounded 결과 레코드 스트리밍 기능 재구축이라는 주요 변경 사항을 명확히 설명합니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/result-streaming-rebuild-current-main

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.

@seonghobae
seonghobae marked this pull request as ready for review August 12, 2026 23:52

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
pg_llm_batch/result_streaming.py (1)

61-69: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

제한 검증 방식을 기존 헬퍼와 통일하십시오.

pg_llm_batch/token_counter.py의 _require_positive_limit은 type(value) is not int로 정확한 int만 허용합니다. 여기서는 isinstance를 사용하므로 IntEnum 같은 int 서브클래스가 통과합니다. 동작 차이는 작지만, 두 검증 경로의 규칙을 같게 유지하면 계약이 명확해집니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pg_llm_batch/result_streaming.py` around lines 61 - 69, Update
_validate_positive_integer to use the same exact-int check as token_counter.py’s
_require_positive_limit, rejecting int subclasses such as IntEnum while
preserving the existing positive-value validation and ValidationError behavior.
pg_llm_batch/__init__.py (1)

9-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

공개 API 문서에 BatchResultRecord도 추가하십시오.

__all__은 BatchResultRecord와 StreamingBatchAPIClient를 함께 노출합니다. 그러나 모듈 docstring의 API 목록에는 StreamingBatchAPIClient만 있습니다. 두 이름을 모두 나열하면 문서와 공개 계약이 일치합니다.

♻️ 제안 변경
     StreamingBatchAPIClient             -- bounded incremental result records
+    BatchResultRecord                   -- immutable streamed result/error record

Also applies to: 43-51

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pg_llm_batch/__init__.py` at line 9, 모듈 docstring의 공개 API 목록에 __all__로 노출되는
BatchResultRecord를 추가하고, 기존 StreamingBatchAPIClient 항목은 유지하여 문서와 실제 공개 계약이 일치하도록
수정하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pg_llm_batch/result_streaming.py`:
- Around line 72-74: Ensure all parsed JSON floating-point values are finite,
including exponent-overflow values such as 1e999: add a parse_float hook
alongside _reject_non_finite_json_constant that validates the converted value
and raises ValueError for non-finite results, then wire it into the relevant
JSON parsing calls. Add coverage for b'{"value":1e999}\n' and preserve rejection
of NaN and Infinity literals.

---

Nitpick comments:
In `@pg_llm_batch/__init__.py`:
- Line 9: 모듈 docstring의 공개 API 목록에 __all__로 노출되는 BatchResultRecord를 추가하고, 기존
StreamingBatchAPIClient 항목은 유지하여 문서와 실제 공개 계약이 일치하도록 수정하세요.

In `@pg_llm_batch/result_streaming.py`:
- Around line 61-69: Update _validate_positive_integer to use the same exact-int
check as token_counter.py’s _require_positive_limit, rejecting int subclasses
such as IntEnum while preserving the existing positive-value validation and
ValidationError behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c1e7bc08-3039-4414-ba2a-3f68c968abd7

📥 Commits

Reviewing files that changed from the base of the PR and between 12929b5 and 9319599.

📒 Files selected for processing (6)
  • pg_llm_batch/__init__.py
  • pg_llm_batch/result_streaming.py
  • tests/test_bounded_jsonl_physical_line_budget.py
  • tests/test_bounded_jsonl_result_streaming.py
  • tests/test_bounded_jsonl_result_streaming_coverage.py
  • tests/test_streaming_transport_handoff.py

Comment thread pg_llm_batch/result_streaming.py

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pg_llm_batch/result_streaming.py (1)

107-115: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

tenant_scope를 명시적으로 받고 provider 경계 전에 검증하십시오.

StreamingBatchAPIClient는 get_batch_status()와 _iter_jsonl_file()에서 자격 증명 조회와 provider I/O를 수행합니다. 생성 시 검증된 tenant scope를 받지 않으므로 이 경계 전에 scope를 검증할 수 없습니다.

tenant_scope를 추가하고 기본값은 정확히 "standalone"로 유지하십시오. endpoint_alias, remote ID, provider 데이터 또는 transport header에서 scope를 도출하지 마십시오. 계약 변경에 맞춰 관련 문서와 CHANGELOG를 갱신하십시오. DurableBatchAPIClient의 기존 네 인수 recorder seam은 유지하십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pg_llm_batch/result_streaming.py` around lines 107 - 115,
StreamingBatchAPIClient.__init__에 tenant_scope 인수를 추가하고 기본값을 정확히 "standalone"으로
설정한 뒤, get_batch_status()와 _iter_jsonl_file()이 자격 증명 조회 또는 provider I/O 전에 생성 시
전달된 scope를 검증하도록 연결하십시오. scope는 endpoint_alias, remote ID, provider 데이터,
transport header에서 추론하지 말고, 관련 문서와 CHANGELOG를 계약 변경에 맞게 갱신하며
DurableBatchAPIClient의 기존 네 인수 recorder seam은 유지하십시오.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@pg_llm_batch/result_streaming.py`:
- Around line 107-115: StreamingBatchAPIClient.__init__에 tenant_scope 인수를 추가하고
기본값을 정확히 "standalone"으로 설정한 뒤, get_batch_status()와 _iter_jsonl_file()이 자격 증명 조회
또는 provider I/O 전에 생성 시 전달된 scope를 검증하도록 연결하십시오. scope는 endpoint_alias, remote
ID, provider 데이터, transport header에서 추론하지 말고, 관련 문서와 CHANGELOG를 계약 변경에 맞게 갱신하며
DurableBatchAPIClient의 기존 네 인수 recorder seam은 유지하십시오.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 47c87992-b33c-49df-a0c2-21b56c28eb59

📥 Commits

Reviewing files that changed from the base of the PR and between 9319599 and d163245.

📒 Files selected for processing (3)
  • pg_llm_batch/__init__.py
  • pg_llm_batch/result_streaming.py
  • tests/test_result_streaming_numeric_contract.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • pg_llm_batch/init.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant