Repository navigation
[Phase 2] Assess simplifying the sonnet->opus in-engine fallback given rate-limit equalization #1099
Copy link
Copy link
Closed
Labels
dev-leadFor dev-lead agent pickupFor dev-lead agent pickupinitiativeEpic / initiative tracking issueEpic / initiative tracking issue
Description
Story
As a engine maintainer,
I want assess whether Sonnet 5's rate-limit equalization (Sonnet/Haiku now match Opus limits at every tier) removes the need for the in-engine sonnet->opus RPM/TPM fallback hop, and adjust the chains only if the evidence supports it,
so that the fallback chain stays exactly as long as it needs to be — a now-redundant hop can be dropped to reduce cost/latency, while the daily-subscription-cap safety net is explicitly kept.
Acceptance Criteria
- A written analysis states whether rate-limit equalization makes the in-engine sonnet->opus hop redundant for RPM/TPM scenarios, citing engine.sh's two-layer fallback doc (lines 12-24) and the shared daily-cap caveat (feat(dev-lead): proactive provider headroom check before engine invocation #206).
- The daily-subscription-cap fallback is explicitly preserved regardless of the RPM/TPM conclusion — the analysis calls out that the shared cap is NOT addressed by per-model RPM/TPM buckets.
- If the analysis concludes the hop is redundant, the chain edit is minimal and covered by an updated
tests/dev-lead/unit/test_engine_chain.bats; if not, the chains are left unchanged and the rationale is recorded in the PR. - No change weakens the cross-provider (claude->copilot->gemini) fallback path or the exit-code-2 rate-limit contract.
shellcheckis clean and the dev-lead unit bats pass whether or not a chain edit is made.
Tasks / Subtasks
- Document the RPM/TPM vs daily-cap fallback distinction from engine.sh lines 12-24 and feat(dev-lead): proactive provider headroom check before engine invocation #206, and state whether equalization removes the RPM/TPM rationale for the sonnet->opus hop. (AC: test issue from agent #1, Go-live improvements for PR review agent #2)
- If redundant: make the minimal chain edit and update test_engine_chain.bats; if not: record the rationale and leave chains unchanged. (AC: Add @claude delegation, auto-merge, and rebase handling #3)
- Confirm the cross-provider fallback and exit-code-2 contract are untouched; run shellcheck + bats. (AC: Optimize review: small-PR and incremental fast paths #4, feat: add Copilot engine support via REVIEW_ENGINE toggle #5)
Dev Notes
- engine.sh header (lines 12-24) documents the two fallback layers precisely; the in-Claude chain helps ONLY with per-model RPM/TPM buckets, never with the shared daily subscription cap (feat(dev-lead): proactive provider headroom check before engine invocation #206). Equalization is about rate LIMITS (RPM/TPM), so it can only affect layer-1 reasoning, not the daily-cap fallback.
- This story is deliberately conditional: the correct outcome may be 'no code change, rationale recorded'. That is a valid, reviewable result — do not force a chain edit to look productive.
- The cross-provider fallback (run_writer_with_fallback / review-batch.sh) keys off the engine layer returning exit code 2 when every in-engine model is rate-limited. Any chain trimming must keep that contract; see the is_rate_limited / exit-2 comments in engine.sh.
- Depends on Story 3 having placed Sonnet 5 in the chain, so the assessment is over the actual post-wiring chain, not the current one.
Project Structure Notes
Analysis-first story scoped to the same engine.sh chains as Story 3; any edit is minimal and covered by the existing dev-lead unit bats. May legitimately produce no code change.
References
- scripts/engine.sh#two-layer-fallback-doc
- scripts/engine.sh#is_rate_limited-exit-2
- tests/dev-lead/unit/test_engine_chain.bats
Likely target surface
scripts/engine.shtests/dev-lead/unit/test_engine_chain.bats
Story prepared by the BMAD Scrum Master (Bob) for epic #1095. Status: ready-for-dev.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
dev-leadFor dev-lead agent pickupFor dev-lead agent pickupinitiativeEpic / initiative tracking issueEpic / initiative tracking issue
Activity
don-petry commentedon Jul 8, 2026
Dev-Lead Implementation Plan
Issue: #1099 — [Phase 2] Assess simplifying the sonnet->opus in-engine fallback given rate-limit equalization
Scope
Analysis-first story. Assess whether Sonnet 5's rate-limit equalization (Sonnet/Haiku now match Opus limits at every tier) makes the in-engine sonnet->opus RPM/TPM fallback hop redundant. Preliminary conclusion: not redundant — equalization changes per-model bucket size, not bucket independence, and layer-1 recovery depends on independence. Chains stay unchanged; rationale recorded durably.
Analysis (AC #1, #2)
CLAUDE_ACTION_MODEL_CHAIN=claude-sonnet-4-6,claude-opus-4-8(engine.sh:154).Implementation Checklist
CLAUDE_*_MODEL_CHAINdefaults unchanged (no weakening of cross-provider path or exit-2 contract).Tests to Write
tests/dev-lead/unit/test_engine_chain.batsdocumenting [Phase 2] Assess simplifying the sonnet->opus in-engine fallback given rate-limit equalization #1099's conclusion: the ACTION chain retains the sonnet->opus hop and the daily-cap/exit-2 contract is untouched.Test Command
bash .dev-lead/scripts/dev-lead-lint.sh(shellcheck) andbats tests/dev-lead/unit/test_engine_chain.batsdon-petry commentedon Jul 8, 2026
Dev-Lead: Implementation Complete
Assessment outcome
The in-engine sonnet→opus hop is NOT redundant — chains left unchanged; rationale recorded.
Rate-limit equalization makes each Claude model's RPM/TPM bucket the same size across tiers, but it does not merge them into one shared bucket. Layer-1 recovery (engine.sh:13-22) works because "each Claude model has its own TPM/RPM bucket" — it depends on the buckets being separate, not on them differing in size. A saturated
claude-sonnet-4-6RPM/TPM bucket is still relieved by hopping toclaude-opus-4-8's independent bucket regardless of equal sizing, so the hop (CLAUDE_ACTION_MODEL_CHAIN=claude-sonnet-4-6,claude-opus-4-8, engine.sh:154) stays useful and is retained.Per the Dev Notes, this "no code change to the chains, rationale recorded" is the expected, valid result — no chain edit was forced to look productive.
Acceptance criteria
test_engine_chain.batsextended with three [Phase 2] Assess simplifying the sonnet->opus in-engine fallback given rate-limit equalization #1099 regression guards.shellcheckclean (dev-lead-lint), dev-lead unit bats pass.Test Results
Files Changed
scripts/engine.sh: added a concise [Phase 2] Assess simplifying the sonnet->opus in-engine fallback given rate-limit equalization #1099 rationale note to the two-layer fallback doc explaining why equalization (equal bucket size, not shared bucket) does not collapse the sonnet→opus hop, and why the daily cap (feat(dev-lead): proactive provider headroom check before engine invocation #206) is layer-2 only. No chain defaults changed.tests/dev-lead/unit/test_engine_chain.bats: added three regression guards documenting the [Phase 2] Assess simplifying the sonnet->opus in-engine fallback given rate-limit equalization #1099 conclusion — hop retention, layer-1 RPM/TPM recovery, and the preserved exit-2 cross-provider contract.Phase-2 (TDD) note
Per the documentation/behavior-preserving exception: the assessment concluded no behavioral change, so there was no red→green cycle. The added tests are regression guards that assert the (unchanged) intended behavior and pass against current code.
Notes
No follow-ups. The daily-subscription-cap safety net is explicitly kept; only per-model RPM/TPM reasoning was re-evaluated.
feat: implement issue #1099 — [Phase 2] Assess simplifying the sonnet…