Skip to content

feat(streaming): bound incremental result records - #58

Closed
seonghobae wants to merge 2 commits into
agent/release-artifact-dirfd-verificationfrom
agent/bounded-jsonl-result-streaming
Closed

feat(streaming): bound incremental result records#58
seonghobae wants to merge 2 commits into
agent/release-artifact-dirfd-verificationfrom
agent/bounded-jsonl-result-streaming

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Product and reliability gap

Bounded aggregate provider-file downloads still materialize complete JSONL and parsed records. This Draft adds an opt-in incremental result path with explicit physical-line accounting, deterministic response ownership, provider-payload confidentiality, and a post-handoff at-most-once application-delivery boundary while preserving the aggregate API.

Bounded behavior

  • StreamingBatchAPIClient + immutable BatchResultRecord are opt-in.
  • Result then error records stream under inherited HTTPS, credential, no-redirect, timeout, identifier, retry and decoded-byte controls.
  • Per-line bytes, total physical lines, total decoded bytes and record count are bounded before excessive yield/buffering.
  • Strict UTF-8 and one unambiguous JSON object per nonblank line; non-finite values and duplicate names fail closed.
  • open_batch_records() is the deterministic-close consumer boundary.
  • Retry eligibility ends before response handoff; post-handoff payload/close failures do not replay yielded records.
  • Exported exception links do not retain provider bytes/text.

Current exact staged state

  • Head: c0b26eb8746820b13f7ef0f4d191827a8f7e2a94.
  • Exact immediate base: feat(release): deliver descriptor-pinned reproducible evidence #57 head 6a6fac2a99134f2bf0271d0d550dffd36ddb6d9c.
  • Ancestry: one commit ahead / zero behind; merge base equals the exact base.
  • CI 31284475447: success.
  • Release Acceptance 31284475435: success.
  • CodeRabbit status: success; latest returned unresolved inline threads: zero.
  • These are staged-stack evidence only, not protected-main acceptance.

Dependency chain

Current order is:

.github#790 -> #53 -> #57 -> this PR -> #59 -> #60 -> #92 -> #94 -> #95 -> #96 -> #97.

Keep Draft while predecessors are unintegrated. After protected integration of prerequisites, reconcile/retarget only for integration correctness and reacquire every required exact-head/exact-base CI, security, dependency, SBOM/provenance, packaging, semantic-review, branch-policy, and repository-policy gate.

Merge only when the unchanged final head has zero valid unresolved findings and every review/approval requirement actually imposed by live policy is satisfied. The protected code-owner gate is disabled/on hold for the current solo-maintainer state and must not be inferred as a universal approval requirement. Queued/pending/failed/cancelled/skipped/absent/stale/predecessor/synthetic/status-only/author-only/rate-limited evidence is not final success.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 84ab2dbc-7e0b-4a34-9e2f-89e560b8ef80

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head lifecycle finding on a7af1ee08681edcf6e4e38f8fcf9dd85f340b0d9: the public operator documentation currently states that an early async for break closes the active response through normal asynchronous-generator cleanup, but Python's asynchronous iteration protocol does not call aclose() on break. Because iter_batch_records() delegates to _iter_jsonl_file(), an early consumer exit can leave the inner generator and its _request() response context open until explicit closure or nondeterministic finalization.

