Repository navigation
Conversation
nwparker
force-pushed
the
oom/08-b-mobile-rest
branch
from
July 24, 2026 07:48
918d261 to
7ab6e01
Compare
nwparker
force-pushed
the
oom/09-b-git-worktree-persistence
branch
from
July 24, 2026 07:48
04e4e5d to
4f0bb9e
Compare
nwparker
force-pushed
the
oom/08-b-mobile-rest
branch
from
July 25, 2026 02:21
7ab6e01 to
c63185a
Compare
nwparker
force-pushed
the
oom/09-b-git-worktree-persistence
branch
from
July 25, 2026 02:21
4f0bb9e to
45a6b3b
Compare
nwparker
force-pushed
the
oom/08-b-mobile-rest
branch
from
July 25, 2026 02:39
c63185a to
597a894
Compare
nwparker
force-pushed
the
oom/09-b-git-worktree-persistence
branch
from
July 25, 2026 02:39
45a6b3b to
980b8d8
Compare
nwparker
force-pushed
the
oom/08-b-mobile-rest
branch
from
July 25, 2026 03:10
597a894 to
5a564b1
Compare
nwparker
force-pushed
the
oom/09-b-git-worktree-persistence
branch
from
July 25, 2026 03:10
980b8d8 to
ed0d6de
Compare
Files: 108 applied, 0 deleted (from 6eb70d8) Co-authored-by: Orca <help@stably.ai>
nwparker
force-pushed
the
oom/08-b-mobile-rest
branch
from
July 25, 2026 03:34
5a564b1 to
040229b
Compare
nwparker
force-pushed
the
oom/09-b-git-worktree-persistence
branch
from
July 25, 2026 03:34
ed0d6de to
c54092b
Compare
Contributor
Author
|
Superseded by #10548, which re-scopes this work to the bound-at-ingress doctrine (see #10533 and An audit found the original #10179 scope was ~50x the size of the fix for the crash it targeted, and that bounds had landed ahead of their callers. Every file in these slices was re-adjudicated individually: ingress bounds (transport frames, PTY flow control, on-disk transcripts, parsing, enumeration, media decode, user-keyed accumulators) were kept; interior ceilings behind an already-bounded input were dropped. 1,882 files → 1,155, full suite green, and no No memory protection was lost — only speculation. |
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.
OOM hardening slice 09/29 — bound git/worktree/persistence/repo/usage state
Summary
This slice re-introduces ~40 independent count/byte/depth/concurrency ceilings across git worktree persistence, terminal-history GC, crash reporting, cloud-profile session stores, usage-history scanning, and process/persistence state files. The behaviorally significant change is a new 10MB default output cap on ALL local git commands (previously unbounded unless a caller opted in); everything else sits far above ordinary use.
ELI5
Imagine dozens of buckets in the app that could previously fill up forever and eventually crash it by running out of memory. This change puts a lid on each bucket at a size much bigger than anyone normally uses. The one lid you can actually bump into during normal work is on git: if a single git command spits out more than 10MB of text (a giant diff or log), it now stops with an error instead of risking a crash.
Proof of OOM fix
Regressions
Normal-path (ordinary use, below the new limits): none — behavior is unchanged below the ceilings.
Overload-only (extreme input / sustained backpressure) — intended, documented degradations:
if (options.maxBuffer && ...)), so unbounded output was allowed. Git commands whose combined stdout/stderr exceed 10MB now fail with 'stdout exceeded maxBuffer.' instead of returning the output. This is reachable on large monorepos (hugegit diff, longgit log,git statuswith very many untracked files). (only when: Any git operation not passing its own maxBuffer that produces >10MB of output on a large repo (native, WSL, or SSH). Intended anti-OOM cap and kept in sync with relay MAX_GIT_BUFFER, but a human should confirm 10MB is comfortably above real large-repo command output.)if (options.maxBuffer && ...), leaving this path unbounded). CORRECTION to the prior reviewer: this is NOT a change to 'every local git command'. The mainline execFileCapture path ALREADY appliedoptions.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER(10MB) in BASE (runner.ts:442, constant at :253). spawnCommandCapture is reached ONLY for Windows batch-script shims (isWindowsBatchScript at runner.ts:879 and the Windows .cmd retry at :896) — e.g. gh.cmd/glab.cmd. So the newly-capped surface is Windows-only + batch-shim-only. On macOS/Linux and the normal execFile git path, output was already 10MB-capped in BASE; no change. (only when: On Windows only, a git/gh/glab command that resolves to a batch-script shim, does not pass its own maxBuffer, and emits >10MB combined stdout/stderr. Now fails with 'stdout/stderr exceeded maxBuffer' instead of returning unbounded output.)Build / CI
mainsince the revert; git auto-merges them (no conflict):workspace-space-analysis.ts.Adversarial review
Evidence (git -C ... diff aab1129 6eb70d8 -- src/main/git/runner.ts):
maxBuffer: options.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER(present in BASE, UNCHANGED by the diff). This is the path used by repo-scoped runGit (hugegit diff/git log/git status).const maxBuffer = options.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER(present in BASE; the diff only swaps the accumulation mechanism to GrowingByteBuffer, not the cap).const maxBuffer = options.maxBuffer ?? DEFAULT_GIT_MAX_BUFFER), replacing BASE'sif (options.maxBuffer && stdoutBytes > options.maxBuffer). spawnCommandCapture is reached ONLY from commandExecFileAsync for (a) Windows batch scripts (isWindowsBatchScript) and (b) the Windows command-shim retry (shouldRetryWindowsCommandShim). Normal git.exe invocations and the reviewer's cited "large diff/log/status" cases go through execFileCapture, which was ALREADY capped in BASE. So the primary and streaming git paths are behaviorally UNCHANGED by this PR; no new normal-path git-output regression.Correctness of the GrowingByteBuffer swap: bounds check
stdout.byteLength + chunk.byteLength > maxBufferrejects the overflowing chunk before appending — equivalent boundary to BASE (no off-by-one). On overflow it calls killSpawnedCommandTree(child) then finish() (same child-cleanup semantics as BASE). finish() clears both GrowingByteBuffers, releasing memory. Decoding moved from per-chunkchunk.toString(encoding)(BASE, which could corrupt multibyte UTF-8 split across chunks) to a single decode-at-end via toString() — this is a CORRECTNESS IMPROVEMENT, not a loss. spawnCommandCapture only returns strings, so the 'buffer' encoding concern does not apply.Other caps spot-checked and confirmed far above ordinary use (overload/corruption-only):
gitdir:line), submodules 10,000 / 64KB per path / 16MB cache.Residual: the Windows batch-script / command-shim path now caps arbitrary command output at 10MB where BASE was unbounded — theoretically a >10MB batch/shim command would now fail with 'stdout exceeded maxBuffer'. This is a narrow, non-git, Windows-only path and matches the anti-OOM intent kept in sync with relay MAX_GIT_BUFFER; not a normal-path regression. Signoff=true.
Files
109 files changed (+4987 / −923).
🤖 Decomposed, reviewed & assembled by Claude Code from the reverted #10179. Draft — do not merge out of order.
Made with Orca 🐋