Build1 publisher2 min readPublished
An AI code reviewer enforces its brevity in a slice() call after the model answers
Severity labels come back from Claude, get checked against four allowed values, stable-sorted and then cut with slice() at a constant, with the count of what got cut printed in the review body, while the priority order inside the cut still comes from the model.
The Engineer · Build desk
What happened
- The reviewer runs as a GitHub webhook handler that fetches the diff, calls Claude, ranks the structured findings and posts inline comments.
- Findings come back as JSON with path, line, severity and message, and a severity string outside the four allowed values gets the finding dropped.
- A stable sort by severity runs first, then slice(0, MAX_COMMENTS) cuts the list, with the cap held as a constant in application code instead of an instruction in the prompt.
- Whatever the cut removes is counted and printed in the review body as lower-priority remarks suppressed to keep the review focused.
- GitHub expects a 2XX within roughly ten seconds of a webhook delivery, and the synchronous version had deliveries logged as failed while the function kept running and posted its comments.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint Review coverage is bounded by a constant, and the author concedes the cap works against you on a pull request holding more than eight genuine bugs.
- decision Adopting this means picking the number yourself and owning it in code, because tuning how much review you see takes a redeploy.
- capability A finding whose line fails to anchor to the diff hunk still reaches the pull request: the handler catches the inline failure and posts one top-level comment.
- cost The ten-second acknowledgement budget rules out a single synchronous handler, so anyone copying the design pays for background execution and the monitoring to match.
The suppression runs in a fixed order. Each finding's severity string is checked against the whitelist first, so anything outside the four values is gone before ranking [3]. The survivors are stable-sorted on a rank table: BUG 0, WARN 1, NIT 2, PRAISE 3 [4]. Then `slice(0, MAX_COMMENTS)` trims the list [5]. Inside a single severity, ties keep the order the model produced them in [4].
So the cap lives in application code and the priority inside it belongs to the model. If a real defect comes back labelled WARN, it sorts behind every BUG and survives only if fewer than MAX_COMMENTS findings outrank it, and nothing downstream re-scores a finding [4][5]. The author is candid about that, writing that he is not willing to guarantee the cap hides no real bugs [10].
The case for doing it in code is stated plainly in the post: "A prompt is a request the model can ignore on a bad day; a slice() cannot." [9] It matches what the author reports trying first, a model that agrees to be concise and hands back fourteen findings anyway [12].
The disclosure counter has a gap. `suppressedCount` is the length of the sanitized list minus the number of comments shown [6], and the sanitized list is what survived the whitelist. A finding dropped for an unrecognised severity sits outside that subtraction. The reader gets it as neither a comment nor a count [18].
PRAISE has the same problem from the other end. It is the fourth severity, the slot reserved for "this was a good change" [16], and it ranks last [4]. The slice keeps the front of the list [5], so the praise line only survives on a pull request that produced fewer findings than the cap [19]. The post uses MAX_COMMENTS as a constant and leaves the value out [20].
For this to be the right default in your repo, most pull requests have to contain fewer genuine bugs than the cap. On a codebase where one pull request routinely carries a dozen, severity ordering is the only thing standing between the reviewer and a real miss [10]. The condition fits the audience the post names: solo developers and small teams with no enterprise code-review bundle sitting on top of their existing tools, who turn a noisy reviewer off in week one and never come back [17].
What to watch
- Whether the author publishes the MAX_COMMENTS value and how often suppressedCount is non-zero on real pull requests.
- Whether a re-scoring step inside a severity level replaces the model's own output order for tie-breaks.
- Whether the top-level fallback comment applies the same cap, or posts findings the inline path would have cut.