Fix test-first without weakening the streaming contract. Add a deterministic response-context regression that consumes one record, exits early while retaining the iterator, and proves the response remains open on the current implementation. Then provide a beginner-readable, supported deterministic-close API—such as an async context manager that owns and aclose()s the iterator in finally, or an explicitly documented contextlib.aclosing(...) usage contract—and prove early exit closes the active response exactly once. Ensure nested iterator closure is explicit, cancellation remains correct, exceptions are preserved, and docs/ADR/doctoring no longer claim implicit cleanup from a bare async for break. Do not add a write-capable workflow or mutate any other stacked branch.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Two additional exact-head fail-closed findings on a7af1ee08681edcf6e4e38f8fcf9dd85f340b0d9:

  1. The advertised body-free parser boundary is not complete. _parse_jsonl_line() raises GatewayError with from exc for UnicodeDecodeError, JSONDecodeError/ValueError, and RecursionError. A JSON decoding exception retains the full decoded provider line in fields such as JSONDecodeError.doc; a Unicode decoding exception retains the original provider bytes. Exception-chain logging or inspection can therefore recover content that the public error message and response_data intentionally omit. Add RED tests that use distinctive secret bytes/text and assert the exported GatewayError retains no cause or context object containing the payload. Refactor so the sanitized error is raised outside the active except block (merely using from None still leaves __context__ attached), while preserving bounded error type/line metadata.

  2. The bounded-stream loop accepts zero-length byte chunks. A custom adapter can yield an unbounded sequence of b"" or empty memoryviews, making no byte progress and spinning indefinitely without reaching the line or total-download limits. Add a deterministic RED regression for an empty chunk and fail closed with a fixed body-free NoForwardProgress diagnostic before continuing. Preserve compatibility with real aiohttp iter_chunked() semantics and the 64 KiB maximum-chunk contract.

Implement test-first on this existing branch path only; no temporary write workflow or parallel branch writer is needed.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head follow-up on 50a362a56e44a74fbc467177a2eff6a422643c63: the three prior lifecycle and confidentiality findings are addressed test-first.

  • open_batch_records() now owns and closes the public iterator in finally; the public iterator explicitly owns each nested provider-file iterator with contextlib.aclosing.
  • Deterministic tests prove context-managed early break, explicit outer aclose(), repeated close, consumer exception propagation, and cancellation all close the active response exactly once while preserving the original exception.
  • Zero-length chunks fail closed with fixed NoForwardProgress metadata before any line buffering.
  • UTF-8 and JSON decoder failures are translated outside their active exception handlers; tests prove the exported GatewayError has neither __cause__ nor __context__ retaining provider bytes or text.
  • README, architecture, ADR 0005, AGENTS, CLAUDE, operator documentation, doctoring, and CHANGELOG now state that a bare async for break does not call aclose() and require explicit lifecycle ownership.

Exact-head CI run 31087306286 and Release Acceptance run 31087306374 both completed successfully; CodeRabbit is successful and unresolved inline review threads are zero. This is an author verification comment, not independent approval. The PR remains draft and stacked on exact base b6293ebf4c0f5957b3a5ba2de0f03c512cff7069; its evidence must be regenerated after prerequisite integration.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head remediation verification for 50a362a56e44a74fbc467177a2eff6a422643c63 against stacked base b6293ebf4c0f5957b3a5ba2de0f03c512cff7069:

  • deterministic RED coverage now proves context-managed early exit, explicit outer aclose(), nested provider response closure exactly once, consumer exception preservation, cancellation propagation, zero-progress chunk rejection, and parser cause/context confidentiality;
  • open_batch_records() owns the public iterator in finally, while iter_batch_records() owns each nested file iterator through contextlib.aclosing;
  • empty byte and memoryview chunks fail closed as NoForwardProgress before buffering;
  • invalid UTF-8 and malformed JSON are translated after their active decoder handlers, leaving exported GatewayError.__cause__ and .__context__ unset;
  • AGENTS, CLAUDE, ARCHITECTURE, ADR 0005, doctoring, user documentation, CHANGELOG, and the PR contract now state the exact lifecycle and confidentiality boundaries;
  • exact-head CI run 31087306286 and Release Acceptance run 31087306374 completed successfully; CodeRabbit status is successful and no unresolved review thread exists.

The PR remains a stacked draft and is not approved or merge-ready. All evidence must be regenerated after prerequisite integration and retargeting to main.

Copy link
Copy Markdown
Contributor Author

