Back to docs
journeyDaily user4 min read

Inline review comments

What's inside each comment — severity, category, evidence, and team-memory attribution.

Every inline comment Revvu posts has the same structure: a severity tag, a category, the finding itself, and the reasoning that led to it. This page explains what each piece means and how to read a comment quickly. If you only have a minute, the severity table is the part that matters.

Severity

Severity tells you how urgent the finding is. The four levels are deliberate — not every issue is critical, and treating them all equally would make the urgent ones harder to spot.

SeverityWhat it meansWhen to act
criticalA bug, security flaw, or correctness issue that will likely break in productionBefore merge — these block the PR in spirit even if not enforced
warningA real issue that's worth fixing but won't necessarily break things on its ownBefore merge if you can; in a follow-up PR if scope is tight
suggestionCode that works but could be clearer, safer, or more idiomaticWhen you're already in the file — don't open it just for these
nitpickStyle, naming, or micro-improvements that genuinely don't change behaviorOptional — fold in if it costs nothing

Categories

Each comment also has a category that tells you what kind of issue it is. Categories help you scan a long review quickly — bugs first, then security, then everything else.

  • bug — Logic that produces wrong output for some input — off-by-one, missed edge case, incorrect branch.
  • security — Something an attacker could exploit — injection, missing auth, leaked secret, weak crypto, unsafe deserialization.
  • performance — Code that will be slow under realistic load — quadratic loop, N+1 query, unnecessary work in a hot path.
  • correctness — Code that's technically working but violates an invariant, contract, or assumption that other parts of the system depend on.
  • testing — A missing test, a test that doesn't actually verify what it claims, or a test that will become flaky.
  • docs — A doc comment, README, or type signature that's now stale or misleading because of the change.
  • asymmetry — A change applied in one place but not its sibling — for example, a helper extracted from one of two callers, leaving the other on the old formula.
  • style — Naming, formatting, or idiom issues that the linter doesn't catch but a human reviewer would.
  • other — Anything that doesn't fit the categories above — used sparingly, with a clear explanation in the body.

Confidence

Every finding also has an internal confidence score from 1 to 10. You won't see the number directly in the comment — it's used as a filter. Findings below the configured threshold (default is 7) are dropped before posting, on the principle that a low-confidence comment is worse than no comment at all. The threshold is tunable in repo settings if you want a stricter or looser bar.

How a comment is structured

Every comment starts with a severity badge in bold, followed by the finding in plain language. The body explains the problem, points at the evidence in the diff, and (when relevant) suggests a direction for the fix. Comments are written to be skimmable — the first line tells you what's wrong, the rest tells you why.

**[critical]** Missing null check before dereferencing `user.email`.

The early return on line 42 only fires when `user` is null, but
`user.email` can also be null when the account hasn't verified an
email yet — the schema marks the column nullable. Calling
`.toLowerCase()` on null will throw at runtime.

Consider returning early if either `user` or `user.email` is null,
or use optional chaining: `user.email?.toLowerCase()`.

Team memory attribution

When a finding is influenced by something the team has taught the bot — through @-mention learnings or per-repo configuration — the comment ends with a short attribution line. This makes it clear when a comment reflects team conventions rather than universal best practice, so you can challenge the rule if it no longer applies.

**[warning]** Throw an `AppError` instead of a raw `Error`.

Raw `Error` instances bypass the central error handler in
`src/lib/errors.ts`, so this won't be tagged with a request id
or surfaced to the structured logger.

_Based on team memory: We always use the AppError class for
thrown errors, never raw Error._

Re-pinned comments

Sometimes a finding is about a file that wasn't changed in this push — for example, a test fixture that needs updating because of a schema change in a different file. GitHub's API only lets the bot post inline comments on lines that appear in the diff. To avoid silently dropping the finding, the bot pins it to the nearest related file and prefixes the body with a pointer to the real location.

**(About src/lib/env.test.ts:24 — outside this diff, re-pinned here for visibility.)**

**[warning]** The schema change in env.ts adds a required field that
the test fixture doesn't provide. The test will fail on the next run.

Off-diff fallback

When a finding has no commentable lines anywhere in the related file — for example, a binary file or a file whose only change is a rename — the bot can't post an inline comment at all. Instead, the finding surfaces in a 'Findings outside the diff' section in the review summary at the top of the PR. The intent is the same: never silently drop a real finding because of where it lives.

Marking issues as fixed

When you push a fix for a flagged issue, the bot recognizes it on the next review. The original comment thread gets a friendly acknowledgement reply ('This issue has been fixed in the latest push — nice work!') and the thread is auto-collapsed in the GitHub UI. You don't have to manually resolve the conversation. If the bot is wrong about a fix, just push a clarifying commit or reply in the thread — the next review will re-evaluate.