feat(review): PR-level collapsible metadata + emoji-tagged inline comments

PR-level comment layout (per operator's format guide):
  * Summary of Changes — 2-4 bullets, sourced from the agent's new
    `summary_changes` JSON field. Falls back to splitting the prose
    `summary` if the list is missing.
  * Key Risks & Concerns — bullets from the new `risks` JSON field.
  * Findings Overview — Markdown table covering every finding
    (severity emoji / location / one-line problem). Both anchored and
    unanchored findings appear here so the table is the single scan point.
  * Unanchored Notes — bullets with severity + fix + Markdown-linked ref,
    for findings with no post-change line to anchor.
  * AI Usage & Run Details — wrapped in a <details>/<summary> collapsible
    so the body stays scannable. Cost line stays inside it.

Inline comment shape:
  * Severity badge: 🔴 [HIGH] / 🟡 [MEDIUM] / 🔵 [LOW] /  [INFO].
    Unknown severities fall back to � [INFO].
  * 1-2 short paragraphs of problem; **Fix:** label for the fix line.
  * Standard ```suggestion fence for replacement code (Gitea/Forgejo
    apply-on-click). Language-tagged fences are no longer used for
    single-file diffs.
  * Reference as a Markdown hyperlink, visible label truncated to
    <=60 chars; the underlying URL is preserved verbatim.
  * NO per-comment 🪙 token attribution. All telemetry stays in the
    collapsible block on the PR-level comment.

Agent prompt updated to emit `summary_changes` and `risks` in the JSON
output (backward-compatible — older outputs missing them still parse;
they fall back to splitting the prose `summary`).

Tests: 15 new (severity emoji mapping, reference truncation, findings
table escaping, collapsible usage rendering, summary_changes+risks
layout). Existing tests updated for the new structure.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Marcos
2026-08-20 16:51:20 +00:00
parent 5302e8dcd7
commit f6be2b3c61
3 changed files with 474 additions and 110 deletions
+14 -3
View File
@@ -142,12 +142,18 @@ containing STRICT JSON, nothing else after it:
```json
{
"summary": "One-paragraph overview of the change and its risk.",
"summary_changes": [
"24 short bullets explaining what the PR introduces or modifies"
],
"risks": [
"Bullets detailing potential bugs, edge cases, lifecycle issues, or performance risks found across the diff"
],
"findings": [
{
"severity": "critical|high|medium|low",
"severity": "critical|high|medium|low|info|nit",
"path": "path exactly as in the diff `+++ b/` side",
"line": 12,
"problem": "one line: what is wrong",
"problem": "12 short paragraphs: what is wrong and why it fails",
"fix": "one line: how to fix it",
"suggestion": "exact replacement lines for that location, indented as in the file, or \"\" if no safe replacement",
"reference": "https://... or \"\""
@@ -157,11 +163,16 @@ containing STRICT JSON, nothing else after it:
```
Rules:
- `summary_changes` (24 bullets) goes into the **Summary of Changes** section.
`risks` (bullets) goes into **Key Risks & Concerns**. Both are required;
empty arrays are fine when nothing applies.
- `suggestion` is the literal new code that replaces the flagged line(s). Minimal —
just the changed lines, indented as they'd appear in the file. Empty string `""`
when no safe textual replacement exists (e.g. missing test, architectural note).
- `problem` is 12 short paragraphs (the inline comment shows it verbatim).
Lead with the consequence (security / data loss / perf / etc.), then the cause.
- At most ~15 findings, highest severity first.
- If the diff is clean, output `{"summary":"...","findings":[]}`.
- If the diff is clean, output `{"summary":"...","summary_changes":[],"risks":[],"findings":[]}`.
- Do NOT repeat anything in `prior_reviews`.
- The JSON block must be the LAST thing in your message — the Python shell parses
the last ```json fenced block from your output. If you run out of context/steps