Exact-head author verification for 36bd1d3ad597d8d6cd6e7160198a6f622ec6d62f against stacked base b6293ebf4c0f5957b3a5ba2de0f03c512cff7069:

  • strict RED head fa89b38340f8993f412f6d5e094b4099a268beef produced seven intended failures on Python 3.10, 3.12, and 3.14 while 513 predecessor tests passed;
  • documentation RED head ea4678824da3ebc49f14552a240a3013bed3f187 failed the new public and authoritative contract checks;
  • current implementation validates max_jsonl_physical_lines, shares one local budget across result and error files, and counts blank, nonblank, newline-terminated, and final unterminated physical lines before decoding or parsing;
  • fixed body-free diagnostics expose only file kind, file-local line number, batch-wide count, and configured limit;
  • README, AGENTS, CLAUDE, architecture, CHANGELOG, operator documentation, ADR 0005, and doctoring now describe the exact control and cite RFC 8259, CWE-400, and OWASP API4:2023 where material;
  • exact-head CI run 31092557594 and Release Acceptance run 31092555210 completed successfully; CodeRabbit status is successful and unresolved inline review threads are zero.

This is author verification, not independent approval. The PR remains a stacked draft; all evidence must be regenerated after prerequisite integration and retargeting.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head transport lifecycle finding on 36bd1d3ad597d8d6cd6e7160198a6f622ec6d62f: BatchAPIClient._request() catches aiohttp.ClientError and asyncio.TimeoutError around the yield response boundary. A payload-stream failure raised by the consumer after the response has been handed off is therefore misclassified as a pre-handoff idempotent GET failure. With retry attempts remaining, the async context manager opens a second response while handling athrow(), which can produce RuntimeError: generator didn't stop after athrow() and may retry after records have already been yielded. That violates the streaming client's at-most-once record and deterministic body-failure boundary.

Fix test-first on the existing PR branch. Add a deterministic RED contract proving a post-handoff aiohttp.ClientPayloadError performs one GET, zero retry sleeps, and becomes one bounded GatewayError rather than reopening the request or exposing an async-contextmanager runtime error. Then separate request-acquisition/status retries from exceptions thrown by the caller body, preserve retries for failures before handoff, close the active response once, and add streaming-level coverage proving a mid-file payload failure never restarts from byte zero or duplicates records. Keep all current credential, timeout, no-redirect, Retry-After, status, coverage, docstring, and body-free diagnostic contracts unchanged.

seonghobae commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Superseded exact-head review request. The branch advanced after this comment from 0b49a40b1b75df29106a334673d96c8cb7d8180f to documentation-complete head 7fcd0ad4b4d2beedf0f753783e59fb57bf35d38d. Do not use this request or its cited runs as current review evidence; use the single exact-head request below.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="b6293ebf4c0f5957b3a5ba2de0f03c512cff7069"
head="0b49a40b1b75df29106a334673d96c8cb7d8180f"

echo "== Commit verification =="
git cat-file -e "${base}^{commit}"
git cat-file -e "${head}^{commit}"
git merge-base --is-ancestor "$base" "$head"
git diff --stat "$base" "$head"
echo
echo "== Changed files =="
git diff --name-status "$base" "$head"
echo
echo "== Python files in diff =="
git diff --name-only --diff-filter=AM "$base" "$head" | grep -E '\.py$' || true
echo
echo "== Python structural outlines =="
git diff --name-only --diff-filter=AM "$base" "$head" | grep -E '\.py$' | while IFS= read -r file; do
  echo "--- $file"
  ast-grep outline "$file" --items all --type class,function --view compact || true
done
echo
echo "== Targeted symbol references =="
rg -n -C 3 --glob '*.py' \
  'StreamingBatchAPIClient|BatchResultRecord|open_batch_records|download_results|_request|ClientPayloadError|max_jsonl_physical_lines|iter_chunked|iter_any|aclose|close\s*\(' \
  .

Length of output: 102546


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="b6293ebf4c0f5957b3a5ba2de0f03c512cff7069"
head="0b49a40b1b75df29106a334673d96c8cb7d8180f"

