From 44cb226b4046277e31b4d830eb8ff6aca2f610c0 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Fri, 28 Aug 2026 09:40:13 -0300 Subject: [PATCH] fix(quality): ratchet-bank verifier rejects object-valued notes (#11892) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recreated from #11702 (MumuTW) onto the current release/v3.8.51 — fixes the object-note comparator bug that has silently blocked the automated ratchet-bank lane since 2026-08-11; 24/24 focused tests + file-size gate green on this tip. Thanks for tracking this down! --- .../fixes/11702-ratchet-bank-object-notes.md | 1 + config/quality/file-size-baseline.json | 112 +++++++++++------- scripts/quality/verify-ratchet-bank.mjs | 8 +- tests/unit/verify-ratchet-bank.test.ts | 21 ++++ 4 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 changelog.d/fixes/11702-ratchet-bank-object-notes.md diff --git a/changelog.d/fixes/11702-ratchet-bank-object-notes.md b/changelog.d/fixes/11702-ratchet-bank-object-notes.md new file mode 100644 index 0000000000..a9cfb0cd72 --- /dev/null +++ b/changelog.d/fixes/11702-ratchet-bank-object-notes.md @@ -0,0 +1 @@ +- Compare `_rebaseline_*` notes structurally in the ratchet-bank verifier so an object-valued note no longer reports itself as rewritten on an unmodified tree — the nightly `bank-ratchet-shrinks` lane had been aborting on every run since 2026-08-11, leaving 41,672 lines of earned file-size shrinks unbanked (#11702). diff --git a/config/quality/file-size-baseline.json b/config/quality/file-size-baseline.json index fa0dd091b3..d8c277307a 100644 --- a/config/quality/file-size-baseline.json +++ b/config/quality/file-size-baseline.json @@ -181,8 +181,6 @@ "cap": 1000, "testCap": 1000, "testFrozen": { - "tests/unit/adobe-firefly.test.ts": 1477, - "tests/unit/reasoning-cache.test.ts": 1346, "_rebaseline_2026_06_27_5193_antigravity_test": "#5193 own test growth: oauth-providers-config.test.ts 870->873 (+3: antigravity projectId assertion + 50ms tick for the now fire-and-forget onboarding, matching the no-PKCE/no-openid flow).", "_rebaseline_2026_07_02_5928_base_red": "web-cookie-providers-new.test.ts 845->850: #5928 (test(security) Kimi Web URL host parse, CodeQL #689) grew the file +5 lines and merged into release/v3.8.44 WITHOUT rebaselining, leaving a fast-gates base-red that blocked every subsequent PR->release. Test growth is legitimate (a security regression test); maintainer absorbs the drift here. Frozen at 850.", "_rebaseline_2026_07_09_6126_clinepass_dualauth": "#6126 (ClinePass dual-auth) own test growth: oauth-providers-config.test.ts 842->845 (+3: clinepass key/config/required-fields entries reusing the Cline WorkOS flow config, needed after registering clinepass in the oauth.ts PROVIDERS enum).", @@ -192,43 +190,64 @@ "_rebaseline_2026_07_22_8213_combo_config_cooldown_wait_tests": "PR #8213 (hartmark, fix/gemini-tpm-quota-cooldown-wait) own growth: tests/unit/combo-config.test.ts 880->940 (+60, entirely this PR's diff — testFrozen add covering isComboCooldownWaitEligible (gating cooldown-wait to auto/quota-share strategies with the feature enabled) and resolveComboTargetTimeoutMsForCombo (raising the per-target timeout floor to cover the cooldown-wait budget + buffer for eligible strategies, fixing the 120s default cutting off a 130s wait early and returning a synthetic 524)). Covered by the new assertions themselves.", "_rebaseline_2026_07_23_8122_codex_image_edits": "#8122 (@xiaoyaner0201) own growth: tests/unit/image-generation-handler.test.ts 2019->2029 (+10) — new coverage for Codex reference image edits (POST /v1/images/edits) plus the sanitizeImageProviderError/redactSensitiveErrorText hardening it introduces. Test-only growth at the existing handler test file.", "_rebaseline_2026_07_25_8510_adobe_firefly_reference_images_tests": "#8510 (artickc, feat/adobe-firefly-reference-images) own test growth: tests/unit/adobe-firefly.test.ts 711->871 (+159, entirely this PR's diff — new referenceBlobs upload/dispatch coverage for handleAdobeFireflyImageGeneration, resolveAdobeSourceImageIds, and the storage-upload wire contract). Route-level /v1/images/edits coverage (credentials/rate-limit/4-ref-cap branches added to route.ts) lives in the new tests/unit/8510-adobe-firefly-edits-route.test.ts instead of growing this file further.", + "_rebaseline_2026_08_24_video_bridge_fu01_fu03_fu04_result_cache_tests": "PRs #11362 (FU-01 cache hardening) + #11382 (FU-03 visual dedup policy identity) + #11383 (FU-04 focused analysis mode) own test growth: videoBridgeResultCache.test.ts <1000->1040, +40 (sum of three stacked PRs boarded together in the same merge-batch, each adding its own cache-identity assertions on the shared result-cache seam). Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).", "_rebaseline_basered_codebuddy_cn": "Base-red fix (#4664 CodeBuddy CN): oauth-providers-config.test.ts 867->870 (+3) to align the EXPECTED provider list/config with the codebuddy-cn provider that #4664 added to the registry without updating this test (it asserts 'exactly once').", "_rebaseline_pr4613_compatible_provider_groups": "Reconcile #4613 already-merged growth: providers-page-utils.test.ts 1004->1052 (+48, buildCompatibleProviderGroups partition unit test). Fast-gate PR->release does not run check:file-size, so this surfaced post-merge.", - "tests/integration/chat-pipeline.test.ts": 2077, - "tests/integration/chatcore-compression-integration.test.ts": 1448, - "tests/unit/account-fallback-service.test.ts": 2032, - "tests/unit/batch_api.test.ts": 1721, - "tests/unit/cc-compatible-provider.test.ts": 1582, - "tests/unit/chatcore-translation-paths.test.ts": 3739, - "tests/unit/combo-routing-engine.test.ts": 4494, - "tests/unit/db-migration-runner.test.ts": 1949, - "tests/unit/deepseek-web.test.ts": 1420, - "tests/unit/executor-codex.test.ts": 1741, - "tests/unit/executor-default-base.test.ts": 1975, - "tests/unit/grok-web.test.ts": 3168, - "tests/unit/image-generation-handler.test.ts": 2638, - "tests/unit/model-sync-route.test.ts": 1321, - "tests/unit/models-catalog-route.test.ts": 2127, - "tests/unit/perplexity-web.test.ts": 1762, - "tests/unit/provider-models-route.test.ts": 2323, - "tests/unit/provider-validation-specialty.test.ts": 3880, - "tests/unit/providers-page-utils.test.ts": 1438, - "tests/unit/response-sanitizer.test.ts": 1382, - "tests/unit/route-edge-coverage.test.ts": 1613, - "tests/unit/search-handler-extended.test.ts": 1392, - "tests/unit/sse-auth.test.ts": 2093, - "tests/unit/stream-utils.test.ts": 3178, - "tests/unit/token-refresh-service.test.ts": 1791, - "tests/unit/translator-openai-responses-req.test.ts": 1552, - "tests/unit/translator-openai-to-gemini.test.ts": 2109, - "tests/unit/translator-openai-to-kiro.test.ts": 1658, - "tests/unit/translator-resp-gemini-to-openai.test.ts": 1604, - "tests/unit/usage-service-hardening.test.ts": 1928, - "tests/unit/vscode-token-routes.test.ts": 1633, - "tests/unit/executor-antigravity.test.ts": 1427, + "tests/integration/chat-pipeline.test.ts": 1604, + "tests/integration/chatcore-compression-integration.test.ts": 1114, + "tests/integration/skills-pipeline.test.ts": 1006, + "tests/unit/account-fallback-service.test.ts": 2008, + "tests/unit/adobe-firefly.test.ts": 1136, + "tests/unit/batch_api.test.ts": 1324, + "tests/unit/cc-compatible-provider.test.ts": 1225, + "tests/unit/chatcore-translation-paths.test.ts": 3446, + "tests/unit/combo-routing-engine.test.ts": 3625, + "tests/unit/db-migration-runner.test.ts": 1509, + "tests/unit/deepseek-web.test.ts": 1141, + "tests/unit/executor-antigravity.test.ts": 1103, + "tests/unit/executor-codex.test.ts": 1467, + "tests/unit/executor-default-base.test.ts": 1632, + "tests/unit/grok-web.test.ts": 2437, + "tests/unit/image-generation-handler.test.ts": 2083, + "tests/unit/model-sync-route.test.ts": 1033, + "tests/unit/models-catalog-route.test.ts": 1652, + "tests/unit/perplexity-web.test.ts": 1384, + "tests/unit/provider-models-route.test.ts": 1783, + "tests/unit/provider-validation-specialty.test.ts": 2912, + "tests/unit/providers-page-utils.test.ts": 1149, + "tests/unit/response-sanitizer.test.ts": 1089, + "tests/unit/route-edge-coverage.test.ts": 1241, + "tests/unit/search-handler-extended.test.ts": 1070, + "tests/unit/sse-auth.test.ts": 1698, + "tests/unit/stream-utils.test.ts": 2512, + "tests/unit/token-refresh-service.test.ts": 1407, + "tests/unit/translator-openai-responses-req.test.ts": 1470, + "tests/unit/translator-openai-to-gemini.test.ts": 1625, + "tests/unit/translator-openai-to-kiro.test.ts": 1275, + "tests/unit/translator-resp-gemini-to-openai.test.ts": 1234, + "tests/unit/usage-service-hardening.test.ts": 1485, + "tests/unit/vscode-token-routes.test.ts": 1259, "tests/unit/guardrails/videoBridgeResultCache.test.ts": 1040, - "_rebaseline_2026_08_24_video_bridge_fu01_fu03_fu04_result_cache_tests": "PRs #11362 (FU-01 cache hardening) + #11382 (FU-03 visual dedup policy identity) + #11383 (FU-04 focused analysis mode) own test growth: videoBridgeResultCache.test.ts <1000->1040, +40 (sum of three stacked PRs boarded together in the same merge-batch, each adding its own cache-identity assertions on the shared result-cache seam). Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).", - "tests/integration/skills-pipeline.test.ts": 1010 + "tests/unit/image-generation-handler.test.ts": 2083, + "tests/unit/model-sync-route.test.ts": 1033, + "tests/unit/models-catalog-route.test.ts": 1652, + "tests/unit/perplexity-web.test.ts": 1384, + "tests/unit/provider-models-route.test.ts": 1783, + "tests/unit/provider-validation-specialty.test.ts": 3070, + "tests/unit/providers-page-utils.test.ts": 1149, + "tests/unit/reasoning-cache.test.ts": 1291, + "tests/unit/response-sanitizer.test.ts": 1089, + "tests/unit/route-edge-coverage.test.ts": 1241, + "tests/unit/search-handler-extended.test.ts": 1070, + "tests/unit/sse-auth.test.ts": 1698, + "tests/unit/stream-utils.test.ts": 2512, + "tests/unit/token-refresh-service.test.ts": 1407, + "tests/unit/translator-openai-responses-req.test.ts": 1470, + "tests/unit/translator-openai-to-gemini.test.ts": 1625, + "tests/unit/translator-openai-to-kiro.test.ts": 1275, + "tests/unit/translator-resp-gemini-to-openai.test.ts": 1234, + "tests/unit/usage-service-hardening.test.ts": 1485, + "tests/unit/vscode-token-routes.test.ts": 1259 }, "_rebaseline_2026_06_09": "Re-baseline consciente pre-release v3.8.19: 9 arquivos cresceram durante o ciclo (features mergeadas: RequestLoggerV2 +281 request-logger rework, stream +101, combo +73, chatCore +45, catalog +32 fable-5/catalog-flag, callLogs +4, accountFallback +2, usageHistory novo 840) + core.ts +7 (fix resetAllDbModuleState, PR 3536). A catraca segue valendo destes valores — proximo crescimento falha. Decisao: encolher (esp. RequestLoggerV2/chatCore) e a issue #3501 ficam para o ciclo seguinte.", "_rebaseline_2026_06_11_phase1f": "Phase 1f (#3501): ProviderDetailPageClient.tsx 4948→4062 (-886 LOC); 3 novos hooks extraídos. useProviderConnections.ts=954 acima do cap=800 — justificado: extração direta do god-component (zero lógica nova), própria redução do cliente supera o custo. useProviderSettings.ts=263 e useProviderModels.ts=154 já abaixo do cap.", @@ -308,9 +327,6 @@ "_rebaseline_2026_07_27_3850_relax_filesize_cap": "OWNER-APPROVED TEMPORARY relax for v3.8.50-3.8.54 PREPARE phase (docs/ROADMAP.md). cap 800->900 (+100), testCap 800->900 (+100). Targets: decompose-existing-frozen unchanged (frozen still only-shrink); this only relaxes the cap for NEW files in the decompose/extract-while-PREPARE phase (.51='executor registry in-place' and .52='combo.ts decomposition' create new leaf modules above 800). RE-TIGHTENING MANDATORY in v3.8.51: cap target 850 = 850 once decomposition wave stabilizes. SUPERSEDED by _rebaseline_2026_07_27_3850_relax_filesize_cap_v2_20pct (v1 +20% buffer) — retained for audit. Tracked via same roadmap issue.", "_rebaseline_2026_07_27_v3849_train1h": "Merge-train 1H (31 PRs) — owner-approved 2026-07-27. Two distinct causes, kept separate on purpose: (1) GENUINE irreducible growth at existing chokepoints — providerLimits/auth (#8632 Kimi quota-reset recovery), rateLimitManager (#8616 idle wedged limiters), models-catalog-route.test (#8610 OpenCode Go effort aliases); (2) COLLISION with #8585, which banked shrinks measured on the pre-train release tip while 30 sibling PRs in the SAME train grew those files again — chat/accountFallback (#8628), chatCore (#8613), videoGeneration (#8581), imageGeneration. The zero-headroom frozen entries cannot absorb either. Ceilings re-pinned to the post-merge tip; #8612 (also in this train) automates shrink-banking so this self-inflicted drift stops recurring. Detail: src/lib/usage/providerLimits.ts 1006->1013 (#8632); src/sse/services/auth.ts 2492->2508 (#8632); open-sse/services/rateLimitManager.ts 1014->1060 (#8616); src/sse/handlers/chat.ts 1842->1845 (#8628); open-sse/handlers/chatCore.ts 4939->4955 (#8613); open-sse/handlers/imageGeneration.ts 3100->3101 ((sem PR — teto do #8585)); open-sse/handlers/videoGeneration.ts 1038->1063 (#8581); open-sse/services/accountFallback.ts 1965->1966 (#8628); tests/unit/models-catalog-route.test.ts 1608->1636 (#8610)", "frozen": { - "_rebaseline_2026_08_20_10878_10799_provider_health_probes": "PRs #10878 (unsupported OpenAI-like validation probes stay neutral) + #10799 (preserve credential health on inconclusive NVIDIA-timeout/Antigravity-400 probes) own growth: src/app/api/providers/[id]/test/route.ts 946->1025 (+79, sum of both boarded together). Both add narrowly-scoped classification branches at the existing test-route dispatch chokepoint (unsupported-capability skip, credential-inconclusive detection) rather than new files, mirroring the prior 2026_06_27_5193 rebaseline of the same file. Covered by tests/unit/provider-validation-unsupported-neutral.test.ts + tests/unit/provider-health-inconclusive-probes.test.ts.", - "src/app/api/providers/[id]/test/route.ts": 1262, - "_rebaseline_2026_08_23_11141_oauth_400_recovery": "PR #11141 (HouMinXi) own growth: test/route.ts 1025->1215 (+190, the reactive-400 recovery path — a fully rebuilt probe for refresh+retry on refreshable non-rotating connections, with inconclusive-status preservation and rotating-provider exclusion; all growth is the new probe builder + guards at the existing test-route dispatch, extraction would split the retry flow mid-logic). Covered by tests/unit/oauth-400-recovery.test.ts (8, bug-injection proof). Owner pre-authorized baseline bumps 2026-08-22.", "_rebaseline_2026_06_22_4644_deepseek_web_tools": "PR #4644 (BugsBag/robust deepseek-web tool-call parsing): open-sse/executors/deepseek-web.ts 1117->1125 (+8). The new agentic tool-call path emits surrounding text + reasoning before tool_calls and swaps to the dedicated deepseekWebTools.ts parser; the +8 lines are cohesive wiring at the existing transformSSE chokepoint (the parser itself lives in the new deepseekWebTools.ts file, already under cap). The PR's own fast-gate (PR->release) does not run check:file-size, so this surfaced only at release reconcile. Covered by tests/unit/deepseek-web-tools-variants.test.ts + deepseek-web-tools-execute.test.ts.", "_rebaseline_2026_06_23_4712_deepseek_web_tool_results": "PR for #4712 (deepseek-web drops role:tool): open-sse/executors/deepseek-web.ts 1125->1148 (+23). messagesToPrompt() now folds role:\"tool\" results into the single-prompt transcript (recovering the tool name from the preceding assistant tool_calls by tool_call_id) instead of silently dropping them; the lines are cohesive wiring inside the existing function. Covered by tests/unit/deepseek-web-tool-result-prompt-4712.test.ts.", "_rebaseline_2026_06_24_headroom_strategy": "Headroom-aware connection selection (dario technique): combo.ts 3168->3180 (+12 = a new `else if (strategy === \"headroom\")` dispatch branch in handleComboChat that delegates to orderTargetsByHeadroom + its log line, plus the import). The actual logic lives OUT of the god-file: the pure ranker rankByHeadroom/computeHeadroom is the new leaf open-sse/services/combo/headroomRanking.ts (91 LOC, 1009 (+4, heavyweight admission leases now increment the SIGTERM drain counter and releaseChatAdmissionWhenDone holds it for the SSE lifetime — closes #11015; +4 are the lease/drain wiring lines at the existing admission chokepoint). Covered by tests/unit/chat-body-admission.test.ts heavyweight-lease cases. Owner pre-authorized baseline bumps 2026-08-22.", "_rebaseline_2026_08_20_10668_tabitoken_gateway": "#10668 (yawar-aquil) own catalog growth: src/shared/constants/providers/apikey/gateways.ts 1268->1283 (+15, entirely this PR diff -- one new tabitoken gateway entry, data lines only; base moved from 1255 to 1268 via other merges since the PR forked). Not combination drift: reproducible on the PR branch alone, so the WS5.5 release-captain rule does not apply. Extraction is not available -- the file is pure data (own header: \"Pure data; merged by apikey/index.ts via spread\") and already split into 6 family files under apikey/. Same precedent as _rebaseline_2026_08_14_imagetotext_servicekinds (#10275/#10291, gateways.ts 1250->1255, data lines only) and _rebaseline_2026_08_11_v3850_merge_storm_provider_registry (owner-authorized for this same file).", - "open-sse/executors/commandCode.ts": 1059, + "_rebaseline_2026_08_20_10878_10799_provider_health_probes": "PRs #10878 (unsupported OpenAI-like validation probes stay neutral) + #10799 (preserve credential health on inconclusive NVIDIA-timeout/Antigravity-400 probes) own growth: src/app/api/providers/[id]/test/route.ts 946->1025 (+79, sum of both boarded together). Both add narrowly-scoped classification branches at the existing test-route dispatch chokepoint (unsupported-capability skip, credential-inconclusive detection) rather than new files, mirroring the prior 2026_06_27_5193 rebaseline of the same file. Covered by tests/unit/provider-validation-unsupported-neutral.test.ts + tests/unit/provider-health-inconclusive-probes.test.ts.", "_rebaseline_2026_08_21_10859_vision_bridge_catalog": "#10859 own growth (Vision Bridge fixes #10808/#10809): src/lib/modelCapabilities.ts 1006->1016 (+10, cmd/gpt-5.3-codex* text-only capability resolution) and open-sse/executors/commandCode.ts 988->1023 (+35, Command Code wire-model normalization for bare ids + reasoning field fallback for opencode-routed gateways). Cohesive bug fixes at the existing capability-resolution / executor chokepoints; not extractable mid-fix. Covered by tests/unit/model-capabilities-command-code-codex-textonly-10703.test.ts, tests/unit/command-code-vision.test.ts, tests/unit/opencode-mimo-reasoning-details-nonstream.test.ts. Pushed directly to release (own-session miss: the original rebaseline was made in a throwaway validation worktree and never landed on the PR branch or the release before merge).", "_rebaseline_2026_08_21_10907_sticky_pin_clear": "#10907 own growth: open-sse/executors/commandCode.ts 1023->1038 (+15, effort-suffix sanitization threading for the sticky-pin-clear fix). Cohesive change at the existing executor chokepoint. Covered by tests/unit/command-code-executor.test.ts.", "_rebaseline_2026_08_21_10986_reasoning_only_content": "#10986 own growth: open-sse/executors/commandCode.ts 1038->1059 (+21, reasoning-only content fallback — when upstream emits only reasoning-delta events and never a text-delta, surface the reasoning text as message.content in createJsonResponse and emit a synthetic content delta in createStreamResponse). Cohesive bug fix at the existing executor chokepoint (mirrors precedent style of #10907/#10859). Covered by tests/unit/command-code-executor.test.ts (2 new cases: non-stream + streaming).", + "_rebaseline_2026_08_21_11034_effort_variants": "DRIFT do tip (base-red #9985): modelCapabilities.ts 1016->1072 (+56) acumulado por PRs ja mergeadas no release/v3.8.50 — principalmente #11034 (resolve effort-variant capabilities a partir do modelo base), alem de #10963/#11040/#10987 growth dos catalogos. Tip puro ficou vermelho neste gate; rebaseline no tip por push direto (owner pre-autorizou crescimento legitimo). Nao tocou no arquivo da #11038.", "_rebaseline_2026_08_21_11069_m365_har_import": "#11069 own growth: AddApiKeyModal.tsx 1073->1080 (+7 = Import .har file button for the copilot-m365-web credential modal — M365 is the only provider whose credential (access_token+chathubPath) must be extracted from a DevTools HAR WebSocket URL, added as a new modal affordance). Cohesive UI at the existing modal chokepoint; not extractable. Covered by tests/unit/m365-har-import*.test.ts.", + "_rebaseline_2026_08_22_11020_sigterm_drain": "PR #11020 (RaviTharuma) own growth: chatBodyAdmission.ts 1005->1009 (+4, heavyweight admission leases now increment the SIGTERM drain counter and releaseChatAdmissionWhenDone holds it for the SSE lifetime — closes #11015; +4 are the lease/drain wiring lines at the existing admission chokepoint). Covered by tests/unit/chat-body-admission.test.ts heavyweight-lease cases. Owner pre-authorized baseline bumps 2026-08-22.", + "_rebaseline_2026_08_22_11084_ccr_caller_gate": "PR #11084 (HouMinXi) own growth: open-sse/services/compression/engines/ccr/index.ts 1000->1024 (first listing — the engine was unlisted and drifted just over the 1000 cap; +24 are the callerSupportsCcrRetrieve gate that skips replacement entirely for callers without the retrieve tool, closing the stranded-prompt incident measured in production). Covered by tests/unit/compression/ccr-non-mcp-full-prompt-loss-7746.test.ts. Owner pre-authorized baseline bumps 2026-08-22.", + "_rebaseline_2026_08_22_11113_purify_system_first": "PR #11113 (ggdayup) own growth: open-sse/services/contextManager.ts 1000->1001 (+1, purifyHistory merges the compression notice into the leading system message instead of splicing a second one mid-array — live-confirmed TokenRouter 400s; the +1 is the merge-into-leading branch, not extractable). Covered by tests/unit/context-manager-purify-system-first.test.ts. Owner pre-authorized baseline bumps 2026-08-22.", + "_rebaseline_2026_08_22_11156_enter_check_disabled": "PR #11156 (rqzbeh) own growth: AddApiKeyModal.tsx 1080->1082 (+2, Enter keydown handler now mirrors the isCheckDisabled condition — owner-requested post-merge polish from #11056; the rest of the diff is Prettier reflow). Covered by tests/unit/ui/add-api-key-modal-enter-key.test.tsx (jsdom render test, Enter dispatch assertions).", + "_rebaseline_2026_08_23_11141_oauth_400_recovery": "PR #11141 (HouMinXi) own growth: test/route.ts 1025->1215 (+190, the reactive-400 recovery path — a fully rebuilt probe for refresh+retry on refreshable non-rotating connections, with inconclusive-status preservation and rotating-provider exclusion; all growth is the new probe builder + guards at the existing test-route dispatch, extraction would split the retry flow mid-logic). Covered by tests/unit/oauth-400-recovery.test.ts (8, bug-injection proof). Owner pre-authorized baseline bumps 2026-08-22.", + "_rebaseline_2026_08_23_11177_dns_retry_classification": "PR #11177 (rqzbeh) own growth: proxyFetch.ts 1239->1244 (+5, EAI_AGAIN/ENOTFOUND/ETIMEDOUT join the retryable dispatcher classification alongside ECONNREFUSED — bounded socket retries for transient DNS failures, part of the #10443 Hermes→Antigravity stream-drop fixes). Covered by tests/unit/proxy-fetch-dns-retry-10443.test.ts. Owner pre-authorized baseline bumps 2026-08-22.", + "_rebaseline_2026_08_23_11186_synced_inventory_routing": "PR #11186 (pacocartones) own growth: src/sse/services/auth.ts 3260->3337 (+77, loadAdvertisedModelsForSelfHostedConnections + the modelNotAdvertised candidate-filter predicate — pins chat routing to the connection whose synced inventory actually advertises the model, fixing spurious model-not-found on multi-host self-hosted setups; at the existing credential-selection chokepoint, not extractable without splitting the selection flow). Covered by tests/unit/chat-routing-synced-inventory-11089.test.ts. Owner pre-authorized baseline bumps 2026-08-22.", + "_rebaseline_2026_08_23_11207_aws_polly_fields": "PR #11207 (rafacpti23, draft) own growth: AddApiKeyModal.tsx 1082->1173 (+91, AWS SigV4 credential fields for aws-polly — Access Key ID / Region / optional Session Token blocks with providerText i18n labels, at the existing per-provider form-section chokepoint; the file is the known god-modal with repeated dated rebaselines). Covered by tests/unit/dashboard/aws-polly-connection-modal-fields.test.ts. Owner pre-authorized baseline bumps 2026-08-22.", "_rebaseline_2026_08_23_tip_drift_post_batch0823": "Tip drift after the 2026-08-23 merge wave: chatBodyAdmission.ts 1009->1118 (+109, gate count incl. +1) and auth.ts 3337->3344 (+7), both grown by merges already on origin/release/v3.8.50 (verified identical on the pristine tip) — not by the codex-appserver-hardening PR that carries this bump. Owner pre-authorized baseline bumps 2026-08-22.", "_rebaseline_2026_08_24_11355_cooldown_recovery_guards": "PR #11355 own growth: test/route.ts 1215->1237, +22 (startup crash-recovery guard: clearStaleCrashCooldowns() now parses the persisted rate_limited_until deadline and skips clearing rows still genuinely in the future, instead of clearing every non-terminal cooldown unconditionally). Cohesive fix at the existing test-route dispatch chokepoint alongside the #11141 probe builder. Covered by tests/unit/startup-stale-cooldown-recovery.test.ts + tests/unit/repro-zai-cooldown-cleared-by-connection-test.test.ts.", - "src/lib/guardrails/videoBridgeRuntime.ts": 1009, + "_rebaseline_2026_08_24_lasterror_provider_error_detail": "PR (ntdat812) own growth: src/sse/services/auth.ts 3344->3346 (+2). One line is the import of describeUpstreamFailure from @/shared/utils/upstreamError, which replaces the string-only collapse `typeof errorText === \"string\" ? errorText.slice(0, 100) : \"Provider error\"` at the single markAccountUnavailable chokepoint (net 0 lines there) — the logic itself lives in upstreamError.ts, next to the extractErrorMessage it reuses, so nothing else moved into this file. The second line is the repo's own lint-staged prettier pass splitting a pre-existing two-statements-on-one-line at getProviderCredentials (`invalidateManagedLease(...); log.warn(...)`); it re-applies on any commit that touches this file, so it is not separable from the change. Covered by tests/unit/provider-error-detail-lastError.test.ts.", "_rebaseline_2026_08_24_video_bridge_fu02_fu07_sampler": "PRs #11344 (FU-02 one-frame scene-aware determinism) + #11381 (FU-07 opt-in segment_aware structural sampling) own growth: videoBridgeRuntime.ts <1000->1009, +9 (sum of both boarded together in the same merge-batch). #11344 adds the deterministic one-frame midpoint fallback + policyEffective=uniform report at the existing scene_aware seam; #11381 adds the bounded local-only FFmpeg structural pre-analysis pass (scene/freeze/blur/exposure/SI-TI) and its budget-reallocation logic. Covered by tests/unit/guardrails/videoBridgeSampler.test.ts, tests/unit/guardrails/videoBridgeFu07StructuralSampling.test.ts, tests/integration/video-bridge-sampler-ffmpeg.test.ts. Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).", "open-sse/services/autoCombo/virtualFactory.ts": 1138, "_rebaseline_2026_08_28_mergebatch_v3851_qwen_retirement": "/merge-batch 2026-08-28 (v3.8.51): #11713 (Qwen Web retirement) own growth: open-sse/services/autoCombo/virtualFactory.ts 1132->1135 (+3, combining the Designer + Runtime retirement-guard filter into the single runtimeConnections predicate at the existing candidate-pool chokepoint, now excluding Qwen Web alongside Felo Web). Irreducible per-mechanism wiring, additive not a new branch. Covered by tests/unit/virtual-auto-combo.test.ts.", "_rebaseline_2026_08_28_mergebatch_v3851_chatgptweb_retirement": "/merge-batch 2026-08-28 (v3.8.51): #11754 (common ChatGPT Web retirement) own growth: open-sse/services/autoCombo/virtualFactory.ts 1135->1138 (+3, an early `available` connection filter for the retired chatgpt-web/cgpt-web ids applied to both the active and disabled-noauth connection lists, ahead of the existing Designer+Runtime runtimeConnections filter). Irreducible per-mechanism wiring, additive not a new branch. Covered by tests/unit/virtual-auto-combo.test.ts.", "src/lib/cloudflaredTunnel.ts": 1078, - "src/shared/components/RequestLoggerDetail.tsx": 1018 + "src/shared/components/RequestLoggerDetail.tsx": 1018, + "src/app/api/providers/[id]/test/route.ts": 1255, + "src/lib/guardrails/videoBridgeRuntime.ts": 1009, + "_rebaseline_2026_08_28_mergebatch_v3851_ratchet_bank_reconcile": "/merge-batch 2026-08-28 (v3.8.51): boarding #11702 (fix/verify-ratchet-bank object-note comparator) surfaced a large stale `frozen`/`testFrozen` snapshot on PR #11702's own branch (forked before the 08-11 banking outage — see the object-valued `_rebaseline_2026_08_11_v3850_merge_storm_provider_registry` note above, the exact bug #11702 fixes in the verifier) — its conflicting block duplicated ~85 already-tracked files with sizes smaller than the current release tip, and still listed open-sse/executors/chatgpt-web.ts (deleted by the #11754 retirement). Resolved by re-measuring every file in the union of both sides directly on the boarded tree (split(\"\\n\").length, matching check-file-size.mjs) rather than trusting either stale snapshot; dropped the dead chatgpt-web.ts entry; kept the two genuinely-new entries PR #11702's branch had that this tip did not yet track (src/app/api/providers/[id]/test/route.ts, src/lib/guardrails/videoBridgeRuntime.ts, both re-measured). Same reconciliation applied to the testFrozen block above." }, "_rebaseline_base_2026_08_10_proxyfetch": "Base-red fix (green-prs sweep, issue #9985): open-sse/utils/proxyFetch.ts 1207 > cap 1000 — new proxied-TLS fetch helper introduced by the Fal reference-image work. Owner-authorized quick rebaseline to green; structural slim tracked for v3.9.0.", "_rebaseline_2026_07_27_v3849_train2": "Merge-train 2 (7 PRs) — owner-approved 2026-07-27. Single entry: chatCore.ts 4955->5006 (#8595, Responses multi-turn image compaction before the context hard-reject). Genuine irreducible growth at the existing compaction chokepoint in handleChatCore — the PR adds a last-resort retry against the concrete budget plus the estimateFinalInputTokens helper, both wired at the pre-existing call site rather than a new branch. Covered by tests/unit/8560-responses-image-compaction.test.ts (4 tests).", diff --git a/scripts/quality/verify-ratchet-bank.mjs b/scripts/quality/verify-ratchet-bank.mjs index 73f2089710..5d5c56c9ac 100644 --- a/scripts/quality/verify-ratchet-bank.mjs +++ b/scripts/quality/verify-ratchet-bank.mjs @@ -63,7 +63,13 @@ export function verifyFrozenMap(before = {}, after = {}, label = "frozen") { if (typeof prev !== "number") { // note key if (!has) problems.push(`${label}: note "${key}" was deleted — notes must be preserved`); - else if (after[key] !== prev) + // Structural, not referential. A note whose value is an OBJECT — the + // 2026-08-11 merge-storm entry folded four file→LOC pairs under a single + // note key — is a fresh object on every JSON.parse, so `!==` reported it + // rewritten on an UNMODIFIED tree. That made this verifier exit 1 + // unconditionally, and the nightly bank-ratchet-shrinks job (#8612) aborts + // on non-zero: every shrink since has gone unbanked. + else if (!jsonEqual(after[key], prev)) problems.push(`${label}: note "${key}" was rewritten — notes must be preserved verbatim`); continue; } diff --git a/tests/unit/verify-ratchet-bank.test.ts b/tests/unit/verify-ratchet-bank.test.ts index 540fbeaeed..c851d758f3 100644 --- a/tests/unit/verify-ratchet-bank.test.ts +++ b/tests/unit/verify-ratchet-bank.test.ts @@ -61,6 +61,27 @@ test("rewriting a note is rejected — the notes are the audit trail", () => { assert.match(r.problems[0], /rewritten/); }); +// A note value is not always a string. The 2026-08-11 merge-storm rebaseline +// folded four file→LOC pairs into the value of a single note key, so `frozen` +// carries an OBJECT-valued note. Compared referentially, two structurally equal +// objects off two JSON.parse calls are never the same reference — the verifier +// reported "rewritten" on a tree nobody had touched and exited 1, which made the +// nightly bank-ratchet-shrinks job (#8612) abort on every run. +test("an object-valued note that did not change is not reported as rewritten", () => { + const note = () => ({ "a.tsx": 1062, "b.ts": 1051 }); + const r = verifyFrozenMap({ _rebaseline_x: note() }, { _rebaseline_x: note() }); + assert.deepEqual(r.problems, [], "structurally equal notes must compare equal"); +}); + +test("an object-valued note that DID change is still rejected", () => { + const r = verifyFrozenMap( + { _rebaseline_x: { "a.tsx": 1062 } }, + { _rebaseline_x: { "a.tsx": 9999 } } + ); + assert.equal(r.problems.length, 1); + assert.match(r.problems[0], /rewritten/); +}); + // --- file-size baseline as a whole --- const fsBefore = () => ({