Skip to content

fix(http): retry 425 Too Early on bounded GETs - #71

Merged
seonghobae merged 71 commits into
mainfrom
agent/retry-http-425-too-early
Aug 11, 2026
Merged

fix(http): retry 425 Too Early on bounded GETs#71
seonghobae merged 71 commits into
mainfrom
agent/retry-http-425-too-early

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Purpose

Harden the OpenAI-compatible Files/Batches HTTP control plane without widening replay: bounded idempotent GET retries, fail-closed TLS trust handling, provider-error confidentiality, exact gateway authority, bounded wait controls, and fail-closed batch-status progress validation.

Bounded implementation

  • Default retryable GET status set is exactly {408, 425, 429, 502, 503, 504}; HTTP 500 and every provider POST remain single-attempt.
  • ClientSSLError/certificate-verification and ServerFingerprintMismatch failures are permanent for the current acquisition attempt and are never retried automatically.
  • Retry eligibility ends at response handoff; body/close failures cannot replay a request after a response is acquired.
  • Transport diagnostics/logs use a closed finite category vocabulary rather than arbitrary dependency exception class names/messages.
  • Non-success provider responses are classified from HTTP status before body parsing; provider JSON/free text/debug fields are not copied into exported package diagnostics.
  • Malformed successful UTF-8/JSON produces fixed bounded diagnostics without retaining provider bytes/text or decoder/parser exceptions through exported cause/context links.
  • Gateway base URLs must already be exact strings and pass destination validation before secret lookup; unsafe whitespace/control/backslash/userinfo/query/fragment/port/non-loopback-HTTP inputs fail before credential acquisition.
  • Alias lookup falls back to gateway.base_url only when the alias-specific value is actually absent (None). An explicit false-y value is still authoritative input and must be validated/rejected rather than silently inheriting another destination authority.
  • wait_for_batch() accepts only finite positive numeric poll/timeout controls before credential/provider I/O.
  • Batch-status responses require a non-empty status string. request_counts, when present, must be an object whose total, completed, and failed are exact non-negative integers, with completed + failed <= total. Malformed evidence raises body-free InvalidBatchStatusPayload rather than raw runtime failures or unsafe normalization.
  • Provider-specific extensions remain outside the reviewed compatibility contract unless separately tested.

Issue #98 integration

The current source contains the bounded data-integrity behavior tracked by Issue #98 for malformed request_counts, boolean/string/negative/non-finite counters, inconsistent progress, and malformed status shape. This remains ACTIVE-PR evidence until #71 reaches protected main; Issue #98 is not a protected-main closure merely because the code is present here.

Test-first evidence

The branch history retains RED→GREEN cycles for HTTP 425/TLS classification, response handoff, transport vocabulary, provider-error confidentiality, malformed-success exception privacy, exact gateway authority, wait-resource validation, and batch-status shape/progress validation.

The latest exact-authority cycle found a concrete fallback defect in the package-provided credential resolver:

  1. RED source e8ef75ba2af5a3f49b3790c48b5b6117b7b9211a added alias-aware regressions. CI 31516117889 failed exactly six false-y non-string alias cases (False, 0, 0.0, b"", [], {}) because the old truthiness test silently fell back to gateway.base_url instead of rejecting the explicit alias value. The observed coverage run still reported 100% owned production statement/branch coverage; the six regression failures are the intended product-boundary RED evidence.
  2. Current source 2e1ffd31148fcc8bc5a20b7e7096a5c646b3a459 changes fallback selection from truthiness to explicit absence (is None), preserving legacy fallback only for a missing alias while routing explicit values through the existing exact URL validator before secret lookup. Current CI 31516889156, Security Scan 31516889318, and SAST Semgrep 31516889246 are all completed / success.

docs/adr/0015-http-425-too-early-retry.md and docs/doctoring/http-425-too-early-retries.md retain primary protocol/Python/aiohttp references and rollback boundaries. Predecessor checks remain development provenance only.

