Skip to content

refactor(combo): split executeTarget into gates, attempt, and loop - #12746

Merged
diegosouzapw merged 22 commits into
diegosouzapw:release/v3.8.51from
HouMinXi:feat/combo-execute-target-split
Sep 7, 2026
Merged

diegosouzapw merged 22 commits into
diegosouzapw:release/v3.8.51from
HouMinXi:feat/combo-execute-target-split

Conversation

@HouMinXi

@HouMinXi HouMinXi commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

handleComboChatInner's 1327-line executeTarget is now three modules: pre-dispatch skip gates, the retry/side-effect loop, and the setTry/safety-timer dispatcher. combo.ts goes from 4080 to 2234 lines (split("\n").length). Round-robin stays in combo.ts.

Why

combo.ts sat on its file-size freeze (4080). The leftover bulk was executeTarget, not more types. ROADMAP 3.8.52 lists this split under PREPARE.

What moved

Module Role LOC
open-sse/services/combo/attemptLoopTypes.ts AttemptLoopState / AttemptLoopDeps 118
open-sse/services/combo/executeTargetGates.ts 10 skip gates, breaker through admission 330
open-sse/services/combo/executeTargetClassify.ts input-bound / body-specific 400 / homogeneous remainder 55
open-sse/services/combo/executeTargetAttempt.ts retry loop + pin/LKGP/quality/cooldown 1205 (frozen; classify already extracted)
open-sse/services/combo/comboAttemptLoop.ts setTry, #11804 safety timer, speculative tasks, cooldown redispatch 576

handleComboChatInner builds AttemptLoopState/AttemptLoopDeps and calls dispatchWithCooldownRetry. Control flow is copied as-is: pin release, LKGP, quota cutoff, 499/400/quality, loop-safety finally, cooldown-wait redispatch.

Tests

Tip b9b24fbfd on upstream/release/v3.8.51 @ c3945a724.

DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 \
  --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts \
  --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit \
  tests/unit/combo/execute-target-gates.test.ts \
  tests/unit/combo/execute-target-attempt.test.ts \
  tests/unit/combo/combo-attempt-loop.test.ts \
  tests/unit/combo-loop-safety-timer-leak-11804.test.ts \
  tests/unit/combo-body-specific-400-stop-4279.test.ts \
  tests/unit/combo-priority-quota-exhaustion-cutoff-5923.test.ts \
  tests/unit/combo-empty-content-failover-5085.test.ts \
  tests/unit/combo-input-bound-failure-8375.test.ts \
  tests/unit/combo/combo-exhausted-skip.test.ts \
  tests/unit/combo-dispatch-prelude.test.ts \
  tests/unit/combo-cooldown-retry.test.ts \
  tests/unit/combo-error-aggregation.test.ts \
  tests/unit/combo-max-global-attempts-config.test.ts

107/107 pass.

Injection (commit 73a1c6c5f): releaseStickyPinOnFailure at executeTargetAttempt.ts:395 replaced with () => {}. Quality-rejected 200 then failed with released==null (2 failures). Restore: 7/7 green.

node scripts/check/check-file-size.mjs --base-ref upstream/release/v3.8.51 OK. New leaf executeTargetAttempt.ts frozen at 1205: remaining growth is I/O plus side effects inside the retry loop; splitting that mid-request would change behavior.

Not in this PR

Base-red inherited

⚠️ base-red inherited: #12732 (release/v3.8.51 currently red). Failures that match that issue are not from this split.

@HouMinXi

HouMinXi commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Technical review notes for the follow-up 83ff97a43 (unused imports after the extract).

LOCAL review-default on that commit: HOLD, 0 CONFIRMED, 1 UNCERTAIN.

The UNCERTAIN is handleRoundRobinCombo nesting: _nesting = null (same pattern on the other unused args). HandleRoundRobinOptions still has those keys; eslint @typescript-eslint/no-unused-vars requires the _ local. _nesting = null without the rename is TS2339. Not a defect.

Earlier extract/hygiene reviews on this branch also HOLD with 0 CONFIRMED. Lift-as-is findings that praised dead-code removal were not defects.

