refactor(session/retry): single-pass classify(); policy() no longer double-calls transportMessage#8
refactor(session/retry): single-pass classify(); policy() no longer double-calls transportMessage#8tesdal wants to merge 2 commits intophase-ab-basefrom
Conversation
…ouble-calls transportMessage
policy() previously called retryable(error) (which internally called
transportMessage) and then called transportMessage(error) again on the
next line to decide whether to apply TRANSPORT_RETRY_CAP. Consolidates
to a single classify() returning { message, isTransport? }; retryable()
becomes a thin wrapper kept to avoid churning the existing retry.test.ts
suite.
Preserves legacy cap behavior for plain-text errors whose message matches
BOTH a rate-limit phrase AND a transport pattern: classify() still picks
the rate-limit message text but sets isTransport so policy() applies
TRANSPORT_RETRY_CAP as before.
Adds retry-classification.test.ts with 7 cases including the mixed
rate-limit + ETIMEDOUT regression test.
Addresses audit finding F5 (Opus diamond review, 2026-04-22).
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
There was a problem hiding this comment.
Pull request overview
Refactors session retry classification to avoid double-calling transportMessage() inside retry policy evaluation, addressing audit finding F5 while preserving legacy retry-cap semantics.
Changes:
- Introduces
SessionRetry.classify()to perform single-pass retry classification and transport detection. - Keeps
retryable()as a compatibility wrapper returning only the message string for existing callers/tests. - Adds a dedicated test suite for classification behavior, including mixed rate-limit + transport cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/opencode/src/session/retry.ts | Adds classify() and updates policy() to use it, eliminating redundant transport classification calls. |
| packages/opencode/test/session/retry-classification.test.ts | New tests covering classify() output, legacy retryable() behavior, and mixed rate-limit/transport regression case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| test("returns non-transport classification for APIError 500", () => { | ||
| const err = new MessageV2.APIError({ | ||
| message: "upstream exploded", | ||
| statusCode: 503, | ||
| isRetryable: false, | ||
| }).toObject() |
There was a problem hiding this comment.
Test name says "APIError 500" but the constructed error uses statusCode: 503. Rename the test description to match the actual status code (or make it generic like "APIError 5xx") to avoid confusion when debugging failures.
Copilot review feedback — test name said '500' but constructed error uses statusCode 503. Addresses audit finding F5 (Opus diamond review, 2026-04-22).
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Closing — review-only PR on fork. Diamond (codex-5.3 + Opus) returned REQUEST_CHANGES; all findings applied. Copilot round 1 flagged one test-name nit (APIError 500 → 5xx, fixed in 42e4dac). Copilot round 2 clean. Merging to local/integration-v2 via --no-ff. |
Summary
policy()previously calledretryable(error)(which internally calledtransportMessage) and then calledtransportMessage(error)again on the next line to decide whether to applyTRANSPORT_RETRY_CAP.classify()returning{ message, isTransport? }.retryable()is kept as a thin wrapper (one-liner) to avoid churning the existingretry.test.tssuite; preferclassify()in new code.classify()still picks the rate-limit message text but setsisTransport: truesopolicy()appliesTRANSPORT_RETRY_CAPas before.Test plan
New file:
packages/opencode/test/session/retry-classification.test.ts— 7 tests:{message, isTransport: true}retryable()legacy wrapper still returns string for transport errorsETIMEDOUT→isTransport: truerate limit (ETIMEDOUT during retry)→ rate-limit message andisTransport: true(regression){message: "Provider is overloaded"}withoutisTransportResults from
packages/opencode/:bun test test/session/retry-classification.test.ts: 7 pass, 0 failbun test test/session/retry: 44 pass, 0 failbun typecheck: cleanReview history
Diamond review (2026-04-24) before push:
retryable()comment (TUI only uses the constant, not the function), redundantisTransport: falseliterals, missing plain-text transport test. All addressed.Both reviewers re-evaluated via rework-in-place pass. This PR is review-only on the fork for Copilot feedback; merges to integration via
--no-fflocally.Base
Branches off
phase-ab-basewhich trackslocal/integration-v2at commit257bdb28b(F4 merged).