Current exact staged state

  • Source head: 2e1ffd31148fcc8bc5a20b7e7096a5c646b3a459.
  • Independently resolved protected main: bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10.
  • GitHub reports Draft and mergeable.
  • Current CI 31516889156: completed / success.
  • Current Security Scan 31516889318: completed / success.
  • Current SAST Semgrep 31516889246: completed / success.
  • Formal reviews: none; unresolved inline review threads: zero at the fresh pre-write refetch.

These successful PR-triggered runs remain staged integration evidence because protected-main CI still predates #88 exact-source checkout governance. They must not be promoted to final exact contributor-source-head acceptance merely because the generated-merge workflow is green.

Follow-up boundaries

Issue #128 remains separate: GatewayCredentials still uses a generated dataclass representation that can expose api_key. Do not add that representation fix on a competing branch while #71 owns this provider-client surface; implement it test-first from the protected #71 result or a proven successor. Later session-ownership/concurrency follow-ups (#110/#111) must likewise compose from the protected result rather than race this branch.

Issue #136 is also separate. Protected main and this branch still have no provider-file lifecycle authority for upload expiry, generated output/error expiry, or explicit Files API deletion. After #71 reaches protected main or is superseded, #136 must compose remote input/output/error retention and deletion through the then-protected validated gateway/credential/resource-ID boundary. Cancellation is not deletion, historical provider file identities remain reconciliation evidence after remote content expires/deletes, and no #71 checks/reviews transfer automatically to that future lifecycle slice.

Current prerequisite / merge boundary

Repository exact-source governance #88 is the immediate prerequisite. Current organization rules require the central workflow set and review-thread resolution, with required_approving_review_count: 0, code-owner review disabled, and no last-push approval requirement. This PR currently has no formal reviews and no unresolved threads, so absence of an independent approval is not a live blocker unless policy changes.

ContextualWisdomLab/.github#790 remains read-only and cannot be copied, weakened, retriggered, dismissed, resolved, or merged by this writer. Its historical review state is not promoted into an extra leaf approval prerequisite beyond current live policy.

Keep Draft until #88 reaches protected main. Then refetch this exact head/base and active-writer state, promote to Ready only if unchanged and non-conflicting, and reacquire every live exact-source central/repository CI, security, coverage, package, provenance, review, and ruleset gate. Merge only with zero valid unresolved findings and every requirement actually imposed by the then-current ruleset satisfied.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2021e122-20b6-42e2-b918-396921aa9f66

📥 Commits

Reviewing files that changed from the base of the PR and between 545334a and 5ee8eb2.

📒 Files selected for processing (22)
  • AGENTS.md
  • CHANGELOG.md
  • README.md
  • docs/adr/0015-http-425-too-early-retry.md
  • docs/doctoring/http-425-too-early-retries.md
  • pg_llm_batch/batch_api_client.py
  • tests/test_batch_api_client.py
  • tests/test_batch_status_shape_documentation.py
  • tests/test_batch_status_shape_validation.py
  • tests/test_gateway_url_exact_input.py
  • tests/test_gateway_url_validation.py
  • tests/test_http_425_retry_contract.py
  • tests/test_http_transport.py
  • tests/test_idempotent_get_retries.py
  • tests/test_provider_compatibility_claims.py
  • tests/test_provider_error_confidentiality.py
  • tests/test_remote_batch_lifecycle.py
  • tests/test_response_handoff_retry_boundary.py
  • tests/test_retry_edge_coverage.py
  • tests/test_transport_retry_classification.py
  • tests/test_wait_resource_bounds.py
  • tests/test_wait_resource_bounds_documentation.py

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.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@opencode-agent @cwl-noema-review

Review-only request for exact source head ecb5a82c3170b4b95970a291dafd1adbd90829e2 against exact current protected main tip bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10. Independently verify the closed GET-only retry set {408, 425, 429, 502, 503, 504}, HTTP 425 response-release and bounded retry semantics, HTTP 500 and every POST remaining single-attempt, Retry-After/equal-jitter compatibility, RFC 8470/9110/6585 claims, public-docstring and 100% production statement/branch coverage evidence, and absence of credential, schema, release, or generated-artifact changes. Treat current CI as synthetic-merge-stage evidence only until the repository’s exact-source-head CI governance prerequisite is integrated. Do not mutate the branch, create a repair workflow, mark ready, merge, release, weaken checks, or bypass repository protection.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

