Extract _RetryPolicy decision module (+ agent-skills config)#76
Merged
Conversation
Scaffold the per-repo config the engineering skills expect: - issue tracker = GitHub Issues (gh CLI), external PRs not a triage surface - triage labels = canonical defaults (wontfix already exists) - domain docs = single-context, CONTEXT.md at root + ADRs under planning/adr Internal docs live under planning/, not the user-facing docs/ site. Adds an ## Agent skills block to CLAUDE.md pointing at the three files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full-lane design.md + plan.md for extracting a stateless _RetryPolicy decision module from the duplicated AsyncRetry/Retry __call__ loops, mirroring the _CircuitBreakerState precedent. Design only — no source changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the ~110 lines of retry decision logic duplicated across AsyncRetry.__call__ and Retry.__call__ into a stateless _RetryPolicy, mirroring the _CircuitBreakerState precedent. Both wrappers shrink to a thin loop (deposit -> try/next -> decide -> sleep) differing only in await/blocking. Behaviour byte-identical; public __init__ unchanged; .budget preserved, six config attributes moved onto the policy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Direct decision-matrix tests for the new policy module — no client, no MockTransport: retryable->delay (bounds), non-retryable/non-eligible re-raise, streaming refusal, exhaustion note, Retry-After exact/exceeds, budget refusal with __cause__, and moved max_attempts validation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the shared stateless _RetryPolicy + thin-wrapper structure in architecture/resilience.md. Includes lint cleanups surfaced by just lint: drop a redundant PLR0912 noqa on decide, fix a docstring mood + magic value in the new seam tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Set status: shipped, pr: 76, and outcome on the change bundle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the leftover 'Label in mattpocock/skills' seed-template header; the column is the canonical role name, mapped to our tracker's label. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent pieces on one branch.
1.
_RetryPolicyextraction (main work)Deepening from the architecture review:
AsyncRetry.__call__andRetry.__call__hand-copied ~110 lines of retry decision logic, differing only inawait. This pulls that logic into a stateless private_RetryPolicyin the same module — mirroring the_CircuitBreakerStateprecedent — so the decision lives once and both wrappers shrink to a thin loop.decide(*, attempt, request, exc) -> floatreturns the sleep delay, or raises the terminal exception (note + event +__cause__already set), called inside the wrapper'sexceptso chaining is free.deposit → for attempt → try/next → decide → sleep; sole sync/async diff isawait.__init__signatures unchanged;.budgetidentity preserved; the six config attributes moved onto the policy (read nowhere external).tests/test_retry_policy.pydrivesdecidedirectly across the decision matrix.architecture/resilience.md. Design bundle:planning/changes/2026-06-23.01-retry-policy-extraction/.2. Agent-skills config (incidental)
Scaffolds
planning/agents/{issue-tracker,triage-labels,domain}.md+ an## Agent skillsblock inCLAUDE.md(GitHub Issues, canonical triage labels, single-context domain docs).Verification
just lintclean (ruff format/check + ty)just test→ 718 passed, 100% coveragegrep -rE 'httpx2\._' src/httpware/clean🤖 Generated with Claude Code