Skip to content

fix: keep qa report and artifact listings inside the protocol frame - #83

Merged
yashranaway merged 2 commits into
mainfrom
t3code/bounded-responses
Aug 5, 2026
Merged

fix: keep qa report and artifact listings inside the protocol frame#83
yashranaway merged 2 commits into
mainfrom
t3code/bounded-responses

Conversation

@yashranaway

Copy link
Copy Markdown
Collaborator

Closes #14.

The bug

A full diagnostic report is 500 events, each holding up to a 4 KiB message and an 8 KiB URL — roughly 2 MB against a 1 MiB frame. encodeLine threw inside handleClient, fell into the generic catch, and the agent received:

INVALID_REQUEST  messageTooLarge

…for a request the host had accepted and executed successfully. There was no escape hatch: no pagination, no way to ask for less. artifacts list had the same unbounded exposure as the store grew over a long session.

The fix

Bounded responses that say what they dropped, matching the pruning contract used everywhere else in the product:

  • qa report trims its issues and events arrays to a byte budget, keeping the newest — those are what an agent is diagnosing. Crucially the summary counts still describe every collected event, so the numbers stay honest when the payload is trimmed.
  • artifacts list returns the newest 250 with total and omitted.
  • Both set truncated.

The transport now separates "this response cannot be framed" from "your request was bad", answering RESPONSE_TOO_LARGE with a suggestion (--limit, or headless qa clear). That path should be unreachable for these two commands now, but it is the honest fallback for any future response that outgrows the frame.

Tests

Two new cases in the protocol suite: a report built from 500 × 4 KiB events, and a store holding 260 artifacts. Both assert the encoded response fits headlessMaximumMessageBytes and that kept + omitted accounts for everything. The first fails on main.

Design note

Per architecture decision §4, response-side bounding was already sanctioned as a compatible addition, so no new decision entry is needed. I chose truncation now over cursor pagination: it is compatible, needs no wire-visible protocol addition, and makes the failure mode honest immediately. Cursor pagination is the richer answer and stays tracked as §G3 — worth doing when console list/network list want the same primitive.

Closes #14.

A full diagnostic report is 500 events, each holding up to a 4 KiB message and
an 8 KiB URL — roughly 2 MB against a 1 MiB frame. Encoding threw inside
handleClient, fell into the generic catch, and the agent received
INVALID_REQUEST for a request the host had accepted and executed. artifacts
list had the same unbounded exposure as the store grew.

Both responses are now bounded and say so. qa report trims its issue and event
arrays to a byte budget, keeping the newest, while summary counts continue to
describe every collected event so the numbers stay honest when the payload is
trimmed. artifacts list returns the newest 250 with total and omitted counts.
Both set truncated, matching the pruning contract used everywhere else.

The transport now distinguishes a response that cannot be framed from a bad
request: it answers RESPONSE_TOO_LARGE with a suggestion instead of blaming
the caller. That path should now be unreachable for these two commands, but it
is the honest fallback for any future response that outgrows the frame.

Tests build a report that would previously have exceeded the frame and a store
of 260 artifacts, and assert both encode within headlessMaximumMessageBytes
with correct omitted accounting. P1 documents the bounds.
@yashranaway
yashranaway requested a review from SarthakWade August 5, 2026 19:57
CI caught the first attempt: the issues array was capped at 100 entries but
not by size. Issues are derived from the same events and carry the same 4 KiB
message and 8 KiB URL, so 100 of them is over a megabyte on its own and the
report still failed to frame.

Both arrays now share one byte-budget helper. The test asserts issue
accounting as well as event accounting, which is the assertion that would have
caught this the first time.
@yashranaway
yashranaway merged commit c5b4069 into main Aug 5, 2026
7 checks passed
@yashranaway
yashranaway deleted the t3code/bounded-responses branch August 5, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A3 — Oversized responses break the 1 MiB frame

1 participant