fix(console): bound the pending queue by lines and bytes

The console's pending, not-yet-drained queue was unbounded, so a hidden
Console page that kept receiving verbose daemon-log chunks could grow
without limit.

- Pending lines are now bounded by both a line count and a byte budget.
  The oldest pending lines are dropped once either is exceeded, while
  the newest line is always kept so one huge line is never lost.
- A formatted RPC result is ingested as one block under a single lock,
  so lines from other producers can never interleave inside it.

The front-sequence accounting is also corrected: a pending line dropped
by the cap never entered the visible buffer, so it no longer advances
the front sequence. Only a front eviction or a clear does.

Tests: the line and byte caps keep the newest lines, a single oversized
line survives, a batch appends contiguously, and the front sequence
advances only on a front eviction or clear.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 08:23:30 -05:00
co-authored by Claude Opus 4.8
parent 70e96f75f0
commit 116a997a3a
4 changed files with 100 additions and 16 deletions
+9 -2
View File
@@ -2056,12 +2056,14 @@ void ConsoleTab::addFormattedResult(const std::string& result, bool is_error)
// Precompute JSON fold spans over the whole block so each opener line carries the offset
// to its matching closer (the spans are relative, so they stay valid as the model's line
// cap evicts from the front). This block is ingested atomically on the main thread.
// cap evicts from the front). The block is ingested under one lock (ingestBatch).
std::vector<std::string> texts;
texts.reserve(resultLines.size());
for (const auto& rl : resultLines) texts.push_back(rl.text);
const std::vector<int> foldSpans = ComputeConsoleFoldSpans(texts);
std::vector<ConsoleModelLine> block;
block.reserve(resultLines.size());
for (std::size_t i = 0; i < resultLines.size(); ++i) {
ConsoleChannel channel = ConsoleChannel::None;
switch (resultLines[i].role) {
@@ -2072,8 +2074,13 @@ void ConsoleTab::addFormattedResult(const std::string& result, bool is_error)
case ConsoleResultLineRole::JsonBrace: channel = ConsoleChannel::JsonBrace; break;
case ConsoleResultLineRole::Result: break;
}
model_.ingest(resultLines[i].text, channel, foldSpans[i]);
ConsoleModelLine ml;
ml.text = resultLines[i].text;
ml.channel = channel;
ml.foldSpan = foldSpans[i];
block.push_back(std::move(ml));
}
model_.ingestBatch(std::move(block));
}
void ConsoleTab::renderStatusHeader(ConsoleCommandExecutor& exec)