AUR-605 — Provedor reserva (fallback)
Medido
llm.Orchestratorjá percorria uma cadeia de provedores, mas todos os chamadores (review, perfis, qualidade da base, dependências, changelog) passavam a lista de reservas vazia (NewOrchestrator(p, nil, ...)).- Não havia variável, input nem secret para declarar uma reserva. Com o provedor fora do ar a revisão falhava fechada, sem plano B.
- O limite de tempo do orquestrador era um só por requisição: uma cadeia cujo primeiro provedor esgotasse o limite nunca ouviria a reserva.
O que mudou
| arquivo | responsabilidade |
|---|---|
internal/llm/fallback.go |
NewFallback (principal sozinho quando não há reserva), Fallback e ToolFallback (só membros que chamam ferramentas recebem rodada com ferramentas); FallbackNotice anuncia cada troca; erro final nomeia cada membro e responde a errors.Is(ErrAllProvidersFailed); TimeoutScaler/callTimeout: um limite por membro. |
internal/llm/orchestrator.go, orchestrator_tools.go |
Limite de tempo por callTimeout(provider); erro de cadeia devolvido sem embrulho duplicado. |
internal/llm/provider/profiles/fallback.go |
FallbacksFromEnv: slots LLM_FALLBACK_1..5_* resolvidos pelo catálogo, URL e chave do slot no lugar das do principal, inclusive as variáveis nativas de chave do perfil, modelo próprio; slot pela metade é erro com as variáveis do slot. |
internal/llm/provider/profiles/resolve.go |
catalogFromEnv compartilhado entre principal e reservas. |
cmd/aurumcode/provider_fallback.go |
withFallbacks monta a cadeia atrás do principal; slotProvider nomeia a reserva pelo slot; aviso no stderr redigido. |
cmd/aurumcode/review_cache.go, review_base_quality.go |
Chave do cache acha a URL atrás da cadeia (llm.As); revisão respondida por reserva (FellBack) não é gravada. |
cmd/aurumcode/main.go, profiles.go |
providerFromEnv usa withFallbacks; o perfil de revisão repassa o limite da cadeia. |
.github/workflows/review.yml |
Inputs fallback_{1,2}_provider/_model, secrets opcionais LLM_FALLBACK_{1,2}_API_KEY/_BASE_URL, nos jobs de revisão e de dependências. |
docs/provedores.md, docs/tutorials/provedores.md, demo/tutoriais/provedores |
Seção "Provedor reserva" e quatro casos executáveis com o provedor falso (rota fora-do-ar responde 503). |
Provas
tests/acceptance/AUR-605.sh (cópia de go.mod go.sum cmd internal pkg):
| id | prova | última linha |
|---|---|---|
| AC-001 | TestAUR605PrimaryFailsFallbackAnswers, TestAUR605HealthyPrimaryAloneIsCalled, TestAUR605ProviderFromEnvFallsBackToTheSlot (servidores HTTP: principal 503, reserva responde com a própria chave; aviso no stderr) |
AUR-605/AC-001/pass |
| AC-002 | TestAUR605AllFailNamesEveryProvider |
AUR-605/AC-002/pass |
| AC-003 | TestAUR605NoFallbackIsThePrimaryItself, TestAUR605NoSlotNoFallback |
AUR-605/AC-003/pass |
| AC-004 | TestAUR605ToolRoundsSkipMembersWithoutTools |
AUR-605/AC-004/pass |
| AC-005 | TestAUR605ChainTimeoutLeavesTimeForTheFallback (limite de 1 s; principal falha em 0,8 s, reserva responde em 0,5 s) |
AUR-605/AC-005/pass |
| AC-006 | TestAUR605SlotsResolveInOrderWithTheirOwnKey |
AUR-605/AC-006/pass |
| AC-007 | TestAUR605UnusableSlotFailsNamingIt, TestAUR605UnusableSlotFailsTheSelection, TestAUR605NativeKeyNeverReachesASlot (OPENAI_API_KEY do ambiente nunca vira chave de reserva) |
AUR-605/AC-007/pass |
| AC-009 | TestAUR605FallbackAnswerIsMarkedAndURLIsThePrimarys, TestAUR605CacheKeyKeepsThePrimaryURL (revisão respondida por reserva não é gravada no cache; llm.As[baseURLReporter] mantém a URL do principal na chave) |
AUR-605/AC-009/pass |
| AC-008 | grep no workflow (inputs, secrets, -e) e nas docs (seção, variáveis, saídas do tutorial) |
AUR-605/AC-008/pass |
| MUT-001 | CallTimeout devolve um limite só |
AUR-605/MUT-001/rejected (...ChainTimeout...) |
| MUT-002 | slot lê LLM_API_KEY do principal |
AUR-605/MUT-002/rejected (...UnusableSlotFailsNamingIt) |
| MUT-003 | troca sem aviso | AUR-605/MUT-003/rejected (...PrimaryFailsFallbackAnswers) |
Tutorial: bash demo/tutoriais/provedores/run.sh all grava os casos
reserva-assume, duas-reservas, falha-todas-caem e
falha-reserva-sem-chave; run.sh --check termina em CHECK OK.