CI on 83ff97a43: eslint now pass. Remaining red matches the release-tip set (#12732): changelog fragment without - , glm.ts TS2554 (not in this diff; #12711 removes the extra positional), mutation / open-sse-typecheck. Local check-complexity-ratchets.mjs is OK (2764 / 1245 vs baseline 3218 / 1437). check-file-size.mjs --base-ref upstream/release/v3.8.51 OK. Focused combo tests 107/107.

Contributor only — not merging.

@HouMinXi
HouMinXi force-pushed the feat/combo-execute-target-split branch from 83ff97a to 5a5ee9b Compare September 5, 2026 14:33
@HouMinXi

HouMinXi commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto upstream/release/v3.8.51 @ 9d1a896c6 (#12670).

range-diff every unique commit =. All rewritten commits GPG G. behind=0 vs tip.

Own tests re-run on the new base. --force-with-lease to the previous fork SHA.

⚠️ base-red inherited: #12732 (FQG / unit shards / changelog-integrity / glm arity until #12770 lands). Files this PR does not touch.

@HouMinXi

HouMinXi commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto release/v3.8.51 tip f9a1cc8a9 (#12682 / #12691 / #12834).

5a5ee9be5 → ec88a6399. range-diff 7 commits =. GPG G. No file overlap with the three landed commits.

Types only. Characterization test watched ERR_MODULE_NOT_FOUND then PASS.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
Copy the 10 skip gates (breaker through admission) into
executeTargetGates.ts. combo.ts still owns executeTarget until the
attempt/loop extract. Circuit-open counters and per-target admission
join AttemptLoopState/Deps.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
Task 2 extract keeps combo.ts executeTarget behavior. Comments pin
the four contracts reviewers treated as new defects.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
Lift-as-is retry loop from combo.ts:1533-2616 into executeTargetAttempt.ts.
Pure classify predicates (homogeneous remainder, input-bound abort, body-specific 400) live in executeTargetClassify.ts. Pin/LKGP go through deps so injection can catch a missed forward. combo.ts not wired yet (Task 4). Attempt file frozen at 1205 after classify extract (54 LOC).

Signed-off-by: Minxi Hou <houminxi@gmail.com>
Extract dispatchWithCooldownRetry into comboAttemptLoop.ts. handleComboChatInner
now builds AttemptLoopState/Deps and calls the extracted loop; executeTarget is
evaluateGates then executeAttempt. diegosouzapw#11804 finally stays on the loop.

Injection: noop deps.releaseStickyPinOnFailure at executeTargetAttempt.ts:395
fails quality-rejected 200 (released==null); restore 7/7 green.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
Attempt budget already lives on state.globalAttempts (executeTargetAttempt).
The extra.{current} box, unused delay locals in handleComboChatInner, unused
clearComboFailureTracking import, and unused timeoutResolve were lift leftovers.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
Barrel still imported lockout/handoff/trace helpers that now live in the
attempt/gates leaves. Unused HandleRoundRobinCombo args renamed in
destructure so the type stays intact.

Signed-off-by: Minxi Hou <houminxi@gmail.com>
@HouMinXi
HouMinXi force-pushed the feat/combo-execute-target-split branch from ec88a63 to 152bf96 Compare September 7, 2026 02:31
@HouMinXi

HouMinXi commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto upstream/release/v3.8.51 b345c7f6c (#12870 OpenCode v2 plugin).

  • ec88a63999c → 152bf96db27
  • range-diff identity (eq=7); all commits GPG G
  • 7 unique commit(s) ahead, 0 behind
  • --force-with-lease to HouMinXi:feat/combo-execute-target-split

diegosouzapw and others added 14 commits September 7, 2026 08:35
…ibution (diegosouzapw#12772)

* chore(ci): guard commit identity in pre-commit to stop author misattribution

Two windows of commits in this checkout were signed with the wrong identity,
both caused by an identity override left behind by an automated session:
2026-08-13..26 (name "Xiangzhe" + @backryun's e-mail, 237 commits) and
2026-08-29..09-02 (name "Markus Hartung" + the maintainer's e-mail, 59 commits).
The .mailmap repairs the record after the fact; this gate stops the next window.

The gate is opt-in per machine via omniroute.expectedName / expectedEmail — with
no config it exits 0, so contributors who clone the repo are never affected. It
blocks three things: a committer that is not this machine's identity (which is
what BOTH windows looked like — in August neither the name nor the e-mail was
the maintainer's, so checking only their e-mail would have missed it), an author
carrying the maintainer's e-mail under someone else's name, and any address
listed in omniroute.legacyEmail.

Crediting a contributor with `git commit --author="Name <their@email>"` keeps
working, since the rule targets the committer and the maintainer's own address.

* test(ci): isolate the identity gate's test from the ambient git config

The "stays inert when the machine has not opted in" case read the real
global config, so on a machine that HAS opted in (omniroute.expectedEmail
set — the maintainer's own boxes, where this gate matters most) the gate
correctly refused a synthetic contributor identity and the test failed.
It only passed on a clean CI runner.

Neutralising GIT_CONFIG_GLOBAL/GIT_CONFIG_SYSTEM makes the opt-in state
come solely from what the test injects, so the suite is deterministic on
both an opted-in and a clean machine.
…2770)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

O `65536` era o 16º posicional de um helper com 15 parâmetros — `TS2554` vivo no tip (`open-sse/executors/glm.ts:244`, confirmado aqui antes do board). O teste de guarda de aridade é o que impede a reincidência: ele checa a assinatura do helper e o call site, não o comportamento, que é exatamente onde o erro morava.

Obrigado por isolar isso do diegosouzapw#12711 em vez de deixar o `glm.ts` viajar junto com pin/combo-split/moonshot.
…iegosouzapw#12711)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

Além do bug do toast, esta PR foi a que derrubou os três base-reds vivos do tip: o fragmento `changelog.d/fixes/reset-aware-model-family.md` sem o `- ` inicial, o registro do `tests/unit/reset-aware-request-scope-12600.test.ts` no `stryker.conf.json` e o `TS2554` do glm. O `check-changelog-integrity` voltou a passar aqui por causa dela.

O diagnóstico do MouseEvent é o que dá o valor: `onConfirm` chegava como handler de clique nativo e `handleBatchDeleteConfirm` tratava qualquer primeiro argumento truthy como callback. O cinto (`typeof`) e o suspensório (o wrap no ConfirmModal) juntos estão certos — só um dos dois deixaria a porta aberta para o próximo caller.
)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

O `nodeMap` lido do closure de `RuntimePageClient` por uma função de nível de módulo é uma bomba-relógio silenciosa: só explode quando um monitor entra em error/exhausted/alerting, e o teste existente só alimentava listas vazias. Tirar o arquivo do exclude do vitest vale tanto quanto o fix — confirmei aqui que `tests/unit/ui/runtime-page-client.test.tsx` agora roda na `test:vitest:ui` e passa.

A anotação sobre o "内部服务器错误" ser o catálogo RSC da página, e não o crash, poupou o próximo a caçar fantasma.
…diegosouzapw#12733)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

Available 0% com Voucher 100% e Cash 100% não é estado de carteira que exista — foi o sinal certo para puxar o fio. Tratar leftover como booleano só para Available e cravar 100% nos outros dois buckets é o tipo de defeito que passa despercebido enquanto a conta tem saldo.

Os dois testes cobrem os dois lados: o produtor e o caminho até `getQuotaRemainingPercentage` com `isCredits` + CNY.
…egosouzapw#12767)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

A separação entre o que é do service worker e o que é do Caddy está certa e é o que torna a PR mergeável: o `respondWith` em navegação é defeito nosso, o `Alt-Svc` mentindo h3 é config de proxy reverso e não tem o que fazer aqui.

O `/dashboardfoo` casando com `startsWith("/dashboard")` é um achado à parte, e o bump de cache v2→v3 é o que faz o worker antigo sair do ar nos clientes que já estão presos.
…gets (diegosouzapw#12475) (diegosouzapw#12926)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

A busca do sufixo mais longo primeiro (`-xhigh` antes de `-high`) é o detalhe que faz a herança funcionar em vez de quase-funcionar. Manter `getResolvedModelContextOverride` fora do escopo, com o teste existente registrando que aquele caminho continua sem herança, deixa a fronteira explícita.
… member (diegosouzapw#12899)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

Regressão de v3.8.50 vinda do diegosouzapw#9057, com o sintoma mais enganoso possível: `attempted: 0`. A política já tinha admitido o combo e a checagem era refeita em cada membro interno.

Manter o filtro por prefixo de provider e o `disableNonPublicModels` intactos é o que impede o short-circuit de virar um buraco na allow-list.
…ts (diegosouzapw#12805)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

A decodificação dos campos aninhados 10/20/30 do `GetRemainingResets` ao vivo (último commit) é o que separa isto de um palpite sobre o formato do frame. Mostrar zero em vez de esconder a linha é a escolha certa: crédito zerado é informação, ausência de linha é ambiguidade.
…apw#12803)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

`blockExtraUsage: false` significa "pode usar crédito extra", nunca "esconda a conta antes de despachar" — a conta saía da rota justamente quando o crédito extra existia para ser usado. Os 32/32 cobrem os quatro pontos onde a mesma decisão era tomada, e revalidei após o merge da base (32/32 de novo).

Nota de integração: o seu `isQuotaExhaustedForRequest` colidiu com o placeholder `_providerSpecificData` do diegosouzapw#12789 na worktree combinada. Ficou a sua implementação, que é a que de fato usa o parâmetro. A base foi mergeada na branch para resolver o `file-size-baseline.json` (aditivo, JSON revalidado).
…iegosouzapw#12697)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes. Após o merge da base nesta branch, os 11/11 do `combo-pin-implicit-allowlist` foram revalidados.

A distinção entre pin de step de combo e pin forçado por header (`x-omniroute-connection`) é o que salva a PR de virar uma restrição ampla demais — o header continua permitindo fallback para conexões irmãs, o step não.

Apontar que o `a11930ec4` para a rotação dentro do `handleSingleModel` mas não popula `allowedConnectionIds` no resolve foi a peça que explicou por que os dois são complementares e não redundantes. Sem isso a PR pareceria duplicar um gate que já existia.
…atalog (diegosouzapw#12597) (diegosouzapw#12934)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437 (ambos sob a baseline), ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

A assimetria era exatamente o defeito: o REST do picker já mesclava `customModels`, o despacho não, e o operador via o modelo na tela e tomava 400 na inferência. O overlay só de campos definidos é o detalhe que impede uma escrita esparsa do picker de apagar metadata de capacidade que veio do sync.

Nota de integração: este arquivo colidiu com o diegosouzapw#12866, que extraiu o mesmo bloco para `loadConnectionCatalog` e uniu os catálogos irmãos agy/antigravity. Integrei os dois na worktree combinada — a união de irmãos primeiro, o `unionCustomModels` por cima — e a resolução vai junto no merge do diegosouzapw#12866.
…iegosouzapw#12866)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437, ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

O ponto que sustenta a PR é o `models.dev` virar overlay de preço em vez de fonte de catálogo. Um catálogo estático que sobrevive à conta já ter listado ids mais novos é o tipo de defeito que só aparece quando o modelo novo é justamente o que se quer usar.

Nota de integração: `activeSyncedCatalog.ts` colidiu com o diegosouzapw#12934 (união dos `customModels` do picker no catálogo de despacho). Como você extraiu o bloco original para `loadConnectionCatalog`, os dois se compõem: a união dos irmãos agy/antigravity primeiro, o `unionCustomModels` por cima. Revalidei com `custom-models-live-catalog-12597`, `live-model-catalog-reconciliation-8926`, `sync-models-degraded-cached-catalog-9683`, `models-dev-catalog-read-gate`, `discovery-class`, `reactive-model-sync` e `l1-oauth-autosync-default` juntos — 48/48 — mais typecheck:core limpo.

Sobre o `autoSync` padrão em Claude/Codex/Copilot com scheduler de 6h: passei isso pelo dono antes de mergear e a decisão foi manter como está.
…ftover (diegosouzapw#12789)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437, ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

Reservar o sorteio antes do próximo `await` (`2cf74acc`) é a parte não-óbvia e a que mais importa: sem isso dois pipelines no mesmo processo observam `inflight=0` na mesma conta e convergem para ela. O comentário no código explica isso melhor do que o commit message.

**Um ajuste meu na sua branch.** O `tests/unit/combo/quota-weighted-strategy.test.ts` era intermitente — falhava em cerca de 1 a cada 5 execuções, alternando entre `A/B isolation: 7 hard-empty…` e `floor=0 puts 0.5% in the main pool`, sempre com dois pares de mesma faixa trocando de posição. A causa é o helper de fixture:

```ts
const iso = (ms = 86_400_000) => new Date(Date.now() + ms).toISOString();
```

Como `iso()` é chamado a cada invocação do fetcher, dois peers que deveriam empatar recebiam `resetAt` com um milissegundo de diferença sempre que o relógio virava entre as duas chamadas. Pressão de reset entra no score, então esse epsilon quebrava o empate e `sortByScoreThenIndex` nunca chegava ao fallback por índice de inserção.

Fixei a base do relógio uma vez só (`CLOCK_BASE`). Nenhuma asserção foi tocada — as garantias de ordem, tamanho e exclusão continuam idênticas. 10/10 execuções verdes depois, e mais 6/6 após o merge da base nesta branch.

Também mergeei a base para resolver `file-size-baseline.json` (aditivo) e `src/domain/quotaCache.ts`, onde o seu placeholder `_providerSpecificData` cedeu lugar à implementação do diegosouzapw#12803, que usa o parâmetro de fato.
@diegosouzapw
diegosouzapw merged commit 6b587d0 into diegosouzapw:release/v3.8.51 Sep 7, 2026
3 of 7 checks passed
diegosouzapw pushed a commit that referenced this pull request Sep 7, 2026
…12811)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437, ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

**Sobre a reconstrução da branch.** Esta PR continha os 7 commits do #12746 mais os 3 do round-robin. O dono escolheu mergear os dois em sequência em vez de fechar um como subsumido, então depois que o squash do #12746 entrou eu reconstruí esta branch: cherry-pick de `05059880`, `54168238` e `ddd6bcbf` sobre o tip novo, e force-push. Autoria preservada — os três commits continuam seus (`Minxi Hou <houminxi@gmail.com>`), verificado com `git log --format=%an` antes do push. A PR foi de +4167/−3187 em 14 arquivos para +1281/−1182 em 5, que é o delta real do round-robin.

O `05059880` ("guard round-robin extract before the lift") é o commit que faz esse tipo de extract ser revisável: sem um teste que fixe o contrato antes do movimento, mover 1198 linhas é indistinguível de reescrever 1198 linhas.

Revalidei sobre o tip reconstruído: `round-robin-combo`, `combo-attempt-loop`, `execute-target-attempt`, `execute-target-gates` e `combo-loop-safety-timer-leak-11804` — 24/24 — com typecheck:core limpo e o cap de arquivo OK.
@HouMinXi
HouMinXi deleted the feat/combo-execute-target-split branch September 7, 2026 13:27
diegosouzapw pushed a commit that referenced this pull request Sep 10, 2026
…12884)

Um `ALL_TARGETS_SKIPPED` 503 que não diz qual janela esgotou é opaco justamente no momento em que o operador mais precisa saber. Alinhar os rótulos de janela AUTH com os da API de uso fecha a outra metade: dois nomes para a mesma coisa fazem o dashboard e o erro parecerem discordar.

Revalidei sobre o tip: **6/6**, typecheck:core limpo, check-file-size OK.

**Dois consertos meus na sua branch.**

1. `typecheck:core` falhava com `TS2345` em `comboAttemptLoop.ts` (linhas 130 e 416): o `QuotaSkipTarget` declarava `connectionId?: string`, mas o `ResolvedComboTarget` carrega `string | null` para alvo não-pinado. Alarguei para `string | null` no tipo de diagnóstico em vez de estreitar o call site — o módulo só **lê** o campo e a linha 29 já narrowa com `typeof === "string"`, então null não custa nada ali. Isso apareceu porque o `comboAttemptLoop` mudou de forma no #12746/#12811, mergeados nesta mesma campanha depois que você cortou a branch.

2. O `roundRobinCombo.ts` foi de 1198 para 1205 e cruzou o teto de 1200 para arquivo novo. Congelei com justificativa: o arquivo já nasceu em 1198 quando o #12811 o levantou de dentro do `combo.ts`, e os diagnósticos em si vivem no `quotaSkipDiagnostics.ts`, sob o cap. Registrei que a próxima extração natural é o corpo do attempt loop, mas que ele acabou de ser movido e deve assentar antes de ser cortado de novo.
hartmark added a commit to hartmark/OmniRoute that referenced this pull request Sep 11, 2026
… the whole fallback chain

A malformed/unsupported request shape (e.g. an incompatible tool-call
history for a provider's translation layer) fails the SAME way against
every fallback target, since it is a property of the request, not of
any one provider. Detect 3 consecutive targets failing with the
identical model-shape error (same kind, status, and message) and stop
retrying -- both the remaining targets in this pass and the whole-set
retry -- instead of burning through all MAX_GLOBAL_ATTEMPTS fallbacks
identically.

Rebased onto release/v3.8.51: the original combo.ts main loop this was
written against has since been split into comboAttemptLoop.ts (gates/
attempt/loop extraction, diegosouzapw#12746), so the fix now lives in the
equivalent per-target loop and set-retry guard there, and the terminal
response reuses the loop's own already-generalized
resolveComboTerminalStatus()/formatComboOutcomes() exhaustion path
(diegosouzapw#10501) instead of a separate response branch.
diegosouzapw added a commit that referenced this pull request Sep 11, 2026
…cted fences

Both reds were inherited from release/v3.8.51 — every production file involved is
byte-identical to the base tip. Three PRs merged 2026-09-07 moved or added call
sites without updating the golden inventory:

- #12867 (d6f3150) extracted the codex 429 / antigravity 422 account rotation
  out of chatCore.ts into chatCore/providerExecutionPipeline.ts. The managed-lease
  fence was NOT removed: it crosses the seam as `policy.allowAccountRotation`,
  still derived from `!managedLease` on both the streaming and the non-streaming
  leg. The antigravity branch, which had no lease fence at all before the extract,
  is now gated by the same flag. The two credential-resolution sites moved with it
  and are called off the injected `connection` context, so countCalls() now also
  sees that property-access shape — otherwise an extract-to-a-seam refactor would
  silently drop a credential site out of the inventory.
- #12746 (6b587d0) lifted combo.ts's persisted-cooldown connection read into
  combo/executeTargetGates.ts byte-identically (same site, renamed).
- #12805 (c042a51) added grok-cli reset credits: grokResetCredits.ts already
  carries isConnectionUnavailableToAuxiliaryActivity() ahead of its lookup, so it
  joins the auxiliary-isolation source list; the shared reset-credit route reads
  the connection only to pick a handler (class C).

Assertions are pinned tighter, not looser: the single chatCore regex is replaced
by both ends of the split fence, and the two rotation-policy sites are counted
exactly rather than merely detected.
hartmark added a commit to hartmark/OmniRoute that referenced this pull request Sep 15, 2026
… the whole fallback chain

A malformed/unsupported request shape (e.g. an incompatible tool-call
history for a provider's translation layer) fails the SAME way against
every fallback target, since it is a property of the request, not of
any one provider. Detect 3 consecutive targets failing with the
identical model-shape error (same kind, status, and message) and stop
retrying -- both the remaining targets in this pass and the whole-set
retry -- instead of burning through all MAX_GLOBAL_ATTEMPTS fallbacks
identically.

Rebased onto release/v3.8.51: the original combo.ts main loop this was
written against has since been split into comboAttemptLoop.ts (gates/
attempt/loop extraction, diegosouzapw#12746), so the fix now lives in the
equivalent per-target loop and set-retry guard there, and the terminal
response reuses the loop's own already-generalized
resolveComboTerminalStatus()/formatComboOutcomes() exhaustion path
(diegosouzapw#10501) instead of a separate response branch.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…iegosouzapw#12746)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437, ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

Guardar os contratos com testes ANTES de levantar o bloco (`05059880` no irmão, e o `287658f5` marcando os `executeTargetGates` como lift-as-is) é o que torna um refactor deste tamanho auditável. Sem essa ordem, um extract de 3 mil linhas é indistinguível de uma reescrita.

Revalidei depois do merge da base: `combo-attempt-loop`, `execute-target-attempt`, `execute-target-gates` e `combo-loop-safety-timer-leak-11804` — 20/20 — mais typecheck:core limpo e o cap de arquivo OK.

O diegosouzapw#12811 entra na sequência logo em seguida, com os três commits do round-robin sobre este.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…iegosouzapw#12811)

Validado numa worktree combinada com as 16 PRs desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-file-size e check-changelog-integrity OK, complexity 2788/3218 e cognitive 1261/1437, ESLint 0 erros nos 152 arquivos alterados, 771 testes unitários focados, 49 de integração e a suíte vitest:ui completa (2149) verdes.

**Sobre a reconstrução da branch.** Esta PR continha os 7 commits do diegosouzapw#12746 mais os 3 do round-robin. O dono escolheu mergear os dois em sequência em vez de fechar um como subsumido, então depois que o squash do diegosouzapw#12746 entrou eu reconstruí esta branch: cherry-pick de `05059880`, `54168238` e `ddd6bcbf` sobre o tip novo, e force-push. Autoria preservada — os três commits continuam seus (`Minxi Hou <houminxi@gmail.com>`), verificado com `git log --format=%an` antes do push. A PR foi de +4167/−3187 em 14 arquivos para +1281/−1182 em 5, que é o delta real do round-robin.

O `05059880` ("guard round-robin extract before the lift") é o commit que faz esse tipo de extract ser revisável: sem um teste que fixe o contrato antes do movimento, mover 1198 linhas é indistinguível de reescrever 1198 linhas.

Revalidei sobre o tip reconstruído: `round-robin-combo`, `combo-attempt-loop`, `execute-target-attempt`, `execute-target-gates` e `combo-loop-safety-timer-leak-11804` — 24/24 — com typecheck:core limpo e o cap de arquivo OK.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…iegosouzapw#12884)

Um `ALL_TARGETS_SKIPPED` 503 que não diz qual janela esgotou é opaco justamente no momento em que o operador mais precisa saber. Alinhar os rótulos de janela AUTH com os da API de uso fecha a outra metade: dois nomes para a mesma coisa fazem o dashboard e o erro parecerem discordar.

Revalidei sobre o tip: **6/6**, typecheck:core limpo, check-file-size OK.

**Dois consertos meus na sua branch.**

1. `typecheck:core` falhava com `TS2345` em `comboAttemptLoop.ts` (linhas 130 e 416): o `QuotaSkipTarget` declarava `connectionId?: string`, mas o `ResolvedComboTarget` carrega `string | null` para alvo não-pinado. Alarguei para `string | null` no tipo de diagnóstico em vez de estreitar o call site — o módulo só **lê** o campo e a linha 29 já narrowa com `typeof === "string"`, então null não custa nada ali. Isso apareceu porque o `comboAttemptLoop` mudou de forma no diegosouzapw#12746/diegosouzapw#12811, mergeados nesta mesma campanha depois que você cortou a branch.

2. O `roundRobinCombo.ts` foi de 1198 para 1205 e cruzou o teto de 1200 para arquivo novo. Congelei com justificativa: o arquivo já nasceu em 1198 quando o diegosouzapw#12811 o levantou de dentro do `combo.ts`, e os diagnósticos em si vivem no `quotaSkipDiagnostics.ts`, sob o cap. Registrei que a próxima extração natural é o corpo do attempt loop, mas que ele acabou de ser movido e deve assentar antes de ser cortado de novo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants