Skip to content

fix(compression): make the hub safe for overlapping saves - #15593

Merged
diegosouzapw merged 101 commits into
cheaper-inference:release/v3.8.52from
woodsonl:fix/compression-hub-overlapping-saves
Oct 6, 2026
Merged

diegosouzapw merged 101 commits into
cheaper-inference:release/v3.8.52from
woodsonl:fix/compression-hub-overlapping-saves

Conversation

@woodsonl

@woodsonl woodsonl commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Summary

The Compression Hub at the top of /dashboard/context/combos (CompressionHub.tsx) has two controls that save to PUT /api/settings/compression: the active-profile select (activeComboId) and the Context Editing toggle (contextEditing). Both stay enabled while a save is in flight, so saves overlap. saveSettings reverted a failed save to the settings value captured when that save started (useCallback deps [settings, t]), which goes wrong once another save starts in between:

  • Change the profile, then flip the toggle before the profile PUT answers. If the profile save fails, the screen goes back to the snapshot from before the profile change and loses the toggle, even though the server stored it.
  • If the profile save fails and then the toggle save fails, the toggle's rollback restores its own snapshot, which already held the rejected profile, so the select shows a profile the server never stored.

The Fix

  • Saves go out one at a time through one promise chain that every mounted Hub shares. The Hub keeps the last saved settings and shows them merged with its saves still queued. A failed save drops out of the queue, so only its own fields roll back and a newer save keeps its value.
  • A Hub waits for the saves already queued before it loads. If you leave the page while a save is pending and come back, the new Hub shows what the server stored, and its own saves land after the older ones. A Hub that unmounts during that wait sends no requests once the wait ends.
  • A queued save whose keys a later queued save all carries is skipped, because the later PUT replaces those keys anyway. Three quick profile changes while the first PUT is pending send two PUTs.
  • Each PUT carries AbortSignal.timeout(15_000). A PUT with no answer by then counts as failed, so one stalled request cannot hold the queue.
  • A failed save's error clears when a later save stores every field it had failed, or at the next edit. A save of another field can no longer leave the banner up forever, and the next edit still dismisses it.
  • While a save is queued or in flight, the page asks before unloading (beforeunload), so leaving cannot silently drop a save the queue was still holding.
  • Each PUT still carries only the changed field (fix(api): api/settings/compression save failed #6039).
  • CompressionSettingsTab has used a per-tab version of this queue since fix(compression): settings tab saves only the fields that changed #14723. The Hub's queue is shared across mounts, because a per-Hub queue let a save from a newly mounted Hub land before an older queued one. The ordering holds within one browser tab; another tab keeps its own queue.

Validation

Check Result
Overlap tests on the base code (the first commit adds only the tests) 4 of the 5 new cases fail: the toggle shows off after a failed profile save the toggle outlived, the select shows c1 after both saves fail, three PUTs go out where two should, and the toggle PUT goes out while the profile PUT is stalled. The fifth case (a later save fails, the earlier one is kept) passes before and after.
Remount tests on the per-Hub queue (the third commit adds only the tests) both fail: the new Hub shows stale values, and it lets its own save go out before the old Hub's queued save
Second-round tests on the queue as first shipped (the eighth commit adds only the tests) 3 of the 4 new cases fail: the banner stays up after a later save stores the failed field, no unload prompt while a save is pending, and an unmounted Hub still sends its settings GET after the queue drains. The fourth (the banner clears at the next edit) pins existing behavior and passes before and after.
The four Hub test files at the head 22/22 pass
All compression and Hub UI test files at the head 26 files, 102/102 pass
Adversarial probes (orderings, mounts, queue mechanics, error display, timeout, two Hubs) 5 scenarios, all pass
StrictMode probe (one PUT per change, per-field rollback, GET-500 fallback) 3/3 pass
Codex review of the diff 2 findings reproduced and probed: both are pre-existing limits the base produces identically (cross-tab staleness across two browser tabs; two Hub copies in one module cannot coexist in the product). Details in Reviewer Notes.
Independent red-team and adversarial code passes on the head both SHIP: no blocker; every constructed failing sequence resolves correctly
Server render and live routes (dev server, scratch data dir) Hub HTML renders server-side; login, settings GET, combos GET all 200
Dashboard typecheck gate, ESLint and Prettier on the changed files, i18n guard, pre-commit gates pass
Interactive browser pass with forced PUT failures not completed: the automation webview cannot finish rendering any dashboard route under the Next dev server (pages without this change hang the same way). The server render check above and the jsdom DOM probes cover what the browser pass would have exercised.

These .tsx tests run under vitest.config.ts (npm run test:vitest:ui). CI runs that suite in ci.yml, which triggers for pull requests into main, so the runs above are local; the suite next runs in CI on the release pull request.

Tests Added Or Updated

tests/unit/ui/compressionHub-active-selector.test.tsx gains a fake route that stores what each successful PUT carries, can hold each PUT, and fails the PUTs that carry chosen keys, so a test decides the order in which saves answer and checks the stored settings:

  1. A failed profile save rolls back only the profile and keeps the toggle save the server stored; the error stays visible after the toggle save succeeds.
  2. A failed toggle save after a failed profile save leaves both controls at their saved values.
  3. A failed toggle save after a successful profile save keeps the profile.
  4. Three quick profile changes while the first PUT is held send two PUTs, and the select ends on the last choice.
  5. A Hub mounted while another Hub still has saves queued shows what the server stored.
  6. A Hub mounted while saves are queued stays in its loading state until they land, so its own save lands last.
  7. A PUT that never answers fails when its 15-second timeout fires, and the toggle save queued behind it then goes out.
  8. The error clears when the user makes the next edit.
  9. The error clears once a later queued save stores the field that failed.
  10. The page asks before unloading while a save is queued or in flight, and stops asking once the queue drains.
  11. A Hub unmounted while its load waits on the queue sends no settings GET after the wait ends.

The harness gains a second named combo for case 4.

Reviewer Notes

  • A PUT that the server stores after the 15-second timeout still counts as failed and rolls back on screen; the screen and the server can then disagree until the next save or remount re-syncs. This is the price of treating a timeout as a failure (the route does not observe the client's abort signal); a fresh Hub always shows the stored value.
  • After a failed save, the banner is driven by the set of fields whose latest save failed: it clears when later saves store all of them, or at the next edit. A next edit also clears failures of other fields that are still unstored; the rolled-back values stay on screen either way. This matches fix(compression): settings tab saves only the fields that changed #14723.
  • A Hub that mounts while a PUT is stalled stays in its loading state until that PUT answers or times out.
  • The select and the toggle stay enabled; a queued change shows on screen at once.
  • The shared queue orders saves within one browser tab. Two tabs can still overwrite each other on the server, as before this change; each tab shows its own last-saved copy until a remount.
  • The queue's promise chain has no catch of its own. Nothing in the task body can throw today (the fetch, its timeout, and network errors are all caught), but a future edit that throws there would stall every later save in the tab and hang future Hubs on their loading state. Hardening the tail is a sensible fast follow.
  • AbortSignal.timeout is treated as available, matching the ten existing client/server usages in the repo; on a browser without it every save would report failure.

⚠️ base-red inherited: #15306

The hub's active-profile select and Context Editing toggle stay enabled
while a settings PUT is in flight, so a second save can start before the
first answers. These tests hold each PUT and answer them in a chosen
order.

They fail on the current hub: a failed profile save wipes a toggle save
the server stored, and a failed toggle save brings back a profile value
the server rejected. They also expect superseded queued saves to be
skipped and a stalled PUT to time out after 15 seconds.
saveSettings reverted a failed PUT to the settings captured when that
save started. The active-profile select and the Context Editing toggle
both stay enabled during a save, so saves overlapped. A failed save
could wipe a newer save the server had stored, or bring back a value
the server had rejected.

Saves now go out one at a time. The hub keeps the last saved settings
and shows them with the saves still queued, so a failed save rolls back
only its own fields. A queued save whose keys a later queued save all
carries is skipped, and a PUT with no answer after 15 seconds counts as
failed, so a stalled request cannot hold the queue. The settings tab
uses the same queue (cheaper-inference#14723).
The fake route now stores what a successful PUT carries and answers
GETs with it, so each overlap test also checks the stored settings.
Two new tests leave the page while hub saves are queued and mount a
new hub. Both fail against a per-hub queue. The new hub loads before
the old saves land and shows stale values, and its own save can land
before an older queued one. The timeout test's stalled PUT now never
reaches the route.
A hub that unmounted with saves still queued kept sending them, but a
hub mounted afterwards had its own queue. It loaded before those saves
landed and showed stale values, and its first save could land before an
older queued one, leaving the server on the older value.

Every hub now shares one module-level save queue, and a hub loads only
after the saves ahead of it have landed.
The timeout comment states how long a PUT gets before it counts as
failed, the refs comment describes only the refs, and the skip comment
says the replaced save is skipped.
…etch

Three new overlapping-saves cases: the error clears once a later save
stores the field that failed; the page asks before unloading while a
save is queued or in flight; and a Hub unmounted while its load waits
on the queue sends no settings GET after the wait ends. A fourth pins
the existing error-clears-on-next-edit rule.
A failed save's error now clears when a later queued save stores every
field it had failed, not only at the next edit. The browser asks before
the page unloads while a save is queued or in flight, so leaving cannot
silently drop one. A Hub unmounted while its load waits on the shared
queue no longer fetches settings after the wait ends. The queue comment
now says its ordering holds within one tab only.
@woodsonl
woodsonl requested a review from diegosouzapw as a code owner October 5, 2026 21:55
woodsonl and others added 22 commits October 5, 2026 16:56
…purify 3.4.16 and patched npm-bundled copies in the image (cheaper-inference#15325)

- next/eslint-config-next 16.3.5 -> 16.3.6 (critical RCE in next/og ImageResponse).
- override axios ^1.20.0 so ibm-cloud-sdk-core's exact 1.18.0 pin cannot keep the vulnerable copy.
- @grpc/grpc-js 1.14.5, dompurify 3.4.16 via lockfile.
- Dockerfile npm-internals overlay: undici 6.29.0, brace-expansion 5.0.12, ip-address 10.7.3.
node-forge has no patched release yet (dev-only, via promptfoo -> jks-js).
…aper-inference#15003)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…inference#15225)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
… Rule cheaper-inference#16 (cheaper-inference#15389)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
… text (cheaper-inference#15399)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…alog (cheaper-inference#15396)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…heaper-inference#15395)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…per-inference#15378)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
cheaper-inference#15432)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…get (cheaper-inference#15433)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…rence#15434)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…ference#15463)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…ce#15466)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…pass (cheaper-inference#15560)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…ead of failing silently (cheaper-inference#15362)

Validated in a combined 14-PR board on the current release tip (112313a): 111 focused tests, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…inference#15224)

Validated in a combined board on the current release tip: focused node:test + vitest suites, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…umn name" (cheaper-inference#15236)

Validated in a combined board on the current release tip: focused node:test + vitest suites, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…guard (cheaper-inference#15239)

Validated in a combined board on the current release tip: focused node:test + vitest suites, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…rt failures (cheaper-inference#15248)

Validated in a combined board on the current release tip: focused node:test + vitest suites, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
… in pool visibility (cheaper-inference#15374)

Validated in a combined board on the current release tip: focused node:test + vitest suites, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
…r-inference#15375)

Validated in a combined board on the current release tip: focused node:test + vitest suites, typecheck:core, open-sse typecheck, gate-manifest, mutation-test-coverage, file-size, changelog-integrity, complexity, env-doc-sync, test-discovery, vitest-exclusions, error-helper, cli-i18n and the i18n new-keys/ui-coverage gates green. Thank you for the contribution.
HouMinXi and others added 29 commits October 6, 2026 17:37
…-inference#15461)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…nce#15355)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…length (cheaper-inference#15369)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…ect (cheaper-inference#15365)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…ner (cheaper-inference#15363)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…x_tokens (cheaper-inference#15418)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…#15416)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…erence#15472)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…cheaper-inference#15516)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…aper-inference#15356)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
cheaper-inference#15553)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…aper-inference#15035)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…heaper-inference#15642)

Onda 2 (HouMinXi) validada num único board em `.claude/worktrees/batch-w2` sobre `origin/release/v3.8.52` (`e05f1bd78bac`), 26 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. changelog-integrity, complexity (2973/3218) e cognitive-complexity (1356/1437) dentro do baseline. Testes focados: 235 passaram. Os 5 vermelhos não são deste diff: o `.test.tsx` do cloudflared passa no Vitest (1/1); o intervalo do Codex usage passou 3/3 isolado (flake sob carga); o banner no-auth cai no mesmo `useContext` nulo de `tests/unit/request-log-detail-stream.test.ts`, que já existe no tip, por causa do React duplicado em `node_modules/node_modules` desta worktree.

O file-size do board ainda vê o teto antigo de `gateways.ts` (já corrigido em cheaper-inference#15679) e o crescimento próprio desta onda em RoutingTab, auth, responseSanitizer, search, proxyFetch e stream. Esse rebaseline entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @HouMinXi.
…#15680)

Follow-up da onda 2. Seis arquivos que já estavam acima do teto cresceram com o squash dos 26 PRs de @HouMinXi. O teto acompanha o tamanho medido com `split("\n").length` no tip `ef3b71c68778`:

- `RoutingTab.tsx` 1618 → 1678
- `auth.ts` 3640 → 3642
- `responseSanitizer.ts` 1204 → 1210
- `search.ts` 1789 → 1805
- `proxyFetch.ts` 1404 → 1405
- `stream.ts` 3298 → 3313

`gateways.ts` permanece em 1547 (cheaper-inference#15679). `node scripts/check/check-file-size.mjs` neste branch: OK.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).
… PR base sha, integration port race (cheaper-inference#15590)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…r-inference#15298)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…#15296)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…eaper-inference#15607)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…map derivation (cheaper-inference#15601)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
… row (cheaper-inference#15613)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
cheaper-inference#15609)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…erence#15614)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…inference#15591)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…e catalogs (cheaper-inference#15599)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…ference#15346)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…thrown save (cheaper-inference#15600)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
cheaper-inference#15583)

Onda 3 (woodsonl) validada num único board em `.claude/worktrees/batch-w3` sobre `origin/release/v3.8.52` (`4f4c983347b9`), 27 PRs, superfícies protegidas 0.

Evidência: `typecheck:core` limpo. i18n drift limpo no board. changelog-integrity ok. file-size ok (170 congelados). complexity 2975/3218 e cognitive-complexity 1357/1437 dentro do baseline. node:test focado: 1868 passaram, 0 falharam. Vitest da UI: 150 passaram em 12 arquivos. Os 38 do RTK caem no `useCallback` nulo de `node_modules/node_modules/react` via zustand, o mesmo React duplicado desta worktree. Onde dois PRs mexiam no mesmo save, o board ficou com os dois comportamentos: escrita parcial de engine por id e a fila/resync do PR que entrou depois.

O hash de `.i18n-state.json` do guia de quality-gates entra no follow-up, fora do squash.

⚠️ base-red inherited: cheaper-inference#15306 (timeouts de suíte no tip, não neste diff).

Obrigado, @woodsonl.
…release

The wave-3 board already validated this overlap. This commit is that resolution.
@diegosouzapw
diegosouzapw merged commit 80a6b73 into cheaper-inference:release/v3.8.52 Oct 6, 2026
5 of 9 checks passed
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.

6 participants