fix(test): replace tautology in playground-api-tab + make test-masking catch it (#6404)#6641
fix(test): replace tautology in playground-api-tab + make test-masking catch it (#6404)#6641diegosouzapw wants to merge 40 commits into
Conversation
Parallel-cycle model (2026-07-04): cut from the frozen release/v3.8.46 tip at the v3.8.46 release freeze so development continues immediately on v3.8.47 while the captain closes v3.8.46. Bumps package.json x3 + openapi + lockfile to 3.8.47, adds the '## [3.8.47] — TBD' living CHANGELOG section, and syncs the 42 i18n mirrors. Closing v3.8.46 fixes reach this branch via the Phase 5 sync-back.
Release v3.8.46. Full changelog: CHANGELOG.md → [3.8.46]. Contributor attribution in the CHANGELOG entries.
…llel-cycle sync-back
…l static gate set (P0) (#6583) * feat(quality): validate-release-green --full-ci reproduces the ci.yml static gate set The curated HARD/DRIFT lists in validate-release-green were a hand-maintained subset — v3.8.46 leaked 11 static base-reds (route-validation:t06, docs-symbols, bundle-size --ratchet, test-masking, file-size, …) to the release PR because they live only in the ci.yml gate jobs, costing ~2h of layered CI. --full-ci reads ci.yml itself and runs every npm run check:* / lint from the lint / quality-gate / quality-extended / docs-sync-strict / pr-test-policy jobs (-- ratchet flags preserved; test-masking against GITHUB_BASE_REF=main; skips pr-evidence + codeql-ratchet which can't run in a local working-tree pre-flight). Reading from ci.yml keeps the set current as gates are added. Also wired into nightly-release-green so a static base-red opens a tracking issue the night it lands. Regression guard: +5 extractCiGates cases (18/18 pass). * chore(quality): add 3 covering tests to stryker tap.testFiles (pre-existing drift on release/v3.8.47) check:mutation-test-coverage (fast-gates) flagged 3 unit tests that cover mutated modules but were missing from stryker.conf.json tap.testFiles — pre-existing drift on release/v3.8.47, surfaced by this PR's CI. Adds codex-quota-selection-hydration (auth.ts), combo-roundrobin-compat-fallback-6238 (circuitBreaker.ts), and combo-rr-fallback-advance-948 (rrState.ts) so their mutant kills count.
…llel-cycle sync-back
…mbo (#6455) (#6532) fix(providers): warn when config.judgeModel is set on a non-fusion combo (#6455) Integrated into release/v3.8.47. (thanks @chirag127)
…#6547) docs(readme): cross-link CodeWebChat as editor-side companion (#6189) Integrated into release/v3.8.47. (thanks @chirag127)
…) (#6548) fix(tests): replace expect(true) tautology in playground-api-tab (#6404) Integrated into release/v3.8.47. (thanks @chirag127)
feat(plugins): add langfuse example plugin Integrated into release/v3.8.47. (thanks @chirag127)
… credential count (#6460) (#6523) fix(providers): enrich model_cooldown 429 body with retry_after ISO + credential count (#6460). Integrated into release/v3.8.47. (thanks @chirag127)
…etrics, /debug, /.env (#6405 follow-up) (#6516) fix(api): JSON 404 for unknown root routes /anthropic/*, /openai/*, /metrics, /debug, /.env (#6405 follow-up) Integrated into release/v3.8.47. (thanks @chirag127)
… widen to lg (#6265) (#6526) fix(providers): size AddApiKeyModal for 1080p (#6265). Integrated into release/v3.8.47. (thanks @chirag127)
) (#6511) * fix(api): exempt test-model requests from Output Styles injection (#6240) Root cause: handleChatCore's Phase 4A Output Styles injection (chatCore.ts) was gated only by the operator's global compression.enabled switch, independent of the per-request x-omniroute-compression header. The dashboard 'Test model' action (modelTestRunner.ts) never sent that header, so a globally-enabled Output Style (e.g. 'Ultra terse') always leaked its system-prompt injection into a plain connection test. Fix: skip Output Styles injection when the request explicitly opts out via x-omniroute-compression: off, and always send that header from buildInternalChatRequest / buildInternalRerankRequest. Regression guard: tests/integration/test-model-compression-off-6240.test.ts, tests/unit/model-test-runner-compression-off-6240.test.ts * chore: sync CHANGELOG to release tip (#6511; bullet re-added at merge)
…tion (#6402) (#6515) fix(api): return 400 for missing/invalid messages before model resolution (#6402). Integrated into release/v3.8.47. (thanks @chirag127)
…h + surface substitution (#6463) (#6534) fix(compression): honor UI-toggled engines in stackedPipeline dispatch + surface substitution (#6463). Integrated into release/v3.8.47. (thanks @chirag127)
…eout (#6458) (#6546) fix(providers): fail fast on empty auto-combo pool instead of 15s timeout (#6458). Integrated into release/v3.8.47. (thanks @chirag127)
#6400) (#6517) fix(api): add explicit HEAD handler for /v1/models to prevent ~6s hang (#6400) Integrated into release/v3.8.47. (thanks @chirag127)
…ed-fallback loops (#6328) (#6549) fix(models): apply hidePaidModels to synced/custom/alias-backed/managed-fallback loops (#6328) Integrated into release/v3.8.47. (thanks @chirag127)
…dModels=true (#6328) (#6551) fix(backup): exclude paid models from JSON export/backup when hidePaidModels=true (#6328) Integrated into release/v3.8.47. (thanks @chirag127)
#6519) fix(compression): surface fallback reasons in preview response (#6461). Integrated into release/v3.8.47. (thanks @chirag127)
…catalog + test endpoints (#6328) (#6552) fix(dashboard-api): apply hidePaidModels to /api/models + openrouter-catalog + test endpoints (#6328). Integrated into release/v3.8.47. (thanks @chirag127)
…hidePaidModels=true (#6328) (#6550) fix(autoCombo): exclude paid-tier auto/* ids from the catalog when hidePaidModels=true (#6328). Integrated into release/v3.8.47. (thanks @chirag127)
…ent-Type (#6414) (#6513) fix(api): return 415 on /v1/messages for non-JSON Content-Type via requireJsonContentType middleware (#6414) Integrated into release/v3.8.47. (thanks @chirag127)
…es in fusion 503 (#6454) (#6521) fix(providers): honor fusion minPanel=1 and surface per-member failures in fusion 503 (#6454) Integrated into release/v3.8.47. (thanks @chirag127)
… clear error (#6457) (#6525) fix(providers): reject image-only models on /v1/chat/completions with a clear error (#6457) Integrated into release/v3.8.47. (thanks @chirag127)
… fetch (#6379) (#6600) orderTargetsByHeadroom already loaded the per-connection DB snapshot (with decrypted credentials) via expandTargetsByQuotaAwareConnections, but discarded it before calling getSaturation. For Codex, fetchCodexSaturation forwards straight to fetchCodexQuota(connectionId, connection), which needs the connection object (or a prior registerCodexConnection() call that never happens before headroom ranking runs) to read accessToken. Without it, fetchCodexQuota returned null for every candidate, saturation failed open to 0 across the board, and headroom ranking fell back to the original combo order regardless of actual free quota. getSaturation() and the headroom SaturationFetcher seam now accept and thread the loaded connection snapshot through to fetchCodexQuota. Regression guard: tests/unit/headroom-codex-quota-snapshot-6379.test.ts (seeds two real Codex connections in a throwaway SQLite DB with a fake upstream fetch, confirms RED on unfixed code, GREEN after the fix).
…g catch it (#6404) playground-api-tab.test.tsx's SSE test always took the disabled-button branch (the fetch mock returned an empty model list) and asserted a tautology instead of exercising the SSE path it claims to verify. The test now selects a real model to enable Send, asserts it is actually enabled, and asserts the streamed SSE content reached the response editor. check-test-masking.mjs's tautology subcheck only compares base-vs-HEAD counts within a PR's own diff and no-ops entirely outside PR context (no GITHUB_BASE_SHA/REF) -- so a tautology merged once, or checked with a bare local run, stayed invisible forever after. Added an always-on absolute-floor scan (scanBareTautologies/countBareTautologies) over every tracked test file, scoped to the bare expect(true).toBe(true)/assert.equal(1,1) patterns that have zero legitimate uses in this codebase -- deliberately excluding assert.ok(true), which has ~15 pre-existing verified-legitimate try/catch-fallback uses and stays on the lenient diff-only path.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Code Review
This pull request improves CLI server startup diagnostics by piping and buffering both stdout and stderr from the server child process, allowing the CLI to print recent logs and diagnostic advice if a timeout occurs instead of hanging silently. It also updates documentation and quality baselines to reflect recent feature additions, such as the new pipeline routing strategy. The review feedback correctly identifies a risk where verbose stdout output could quickly flush out critical stderr error logs from the limited 50-line buffer, and suggests increasing the buffer size to mitigate this.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const bufferOutput = (data) => { | ||
| const lines = data.toString().split("\n").filter(Boolean); | ||
| this.crashLog.push(...lines); | ||
| if (this.crashLog.length > CRASH_LOG_LINES) { | ||
| this.crashLog = this.crashLog.slice(-CRASH_LOG_LINES); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Ao direcionar tanto o stdout quanto o stderr para o mesmo buffer this.crashLog (que possui um limite rígido de apenas 50 linhas, definido por CRASH_LOG_LINES), há um risco real de que mensagens informativas ou de depuração mais volumosas vindas do stdout acabem expulsando rapidamente as mensagens de erro críticas e stack traces do stderr.\n\nIsso pode inutilizar o diagnóstico de falhas de inicialização ou travamentos (que é o objetivo principal desta alteração).\n\nSugestão: Aumentar o limite de linhas mantidas no buffer para garantir que os logs de erro do stderr não sejam perdidos devido à verbosidade do stdout.
const bufferOutput = (data) => {\n const lines = data.toString().split(\"\\n\").filter(Boolean);\n this.crashLog.push(...lines);\n const maxLines = CRASH_LOG_LINES * 4; // Aumenta o limite para acomodar stdout + stderr\n if (this.crashLog.length > maxLines) {\n this.crashLog = this.crashLog.slice(-maxLines);\n }\n };
Recupera o commit
a21928e7a6que ficou solto (detached HEAD) e o aponta para a release atual.O que muda
tests/unit/ui/playground-api-tab.test.tsx— o teste de SSE sempre caía no ramo do botão desabilitado (o mock defetchdevolvia lista de modelos vazia) e afirmava uma tautologia em vez de exercitar o caminho SSE que diz verificar. Agora o teste seleciona um modelo real para habilitar o Send, afirma que ele está de fato habilitado, e afirma que o conteúdo SSE transmitido chegou ao editor de resposta.scripts/check/check-test-masking.mjs— a subcheck de tautologia só comparava contagens base-vs-HEAD dentro do diff da própria PR e virava no-op fora de contexto de PR (semGITHUB_BASE_SHA/REF) — então uma tautologia mergeada uma vez, ou checada com run local puro, ficava invisível para sempre. Adicionado um scan de piso absoluto sempre-ativo (scanBareTautologies/countBareTautologies) sobre todo arquivo de teste rastreado, escopado aos padrõesexpect(true).toBe(true)/assert.equal(1,1)que têm zero uso legítimo neste código — excluindo deliberadamenteassert.ok(true), que tem ~15 usos pré-existentes verificados-legítimos em fallback try/catch e permanece no caminho leniente diff-only.Testes
tests/unit/check-test-masking.test.ts— cobre o novo scan de piso absoluto.tests/unit/ui/playground-api-tab.test.tsx— reescrito para exercitar o caminho SSE real.