source_commit='ecb5a82c3170b4b95970a291dafd1adbd90829e2'
base_commit='bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10'
repo='ContextualWisdomLab/pg-llm-batch'

echo '== Repository state and requested commits =='
git rev-parse HEAD
git rev-parse "$source_commit"
git rev-parse "$base_commit"
git merge-base --is-ancestor "$base_commit" "$source_commit" && echo 'BASE_IS_ANCESTOR=yes' || echo 'BASE_IS_ANCESTOR=no'
git show -s --format='source=%H%nparents=%P%nsubject=%s' "$source_commit"
git show -s --format='base=%H%nparents=%P%nsubject=%s' "$base_commit"

echo '== Changed files and change statistics =='
git diff --stat "$base_commit" "$source_commit"
git diff --name-status "$base_commit" "$source_commit"
git diff --numstat "$base_commit" "$source_commit"

echo '== Full PR-range diff =='
git diff --find-renames --find-copies --no-ext-diff "$base_commit" "$source_commit"

echo '== Candidate source, test, and documentation files =='
fd -HI -t f . | sort | sed -n '1,500p'

echo '== Retry-related definitions and call sites =='
rg -n -i -C 5 \
  '(retry[-_ ]?after|equal[-_ ]?jitter|retryable|retry.*status|status.*retry|Too Early|HTTP.?425|HTTP.?500|early data|ClientResponse|response\.release|\.release\(\)|request\(|\.get\(|\.post\()' \
  -g '!**/.git/**' . || true

echo '== Public functions/classes in changed Python files =='
changed_py="$(git diff --name-only --diff-filter=ACMR "$base_commit" "$source_commit" -- '*.py')"
if [ -n "$changed_py" ]; then
  printf '%s\n' "$changed_py" | while IFS= read -r file; do
    echo "-- $file --"
    ast-grep outline "$file" --items all --type class,function --view expanded || true
  done
fi

echo '== Documentation references in changed Markdown/reStructuredText files =='
changed_docs="$(git diff --name-only --diff-filter=ACMR "$base_commit" "$source_commit" -- '*.md' '*.rst' '*.txt')"
if [ -n "$changed_docs" ]; then
  printf '%s\n' "$changed_docs" | while IFS= read -r file; do
    echo "-- $file --"
    rg -n -i -C 3 '(RFC ?8470|RFC ?9110|RFC ?6585|425|500|Retry-After|early data)' "$file" || true
  done
fi

echo '== GitHub PR metadata and checks by requested source commit =='
gh pr view 71 --repo "$repo" --json number,state,isDraft,headRefName,headRefOid,baseRefName,baseRefOid,mergeCommit,reviewDecision,statusCheckRollup,reviews
gh api "repos/$repo/commits/$source_commit/check-runs?per_page=100" \
  --jq '.check_runs[] | {name, status, conclusion, head_sha, details_url, started_at, completed_at}'
gh api "repos/$repo/commits/$source_commit/status" \
  --jq '{sha, state, statuses: [.statuses[] | {context, state, target_url, created_at, updated_at}]}'

Length of output: 210011


🏁 Script executed:

#!/bin/bash
set -euo pipefail

source_commit='ecb5a82c3170b4b95970a291dafd1adbd90829e2'
base_commit='bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10'
repo='ContextualWisdomLab/pg-llm-batch'

echo '== Retry control flow =='
sed -n '45,95p;300,412p' pg_llm_batch/batch_api_client.py

echo '== Existing GET retry and POST non-retry tests =='
rg -n -C 4 \
  '(async def test_.*(post|POST|retryable_get|stops_after)|"post"|POST|Retry-After|exit_count|sleep)' \
  tests/test_idempotent_get_retries.py tests/test_retry_edge_coverage.py tests/test_http_transport.py

echo '== Public retry documentation locations =='
rg -n -i -C 3 \
  '(idempotent provider `GET`|retryable statuses|transient `408`|HTTP 425|Too Early|RETRYABLE_GET_STATUSES)' \
  README.md CHANGELOG.md docs AGENTS.md

