fix(server): release drained terminal output while queue stays busy

PA
3d ago
+92-3

Problem

A terminal that keeps its output queue busy retains every consumed
chunk until the queue becomes empty. The history limit does not bound
these references. Sustained output can grow the server heap without
bound and eventually exhaust memory.

The regression keeps only two chunks pending. After 256 deliveries,
the old queue still holds 16,842,752 bytes of ASCII output.

Change

Release each consumed entry immediately. Compact the queue when at
least half its slots have been consumed, keeping compaction amortized.
Output order and delivery remain unchanged.

Scope and approval

This qualifies for the small, focused obvious-bug exception:
it only releases consumed terminal output and bounds empty queue slots.
It adds no setting, contract, or product behavior change.

Verification

Linux x64, Node 26.12.1, pnpm 12.14.0.

  • Added a failing regression in the existing manager test file.
    It exercises the real manager with a fake PTY, uses Deferred gates,
    and observes retained queue payloads without mocking the drain logic.
  • The fixed queue retains at most 131,072 bytes with two chunks pending.
    The test also bounds queue slots and checks all 258 deliveries in order.
  • vp test run apps/server/src/terminal/Manager.test.ts apps/server/src/terminal/OutputProtocol.test.ts: 56 passed.
  • vp run check:changed: format, lint, knip, generated GraphQL,
    affected-package typechecks, and manager tests passed.
    An existing lint warning remains on unchanged line 731.
    Checks used NODE_USE_ENV_PROXY=1 for license downloads.

Service test transcript:

Before: expected 16842752 to be less than or equal to 131072
After:  43 manager tests passed, including bounded retention and delivery

This measures retained references, not a forced out-of-memory crash.
No native PTY stress test or UI verification was performed.

Model: GPT-6. Harness: Codex.