code-yeongyu / code-yeongyu/senpi
bug(coding-agent): monitor line buffer grows unbounded on newline-less output; 250 ms SHA-256 polling continues while paused
- Dominant language
- TypeScript
- Stars
- 429
- Forks
- 98
- Avg merge
- 5h 3m
- Merged PRs (30d)
- 526
Description
## Summary
packages/coding-agent/src/core/extensions/builtin/terminal/monitor-registry.ts:
- lineBuffer (line 180) accumulates command output until a newline appears (lines 758-789). Output that never emits a newline (CR-based progress bars, single-line spinners) grows the buffer without bound — even while the monitor is paused (the paused check at line 767 happens after the append path).
- File monitors poll every 250 ms (setInterval at line 396) and hash up to 3 x 64 KiB with SHA-256 (line 735) on every tick; the paused check (lines 568-570) runs after the read/hash work, so paused monitors keep doing the expensive part.
## Context
Root-caused during a profiling investigation of a long-lived macOS host (M4 Pro, 64 GB) running ~28 concurrent senpi/omo sessions for several days. Symptoms: load average ~150 with ~50% CPU utilization (threads blocked on swap I/O), 20 GB swap in use, 61 ppid=1 orphan processes (~2.1 GB, including vite dev servers up to 3.1 GB compressed, dev-runner and vp trees), and 12-14 zombies whose parents are live TUI main processes. All file:line references are against main (b19491745). Raw profiling evidence held locally.
## Expected (ideal state)
lineBuffer is byte-capped (oldest or newest truncation, explicitly documented); paused monitors skip the read/hash work entirely (checks before the I/O, not after); fs.watch remains the primary signal with polling as a slow fallback.
## Acceptance criteria
- Tests: newline-less output beyond the cap leaves the buffer bounded; a paused monitor performs no hash/poll work (observable via injected fs/crypto spies); resume still detects changes.
Contributor guide
Research direction
Start in packages/coding-agent/src/core/extensions/builtin/terminal/monitor-registry.ts, inspecting lineBuffer handling around lines 758-789 and the polling path around lines 396, 568-570, and 735. Add or update tests for bounded newline-less output, no polling or hashing while paused, and change detection after resume; the acceptance criteria define done.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, performance, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100