Build the retry subsystem in full: one shared policy core (status-and-throwable classification, the
re-sendability gate, the backoff calculator, the pacing-header parser, tuning constants) and the two stacks
— the recovery-chain retry that installs beneath phase 4b's Recovery::Orchestrator with a total-timeout
budget, and the stage-based pillar step at Dexpace::Pipeline::Stages::RETRY with a sync and an async driver.
The largest sub-phase in the roadmap, sixty IDs.
Scope
Dexpace::Resilience::Policy (visibility and Resend.eligible?, R5): classification via RETRY-2's
capability-only throwable query and its blind spot (R4), RETRY-13's single backoff calculator serving two
budget policies (R6), Retry-After pacing through phase 5a's Dexpace::HTTPDate.parse against RETRY-15's
tolerances (R1), idempotency-key preservation.
- The recovery-stack engine —
RECOV-17–RECOV-30 and RECOV-34, each with its own checklist row (a
cross-reference to the RETRY twin is an annotation, never the row's disposition) — installing into what
4b shipped, with CFG-15's cancellable wait as its delay primitive.
- The pillar step at
Stages::RETRY with a sync driver and an async trampoline that needs no Fiber.scheduler
(R2); the retry step's HTTPTracer source (R3); per-attempt OBS-29 events — attempt started, attempt
failed with next delay, retries exhausted (R15 decides no PRE_REDIRECT; phase 10 confirmed it).
- Picks up and closes:
ProtocolError#retryable_by_status?, CFG-35's throwable half, and the Cursor
context-bundle widening (Task 8) that 6b and 6c consume if it exists and never wait on.
Spec refs
Product spec §9 — RETRY-1–RETRY-45 (45); appendix C — RECOV-17–RECOV-30, RECOV-34 (15, the largest
gap cluster in the corpus; budget the spec reading). sdk-design: §6.1, §8.3.
Dependencies
Phases 0–5 — and phase 5 is a real prerequisite: RETRY-12's defaults come from CFG-14, the delay from
CFG-15–CFG-21, the events from 5b/5c's instrumentation. Independent of 6b and 6c — 4c's
stage-namespaced cursor state makes a RETRY fork's state: invisible under any other stage's key, which is
the same assertion that keeps 6b/6c's marker exchange safe from 6a.
Docs
- Segmentation:
docs/work/mvp/phase6/2026-09-09-phase6-segmentation-design.md
- Design:
docs/work/mvp/phase6/phase6a/2026-09-09-phase6a-retry-design.md
- Plan:
docs/work/mvp/phase6/phase6a/2026-09-09-phase6a-retry.md (13 tasks)
- Checklist:
docs/work/mvp/phase6/phase6a/<date>-phase6a-retry-checklist.md — written at execution time, one
row per ID in scope, sixty rows
Notes
Recommended first of the three for four reasons the charter gives: longest pole, closes or half-closes four
postponed items, owns the cursor widening, and touches neither side of the redirect-then-auth marker. RETRY-28
is a phase-10 row by design §10's closing note. RETRY-38 (MAY) is declined for v1 with RECOV-31.
Build the retry subsystem in full: one shared policy core (status-and-throwable classification, the
re-sendability gate, the backoff calculator, the pacing-header parser, tuning constants) and the two stacks
— the recovery-chain retry that installs beneath phase 4b's
Recovery::Orchestratorwith a total-timeoutbudget, and the stage-based pillar step at
Dexpace::Pipeline::Stages::RETRYwith a sync and an async driver.The largest sub-phase in the roadmap, sixty IDs.
Scope
Dexpace::Resilience::Policy(visibility andResend.eligible?, R5): classification viaRETRY-2'scapability-only throwable query and its blind spot (R4),
RETRY-13's single backoff calculator serving twobudget policies (R6),
Retry-Afterpacing through phase 5a'sDexpace::HTTPDate.parseagainstRETRY-15'stolerances (R1), idempotency-key preservation.
RECOV-17–RECOV-30andRECOV-34, each with its own checklist row (across-reference to the
RETRYtwin is an annotation, never the row's disposition) — installing into what4b shipped, with
CFG-15's cancellable wait as its delay primitive.Stages::RETRYwith a sync driver and an async trampoline that needs noFiber.scheduler(R2); the retry step's
HTTPTracersource (R3); per-attemptOBS-29events — attempt started, attemptfailed with next delay, retries exhausted (R15 decides no
PRE_REDIRECT; phase 10 confirmed it).ProtocolError#retryable_by_status?,CFG-35's throwable half, and theCursorcontext-bundle widening (Task 8) that 6b and 6c consume if it exists and never wait on.
Spec refs
Product spec §9 —
RETRY-1–RETRY-45(45); appendix C —RECOV-17–RECOV-30,RECOV-34(15, the largestgap cluster in the corpus; budget the spec reading). sdk-design: §6.1, §8.3.
Dependencies
Phases 0–5 — and phase 5 is a real prerequisite:
RETRY-12's defaults come fromCFG-14, the delay fromCFG-15–CFG-21, the events from 5b/5c's instrumentation. Independent of6band6c— 4c'sstage-namespaced cursor state makes a RETRY fork's
state:invisible under any other stage's key, which isthe same assertion that keeps 6b/6c's marker exchange safe from 6a.
Docs
docs/work/mvp/phase6/2026-09-09-phase6-segmentation-design.mddocs/work/mvp/phase6/phase6a/2026-09-09-phase6a-retry-design.mddocs/work/mvp/phase6/phase6a/2026-09-09-phase6a-retry.md(13 tasks)docs/work/mvp/phase6/phase6a/<date>-phase6a-retry-checklist.md— written at execution time, onerow per ID in scope, sixty rows
Notes
Recommended first of the three for four reasons the charter gives: longest pole, closes or half-closes four
postponed items, owns the cursor widening, and touches neither side of the redirect-then-auth marker.
RETRY-28is a phase-10 row by design §10's closing note.
RETRY-38(MAY) is declined for v1 withRECOV-31.