echo "== Supported structural outline: result streaming =="
ast-grep outline pg_llm_batch/result_streaming.py --items all --view signatures
echo
echo "== Modified request and shared bounded-read code =="
git diff --unified=100 "$base" "$head" -- pg_llm_batch/batch_api_client.py pg_llm_batch/exceptions.py
echo
echo "== Result streaming implementation, Lines 1-460 =="
nl -ba pg_llm_batch/result_streaming.py | sed -n '1,460p'
echo
echo "== Handoff regression tests =="
nl -ba tests/test_streaming_transport_handoff.py | sed -n '1,280p'
echo
echo "== Streaming ownership and adapter regression tests =="
nl -ba tests/test_bounded_jsonl_result_streaming_coverage.py | sed -n '120,280p'
echo
echo "== Physical-line regression tests =="
nl -ba tests/test_bounded_jsonl_physical_line_budget.py | sed -n '90,180p'
echo
echo "== Main streaming behavior tests =="
nl -ba tests/test_bounded_jsonl_result_streaming.py | sed -n '120,420p'

Length of output: 17452


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="b6293ebf4c0f5957b3a5ba2de0f03c512cff7069"
head="0b49a40b1b75df29106a334673d96c8cb7d8180f"

numbered() {
  awk '{printf "%6d  %s\n", NR, $0}' "$1"
}

echo "== Diff whitespace validation =="
git diff --check "$base" "$head"
echo
echo "== result_streaming.py =="
numbered pg_llm_batch/result_streaming.py
echo
echo "== batch_api_client.py Lines 330-455 (_request and bounded reader) =="
awk 'NR >= 330 && NR <= 455 {printf "%6d  %s\n", NR, $0}' pg_llm_batch/batch_api_client.py
echo
echo "== test_streaming_transport_handoff.py =="
numbered tests/test_streaming_transport_handoff.py
echo
echo "== test_bounded_jsonl_result_streaming_coverage.py Lines 120-280 =="
awk 'NR >= 120 && NR <= 280 {printf "%6d  %s\n", NR, $0}' tests/test_bounded_jsonl_result_streaming_coverage.py
echo
echo "== test_bounded_jsonl_physical_line_budget.py Lines 90-180 =="
awk 'NR >= 90 && NR <= 180 {printf "%6d  %s\n", NR, $0}' tests/test_bounded_jsonl_physical_line_budget.py
echo
echo "== test_bounded_jsonl_result_streaming.py Lines 120-420 =="
awk 'NR >= 120 && NR <= 420 {printf "%6d  %s\n", NR, $0}' tests/test_bounded_jsonl_result_streaming.py

Length of output: 58212


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Public record-mutability contract =="
rg -n -i -C 3 \
  'BatchResultRecord|immutable|mutabl|mapping|record.*dict|dict.*record' \
  README.md docs/result-streaming.md AGENTS.md ARCHITECTURE.md \
  pg_llm_batch/result_streaming.py \
  tests/test_bounded_jsonl_result_streaming.py \
  tests/test_bounded_jsonl_result_streaming_coverage.py \
  tests/test_streaming_transport_handoff.py || true
echo
echo "== Changed streaming code: exception chaining and catch paths =="
rg -n -C 4 \
  'raise |except |__cause__|__context__|from None|aclose|aclosing|asynccontextmanager' \
  pg_llm_batch/result_streaming.py pg_llm_batch/batch_api_client.py \
  tests/test_bounded_jsonl_result_streaming.py \
  tests/test_bounded_jsonl_result_streaming_coverage.py \
  tests/test_streaming_transport_handoff.py
echo
echo "== Remaining main streaming test file =="
awk 'NR >= 1 && NR <= 135 {printf "%6d  %s\n", NR, $0}' tests/test_bounded_jsonl_result_streaming.py
awk 'NR >= 393 && NR <= 500 {printf "%6d  %s\n", NR, $0}' tests/test_bounded_jsonl_result_streaming.py
echo
echo "== Full coverage test file, for unreviewed cases =="
awk '{printf "%6d  %s\n", NR, $0}' tests/test_bounded_jsonl_result_streaming_coverage.py
echo
echo "== New-file diff metadata and no generated artifacts =="
git diff --name-only b6293ebf4c0f5957b3a5ba2de0f03c512cff7069 0b49a40b1b75df29106a334673d96c8cb7d8180f \
  | grep -E '(^|/)(dist|build|\.cache|__pycache__|\.pytest_cache)/|\.pyc$' \
  && exit 1 || true

