Repository navigation
Conversation
Slice 10 of the re-landed OOM work. Bounds the unbounded accumulators in the provider rate-limit fetchers. - Auth filesystem operations share one read per path, with caps on retained entries, coalesced waiters, path bytes, and the WSL wait queue. WSL reads serialize by distro so a few disconnected distros cannot occupy libuv's filesystem pool. - Gemini CLI OAuth extraction bounds the source read, package.json read, and the bundle-directory scan by entries, files, and aggregate bytes. - Codex RPC drops a run once one unterminated stdout line exceeds 4 MiB. - Hidden rate-limit PTYs are capped and torn down on overflow; PTY diagnostic output retains a bounded tail detached from the oversized chunk. - Provider JSON responses read through the shared bounded-response helper. Every bound is covered by a test asserting the literal ceiling, so raising a constant fails the suite rather than silently buffering more.
The rate-limit fetchers import readIntegrationCredentialFileText and readIntegrationCredentialFileSyncText, but the source module was never brought into the slice, so those exports did not exist. Adds them along with the 1 MiB read ceiling they wrap, plus tests asserting the literal cap in both the sync and async readers.
OrcaWin
marked this pull request as draft
October 27, 2026 09:44
Collaborator
|
Moving this PR to draft because it has been untouched for more than 80 days (latest recorded PR activity or commit timestamp: 2026-07-28T05:02:39Z; checked on 2026-10-27). This keeps the review queue focused on active work while preserving the proposal. Please mark it ready for review when work resumes. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 10 of the re-landed OOM work (#10179, reverted in #10255 for size). Based on
oom-slice-9-markdown(#10990).ELI5
Orca shows how much of your usage quota each AI provider has left. To find out, it reads credential files, calls provider APIs, and — when there's no API for it — spawns a hidden terminal and scrapes the output.
Every one of those paths accumulated without a ceiling:
This puts a ceiling on each.
What changed
Shared, bounded auth reads. One read is now shared per credential path instead of one per caller, with ceilings on retained entries, coalesced waiters, and path length:
WSL reads serialize by normalized distro, which folds
wsl$/wsl.localhostand case aliases together. Healthy local reads never enter this queue.Bounded Gemini CLI credential discovery. Newer Gemini CLI versions ship no
oauth2.js, so Orca scans the bundle directory as a fallback. That scan now stops at 4,096 entries, 512.jsfiles, or 128 MiB inspected — whichever comes first — and the directory handle is closed even when a read throws. Source reads cap at 32 MiB andpackage.jsonreads at 1 MiB.Bounded Codex RPC lines. A run is dropped once a single unterminated stdout line would exceed 4 MiB, rather than buffering until the process dies.
Bounded hidden PTYs. At most 16 hidden rate-limit PTYs may be active; an overflow attempt is torn down immediately and raises a typed error. Scraped output retains only a bounded tail, copied through a round trip so the retained string doesn't pin the much larger chunk it was sliced from.
Bounded provider JSON. Provider responses go through the shared bounded-response helper instead of
await response.json(). Credential files themselves read through a 1 MiB ceiling.User-facing changes
I looked specifically for behavior changes a user could notice. There are none. Every ceiling here sits far above real usage:
Below those ceilings behavior is unchanged. Above them the failure is a typed error and a
status: 'error'rate-limit result — the same shape the UI already handles for an unreachable provider — rather than a hang or a crash.The WSL serialization is the one case where timing changes: two credential reads on different disconnected distros now run one after another instead of together. Both were going to hang regardless; this stops them consuming the filesystem threadpool that the rest of the app shares.
Proof the bounds actually hold
Every constant was rewritten to
Number.MAX_SAFE_INTEGERand the suite re-run serially, with the baseline sampled twice and intersected so a load-sensitive flake can't be mistaken for a kill. A bound whose removal leaves the suite green isn't proven — it's decoration.MAX_QUEUED_WSL_AUTH_OPERATIONSMAX_CONCURRENT_WSL_AUTH_OPERATIONSMAX_AUTH_FILESYSTEM_OPERATION_WAITERSMAX_AUTH_FILESYSTEM_OPERATION_PATH_BYTESMAX_AUTH_FILESYSTEM_REGISTRY_ENTRIESMAX_GEMINI_CLI_OAUTH_SOURCE_BYTESMAX_GEMINI_CLI_PACKAGE_JSON_BYTESMAX_GEMINI_CLI_BUNDLE_ENTRIESMAX_GEMINI_CLI_BUNDLE_FILESMAX_GEMINI_CLI_BUNDLE_BYTESMAX_RPC_RESPONSE_LINE_BYTESMAX_ACTIVE_HIDDEN_RATE_LIMIT_PTYSMAX_INTEGRATION_CREDENTIAL_FILE_BYTES8 of these survived the first pass, and the cause is worth stating because it recurred from slice 9. Tests that seed state relative to the constant under test (
Array.from({ length: MAX_ENTRIES })) pass at any constant value. Worse, atMAX_SAFE_INTEGERsome of them fail withRangeErroror an OOM'd worker — which looks like a kill while proving nothing about the bound. Every test now asserts against the literal ceiling (128, 256, 64 KiB, 4,096, 512, 16), so raising a constant fails the suite.The Gemini extractor had no test file at all — it was mocked out at the module boundary everywhere it appeared. Its five bounds are now covered directly.
One bound was deleted rather than tested.
MAX_AUTH_FILESYSTEM_REGISTRY_PATH_BYTES(8 MiB aggregate) is exactly 128 × 64 KiB — the entry count times the per-path ceiling. It cannot bind before those two do. Rather than write a test for an unreachable branch, I removed the constant and its byte accounting.Proof of no regressions
src/relay/agent-exec-handler.test.tsare pre-existing — I confirmed viagit stashthat they fail identically on the base commit.worktree-logic×4,worktree-metadata-merge×1,worktree-name-suggestions.test×1).it(count of all 13 touched test files against their previous versions: net +24 tests, none lost.grok-auth.test.tslooks heavily rewritten in the diff, but that's mock rewiring for the bounded reader — the same 6 tests remain.A real defect, caught by CI and fixed. The first push failed typecheck: six fetchers import
readIntegrationCredentialFileText/readIntegrationCredentialFileSyncText, but I had taken the importers without the module that defines them — the revert had removed those exports. My local typecheck had run before those edits were staged, so it passed against a stale tree; CI caught it honestly. Fixed in0336ea4b4cby restoring the module with its 1 MiB read ceiling, plus tests for both readers. The lesson generalizes: taking a file from the reverted branch means checking what it imports, not just what it changes.Four revert hazards caught during assembly. Files that show
0/0against the merge base are not safe to take wholesale from the reverted branch — doing so silently reverts fixes that shipped on main after the branch point. Restored toHEADand re-applied by hand:service.ts/service.test.ts— would have reverted a weekly-only Codex fix and deleted 2 tests.claude-pty-reset-parser.ts— a pure revert deleting 24-hour reset parsing and box-glyph stripping (main: 4 tests, branch: 0).codex-fetcher-pty-settle.test.ts— deleted 223 lines including a shipped test.codex-fetcher.ts— genuine OOM work mixed with a revert of the PTY status-nudge timings. Rebuilt fromHEADwith only the OOM changes applied.