echo '== CI workflow trigger and coverage/docstring commands =='
sed -n '1,280p' .github/workflows/ci.yml
echo '== All workflow references to PR merge refs, head SHA, and checkout refs =='
rg -n -C 3 \
  '(pull_request|merge_group|github\.sha|github\.event\.pull_request\.head\.sha|actions/checkout|ref:)' \
  .github/workflows

echo '== Exact changed-file safety classification =='
git diff --name-only "$base_commit" "$source_commit" | \
  awk '
    /^(\.github\/|docker\/|pg_llm_batch\/schema\.sql$|.*\.(sql|lock|pem|key|crt|p12|pfx)$)/ {print "SENSITIVE_OR_GENERATED_CANDIDATE " $0; next}
    {print "REVIEWED_CHANGE " $0}
  '

echo '== GitHub Actions run event, SHA, and PR association =='
for run in 31248352447 31248352452 31248352460 31248351228; do
  gh api "repos/$repo/actions/runs/$run" \
    --jq '{id,event,status,conclusion,head_sha,head_branch,workflow_id,pull_requests}'
done

echo '== Branch protection and repository ruleset summary =='
gh api "repos/$repo/branches/main/protection" --jq '{required_status_checks,required_pull_request_reviews,enforce_admins,required_linear_history,restrictions}' 2>/dev/null || true
gh api "repos/$repo/rulesets" --jq '.[] | {id,name,target,enforcement,rules}' 2>/dev/null || true

Length of output: 54357


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/pg-llm-batch'
run_id='31248352447'

echo '== Coverage and test configuration =='
rg -n -C 5 \
  '(tool\.coverage|coverage|branch|pytest|interrogate|fail-under|addopts)' \
  pyproject.toml .coveragerc setup.cfg tox.ini 2>/dev/null || true

echo '== CI job identifiers =='
gh api "repos/$repo/actions/runs/$run_id/jobs?per_page=100" \
  --jq '.jobs[] | {id,name,conclusion,started_at,completed_at}'

echo '== Quality-gate log: checkout revision and coverage report only =='
quality_job_id="$(
  gh api "repos/$repo/actions/runs/$run_id/jobs?per_page=100" \
    --jq '.jobs[] | select(.name == "Coverage, docstrings, lint, and package") | .id'
)"
gh api "repos/$repo/actions/jobs/$quality_job_id/logs" > /tmp/quality-gate.log
rg -n -i -C 3 \
  '(checking out|checked out|git checkout|git rev-parse|HEAD is now at|coverage|branch|TOTAL|interrogate|100%)' \
  /tmp/quality-gate.log || true

echo '== Source-head versus pull-request merge references =='
gh api "repos/$repo/git/ref/pulls/71/merge" --jq '.object.sha' 2>/dev/null || true
gh api "repos/$repo/git/ref/pulls/71/head" --jq '.object.sha'

Length of output: 4608


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/pg-llm-batch'
quality_job_id='93080564666'

echo '== Quality-gate checkout and coverage evidence =='
gh api --allow-escape-sequences "repos/$repo/actions/jobs/$quality_job_id/logs" \
  | sed -r 's/\x1B\[[0-9;]*[[:alpha:]]//g' > /tmp/quality-gate.log

rg -n -i -C 4 \
  '(checking out|checked out|git checkout|git rev-parse|HEAD is now at|coverage|branch|TOTAL|interrogate|100%|passed)' \
  /tmp/quality-gate.log || true

echo '== Pull request references =='
printf 'merge_ref='
gh api "repos/$repo/git/ref/pulls/71/merge" --jq '.object.sha' 2>/dev/null || echo 'not_available'
printf 'head_ref='
gh api "repos/$repo/git/ref/pulls/71/head" --jq '.object.sha'

Length of output: 13767


@seonghobae Review complete for source ecb5a82c3170b4b95970a291dafd1adbd90829e2 against base bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10.