Length of output: 80083


@seonghobae I found one current-head actionable finding.

  • BatchResultRecord is only shallowly immutable. At pg_llm_batch/result_streaming.py, Line 36, record is a mutable Dict[str, Any]. The frozen=True dataclass prevents record.record = ..., but record.record["key"] = value still succeeds. Nested provider JSON objects and arrays also remain mutable. This conflicts with the stated immutable BatchResultRecord contract. Convert the payload to an immutable JSON representation, or change the public contract and type to state that the payload is mutable. Add a regression test for top-level and nested mutation.

I found no other actionable defects in the reviewed streaming limits, iterator ownership, zero-progress handling, body-free parser diagnostics, or response-handoff boundary.

This is a review-only result. The stacked draft remains not merge-ready until prerequisite integration, retargeting to main, and fresh required-gate evidence.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head verification for the transport handoff finding on 7fcd0ad4b4d2beedf0f753783e59fb57bf35d38d against stacked base b6293ebf4c0f5957b3a5ba2de0f03c512cff7069:

  • request acquisition and retryable HTTP-status decisions finish before response handoff;
  • direct payload failure, response-close failure, and a streaming body that yields one record then fails each perform one GET, zero retry sleeps, one response close, and no replay;
  • translated transport diagnostics retain neither provider-controlled text nor the original exception through __cause__ or __context__;
  • AGENTS, CLAUDE, ARCHITECTURE, ADR 0005, doctoring, README, operator documentation, and CHANGELOG now define the same pre-handoff retry and post-handoff at-most-once boundary;
  • exact-head CI run 31098730542 completed successfully on Python 3.10, 3.12, and 3.14 with 526 tests passed, 100% of 1,957 production statements and 522 branches covered, 100% public docstrings, clean lint/compile/lock/package/container gates;
  • exact-head Release Acceptance run 31098730612 completed successfully; CodeRabbit status is successful and unresolved inline review threads are zero.

The valid finding is addressed. This remains an author verification comment, not independent approval. The PR remains a stacked draft and its evidence cannot be reused after prerequisite integration or retargeting.

Copy link
Copy Markdown
Contributor Author

@opencode-agent @cwl-noema-review @coderabbitai review

Perform one fresh review-only comparison of exact current draft head 7fcd0ad4b4d2beedf0f753783e59fb57bf35d38d against exact stacked base b6293ebf4c0f5957b3a5ba2de0f03c512cff7069. Do not write the branch, retarget, or merge.

Exact-head CI 31098730542 and Release Acceptance 31098730612 are complete and successful. Python 3.10/3.12/3.14, 526 tests, 100% production statement/branch/docstring coverage, Ruff, lock freshness, package and container builds passed; CodeRabbit status is successful and unresolved review threads are zero.

Review the bounded streaming memory/CPU budgets, deterministic iterator ownership, zero-progress rejection, body-free diagnostics, and the response-handoff boundary: pre-handoff acquisition/status failures may retry, while post-handoff payload or close failures must perform one GET, zero sleeps, close exactly once, expose no provider exception through cause/context/public text, and never restart or duplicate an already-yielded record. Verify the new protocol-idempotency versus application-delivery-idempotency, durable checkpoint/reconciliation, and operator recovery documentation. Report only current-head actionable findings.

This is a stacked-stage review. Missing default-branch required workflows are not success, and no merge approval is valid until prerequisites are integrated, this PR is retargeted to main, and every current default-branch gate is rerun.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="b6293ebf4c0f5957b3a5ba2de0f03c512cff7069"
head="7fcd0ad4b4d2beedf0f753783e59fb57bf35d38d"

git cat-file -e "${base}^{commit}"
git cat-file -e "${head}^{commit}"
git merge-base --is-ancestor "$base" "$head"

echo "== Changed files =="
git diff --name-status "$base" "$head"

echo "== Whitespace errors =="
git diff --check "$base" "$head"

echo "== Python outlines =="
git diff --name-only --diff-filter=AM "$base" "$head" |
  grep -E '\.py$' |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo "== Streaming and transport implementation =="
