Files
review-bot/review/prompt.go
T
Rodin c76362af95
CI / test (pull_request) Successful in 13s
CI / review (gpt-5, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m59s
CI / review (gpt-5-mini, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 3m36s
fix: prevent false-positive missing-import findings
The LLM was treating the diff as complete file context and flagging
"missing imports" for symbols that exist in unchanged portions of
the file. Added explicit instructions to the system prompt:

- Clarify that the diff is partial; unchanged code already exists
- Explicitly instruct: do not flag missing imports/types unless the
  diff introduces a new usage without a corresponding addition
- Add rule: never flag undefined symbols that could exist in the
  unchanged portions
2026-05-01 12:00:27 -07:00

79 lines
3.6 KiB
Go

package review
import (
"fmt"
"strings"
)
// BuildSystemPrompt constructs the system prompt for the LLM reviewer.
func BuildSystemPrompt(conventions string) string {
var sb strings.Builder
sb.WriteString("You are an expert code reviewer. Review the provided pull request diff carefully.\n\n")
sb.WriteString("IMPORTANT CONTEXT:\n")
sb.WriteString("- You are reviewing a DIFF, not the complete file. Code not shown in the diff already exists in the repository.\n")
sb.WriteString("- Imports, type definitions, functions, and other declarations that do not appear in the diff are already present in the file.\n")
sb.WriteString("- Do NOT flag missing imports, missing type definitions, or undefined references unless the diff itself introduces a new usage without a corresponding addition in the same diff.\n")
sb.WriteString("- Only flag issues with code that is actually being ADDED or MODIFIED in this diff.\n\n")
sb.WriteString("Your task:\n")
sb.WriteString("1. Review the diff for correctness, idiomatic code, potential bugs, and design issues.\n")
sb.WriteString("2. Consider the CI status — if CI has failed, that is an automatic REQUEST_CHANGES regardless of code quality.\n")
sb.WriteString("3. Output your review as structured JSON (and ONLY JSON, no markdown fences or other text).\n\n")
sb.WriteString("Output format:\n")
sb.WriteString("{\n")
sb.WriteString(" \"verdict\": \"APPROVE\" or \"REQUEST_CHANGES\",\n")
sb.WriteString(" \"summary\": \"Brief overall assessment (1-3 sentences)\",\n")
sb.WriteString(" \"findings\": [\n")
sb.WriteString(" {\n")
sb.WriteString(" \"severity\": \"MAJOR\" or \"MINOR\" or \"NIT\",\n")
sb.WriteString(" \"file\": \"path/to/file\",\n")
sb.WriteString(" \"line\": <line number from the diff>,\n")
sb.WriteString(" \"finding\": \"Description of the issue\"\n")
sb.WriteString(" }\n")
sb.WriteString(" ],\n")
sb.WriteString(" \"recommendation\": \"Full recommendation text explaining your verdict\"\n")
sb.WriteString("}\n\n")
sb.WriteString("Rules:\n")
sb.WriteString("- If there are any MAJOR findings → verdict must be REQUEST_CHANGES\n")
sb.WriteString("- If there are no MAJOR findings → verdict should be APPROVE\n")
sb.WriteString("- If CI has failed → verdict must be REQUEST_CHANGES with a finding noting the CI failure\n")
sb.WriteString("- Be thorough but fair. Don't nitpick style unless it impacts readability significantly.\n")
sb.WriteString("- Line numbers should reference the new file line numbers from the diff headers.\n")
sb.WriteString("- If the diff is empty or trivial (only formatting/whitespace), APPROVE with no findings.\n")
sb.WriteString("- Never flag 'missing imports' or 'undefined' errors for symbols that could exist in the unchanged portions of the file.\n")
if conventions != "" {
sb.WriteString(fmt.Sprintf("\n\nThe repository has the following coding conventions that should be respected:\n\n%s\n", conventions))
}
return sb.String()
}
// BuildUserPrompt constructs the user message with PR context.
func BuildUserPrompt(title, description, diff string, ciPassed bool, ciDetails string) string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("## Pull Request: %s\n\n", title))
if description != "" {
sb.WriteString(fmt.Sprintf("### Description\n%s\n\n", description))
}
ciStatus := "PASSED"
if !ciPassed {
ciStatus = "FAILED"
}
sb.WriteString(fmt.Sprintf("### CI Status: %s\n", ciStatus))
if ciDetails != "" {
sb.WriteString(fmt.Sprintf("CI Details: %s\n", ciDetails))
}
sb.WriteString("\n### Diff\n\n")
sb.WriteString("```diff\n")
sb.WriteString(diff)
sb.WriteString("\n```\n")
return sb.String()
}