Finding

  • P2 — Update the public retry-status list in README.md.
    README.md Lines 183-184 still states that default GET retries apply to 408, 429, 502, 503, and 504. The source now uses the exact set {408, 425, 429, 502, 503, 504}. This creates a user-visible contract mismatch. Add HTTP 425 Too Early to this list.

Verified

  • The requested base commit is an ancestor of the requested source commit.
  • RETRYABLE_GET_STATUSES is exactly {408, 425, 429, 502, 503, 504}.
  • BatchAPIClient._request() retries only normalized GET requests.
  • The failed response context exits before asyncio.sleep() and the next request.
  • Retry-After precedence and equal-jitter fallback remain unchanged.
  • HTTP 500 remains outside the retry set and is single-attempt.
  • POST response failures and POST transport failures remain single-attempt.
  • The added test covers HTTP 425 response release, one fallback delay, and one GET retry.
  • The range has no credential, schema, release, workflow, lockfile, or generated-artifact changes.
  • The ADR and doctoring record contain APA-style references to RFC 8470, RFC 9110, and RFC 6585.

CI evidence

The quality gate reports 100% production statement and branch coverage, and 100% public docstrings. However, the job checked out refs/remotes/pull/71/merge at synthetic merge commit 8623c5f35b57779f77fbb454bf95729a52320c27.

Therefore, under the stated governance requirement, this is synthetic-merge-stage evidence only. It does not verify the exact source head. I do not approve or mark this Draft PR ready.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@opencode-agent @cwl-noema-review

Fresh review-only request for exact head 52254aa95f245fceebc2a12a9a69aa94c0273b35 against unchanged protected main tip bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10. CodeRabbit’s predecessor-head P2 finding was reproduced test-first: RED head 2b1f143809aca5fee1c293667e6338dc744a7548, CI 31248896618, failed only the new README retry-contract assertion on Python 3.10/3.12/3.14 and coverage while container evidence remained green. The current head adds HTTP 425 to the public README and CI 31248982685, Security Scan 31248982690, and SAST 31248982733 are completed/success. Re-review the exact range for remaining correctness, replay, Retry-After, documentation, and evidence issues. Current CI still checks out the synthetic PR merge ref, so treat it as staged evidence rather than exact-source final evidence until PR #69’s separate governance prerequisite integrates. Do not mutate the branch, create repair workflows, mark ready, merge, release, weaken gates, or bypass protection.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/pg-llm-batch'
base='bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10'
head='52254aa95f245fceebc2a12a9a69aa94c0273b35'

echo '== Exact commits and range =='
git rev-parse "$base" "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base_is_ancestor=yes'
git show -s --format='head=%H%nparents=%P%nsubject=%s' "$head"
git diff --name-status "$base" "$head"
git diff --stat "$base" "$head"
echo '== Diff =='
git diff --find-renames --no-ext-diff "$base" "$head"

echo '== Retry implementation outline and relevant source =='
ast-grep outline pg_llm_batch/batch_api_client.py --items all --type class,function --view expanded
rg -n -C 8 \
  '(RETRYABLE_GET_STATUSES|async def _request|response\.release|Retry-After|equal.*jitter|asyncio\.sleep|method.*GET|method.*POST)' \
  pg_llm_batch/batch_api_client.py

echo '== Retry and README contract test definitions =='
rg -n -C 8 \
  '(425|Too Early|RETRYABLE_GET_STATUSES|README|retry.*status|response.*release|Retry-After|equal.*jitter|500|POST)' \
  tests README.md CHANGELOG.md docs AGENTS.md 2>/dev/null || true

echo '== PR, runs, check-runs, statuses, and checkout refs =='
gh pr view 71 --repo "$repo" \
  --json number,state,isDraft,headRefOid,baseRefOid,reviewDecision,reviews,statusCheckRollup
for run in 31248982685 31248982690 31248982733; do
  gh api "repos/$repo/actions/runs/$run" \
    --jq '{id,event,status,conclusion,head_sha,head_branch,workflow_id,pull_requests}'
done
gh api "repos/$repo/commits/$head/check-runs?per_page=100" \
  --jq '.check_runs[] | {name,status,conclusion,head_sha,details_url}'