for file in pg_llm_batch/result_streaming.py pg_llm_batch/batch_api_client.py pg_llm_batch/exceptions.py; do
  if [ -f "$file" ]; then
    echo "--- $file"
    nl -ba "$file" | sed -n '1,620p'
  fi
done

echo "== Focused regression tests =="
for file in \
  tests/test_streaming_transport_handoff.py \
  tests/test_bounded_jsonl_result_streaming.py \
  tests/test_bounded_jsonl_result_streaming_coverage.py \
  tests/test_bounded_jsonl_physical_line_budget.py; do
  if [ -f "$file" ]; then
    echo "--- $file"
    nl -ba "$file" | sed -n '1,700p'
  fi
done

echo "== Contract documentation references =="
rg -n -i -C 3 \
  'open_batch_records|StreamingBatchAPIClient|BatchResultRecord|idempot|checkpoint|reconcil|recovery|physical.line|zero.progress|handoff|retry|close' \
  README.md AGENTS.md CLAUDE.md ARCHITECTURE.md CHANGELOG.md docs pg_llm_batch \
  || true

Length of output: 11278


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="b6293ebf4c0f5957b3a5ba2de0f03c512cff7069"
head="7fcd0ad4b4d2beedf0f753783e59fb57bf35d38d"

numbered() {
  awk '{printf "%6d  %s\n", NR, $0}' "$1"
}

echo "== Exact implementation diffs =="
git diff --unified=80 "$base" "$head" -- \
  pg_llm_batch/result_streaming.py \
  pg_llm_batch/batch_api_client.py \
  pg_llm_batch/exceptions.py \
  pg_llm_batch/__init__.py

echo "== result_streaming.py =="
numbered pg_llm_batch/result_streaming.py

echo "== batch_api_client.py: request and bounded-stream methods =="
rg -n -C 8 \
  'asynccontextmanager|def _request|async def _request|yield response|ClientPayloadError|iter_chunked|iter_any|async for|await response\.close|response\.close|retry|sleep' \
  pg_llm_batch/batch_api_client.py

echo "== Handoff regression tests =="
numbered tests/test_streaming_transport_handoff.py

echo "== Streaming coverage tests =="
numbered tests/test_bounded_jsonl_result_streaming_coverage.py

echo "== Core streaming tests =="
numbered tests/test_bounded_jsonl_result_streaming.py

echo "== Physical line tests =="
numbered tests/test_bounded_jsonl_physical_line_budget.py

echo "== Documentation contract excerpts =="
rg -n -i -C 5 \
  'protocol.idempot|application.delivery|checkpoint|reconcil|operator recovery|handoff|one GET|zero retry|physical.line|max_jsonl_physical_lines|zero.progress|close exactly once' \
  README.md AGENTS.md CLAUDE.md ARCHITECTURE.md CHANGELOG.md \
  docs/result-streaming.md \
  docs/adr/0005-bounded-jsonl-result-streaming.md \
  docs/doctoring/bounded-jsonl-result-streaming.md \
  || true

Length of output: 160151


@seonghobae I found one current-head actionable finding.

  • BatchResultRecord is only shallowly immutable. In pg_llm_batch/result_streaming.py, Line 36, record is a mutable Dict[str, Any]. @dataclass(frozen=True) prevents attribute reassignment, but it does not prevent item.record["key"] = value. Nested JSON dictionaries and lists also remain mutable. This conflicts with the documented immutable BatchResultRecord and immutable record-envelope contract. Convert the decoded payload to an immutable recursive representation, or revise the public contract to state that the payload is mutable. Add regression tests for top-level and nested mutation.

I found no other current-head actionable defects in the reviewed bounds, iterator closure, zero-progress rejection, body-free diagnostics, response-handoff behavior, or checkpoint and recovery documentation.

This was a read-only review. I did not modify, retarget, or merge the branch. The stacked draft remains not merge-ready until prerequisite integration, retargeting to main, and fresh required-gate evidence.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae
seonghobae force-pushed the agent/release-artifact-dirfd-verification branch from b6293eb to 6a6fac2 Compare August 8, 2026 23:15

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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