gh api "repos/$repo/commits/$head/status" \
  --jq '{sha,state,statuses:[.statuses[] | {context,state,target_url}]}'
printf 'pr_head_ref='
gh api "repos/$repo/git/ref/pulls/71/head" --jq '.object.sha'
printf 'pr_merge_ref='
gh api "repos/$repo/git/ref/pulls/71/merge" --jq '.object.sha' 2>/dev/null || true

Length of output: 181761


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/pg-llm-batch'
run='31248982685'
job='93082174686'
head='52254aa95f245fceebc2a12a9a69aa94c0273b35'

echo '== CI checkout configuration =='
sed -n '1,280p' .github/workflows/ci.yml
echo '== CI quality-gate checkout and result excerpts =='
gh api --allow-escape-sequences "repos/$repo/actions/jobs/$job/logs" \
  | sed -r 's/\x1B\[[0-9;]*[[:alpha:]]//g' > /tmp/quality-gate.log
rg -n -i -C 3 \
  '(checking out|checked out|git checkout|git rev-parse|HEAD is now at|refs/remotes/pull|coverage|TOTAL|branch|interrogate|100%|passed|deselected|built)' \
  /tmp/quality-gate.log || true

echo '== Current Strix workflow and check state =='
gh api "repos/$repo/actions/runs/31248981773" \
  --jq '{id,event,status,conclusion,head_sha,updated_at,pull_requests}'
gh api "repos/$repo/commits/$head/check-runs?per_page=100" \
  --jq '[.check_runs[] | select(.name == "strix") | {status,conclusion,started_at,completed_at,details_url}]'

echo '== Review and unresolved review-thread state =='
gh pr view 71 --repo "$repo" --json reviews,reviewDecision
gh api graphql -F owner='ContextualWisdomLab' -F name='pg-llm-batch' -F number=71 -f query='
query($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    pullRequest(number: $number) {
      reviewThreads(first: 100) {
        nodes { isResolved comments(first: 1) { nodes { author { login } body } } }
      }
    }
  }
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {author: .comments.nodes[0].author.login, body: .comments.nodes[0].body}]'

Length of output: 19168


@seonghobae Review complete for source 52254aa95f245fceebc2a12a9a69aa94c0273b35 against base bf2cc2e140dc3ff4a56c3203f80f41bb9fed5d10.

No new code or documentation finding was identified.

The predecessor P2 finding is fixed. README.md now documents the exact default GET retry set: {408, 425, 429, 502, 503, 504}. The new contract test prevents this documentation mismatch from returning.

I verified the following:

  • RETRYABLE_GET_STATUSES is exactly {408, 425, 429, 502, 503, 504}.
  • Retries remain restricted to normalized GET requests.
  • A retryable response context exits before the delay and next request.
  • The HTTP 425 test verifies one response release, one bounded fallback delay, and one GET retry.
  • HTTP 500 remains outside the retry set and is single-attempt.
  • POST response failures and POST transport failures remain single-attempt.
  • Retry-After precedence and equal-jitter fallback are unchanged.
  • The range contains no workflow, schema, credential, lockfile, release, or generated-artifact changes.
  • The ADR and doctoring record document the retry boundary and cite RFC 8470, RFC 9110, and RFC 6585.
  • The quality gate reports 100% public docstrings, 100% production statement and branch coverage, and 353 passed, 3 deselected.
  • Security Scan and SAST completed successfully for the requested source-head-associated PR event.
  • There are zero unresolved inline review threads.

I also verified that CI checked out synthetic merge commit 4868fcd2500dda455d7ef612a74091b360af37c5 from refs/remotes/pull/71/merge. Therefore, its successful results are staged integration evidence only. They do not provide final exact-source-head verification.

The strix check is still in progress. This pending check is not successful evidence. I do not approve or change the Draft state.

⚠️ 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 marked this pull request as ready for review August 11, 2026 21:11
@seonghobae
seonghobae merged commit 8963916 into main Aug 11, 2026
33 checks passed
@seonghobae
seonghobae deleted the agent/retry-http-425-too-early branch August 11, 2026 21:13
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