From db7c25ce5b893e76608d84a9dadcfcf4b3c3ea11 Mon Sep 17 00:00:00 2001
From: Patel230
Date: Tue, 9 Jun 2026 01:14:11 +0530
Subject: [PATCH] chore: sync lint config and review code updates
---
.DS_Store | Bin 6148 -> 0 bytes
.gitignore | 3 +++
.golangci.yml | 45 +++++++++++++++++++++++++++++++++++-
CHANGELOG.md | 2 --
README.md | 4 ++--
SECURITY.md | 4 ++--
autofix_test.go | 4 ++--
checks.go | 2 +-
dedup.go | 6 +----
describe.go | 7 +++---
filter.go | 5 +---
incremental.go | 4 ++--
internal/comment/comment.go | 4 ++--
internal/context/git.go | 6 ++---
internal/output/output.go | 26 ++++++++++-----------
internal/review/prompt.go | 38 +++++++++++++++---------------
internal/review/reflect.go | 6 ++---
reviewer.go | 4 ++--
sast_fusion.go | 10 ++++----
sast_integration.go | 6 ++---
20 files changed, 112 insertions(+), 74 deletions(-)
delete mode 100644 .DS_Store
diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6148
zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3
zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ
zLs35+`xjp>T0AI-powered code review for diffs
-
+
@@ -61,7 +61,7 @@ type Provider interface {
go get github.com/GrayCodeAI/sight@latest
```
-Requires Go 1.23+.
+Requires Go 1.26+.
## Contributing
diff --git a/SECURITY.md b/SECURITY.md
index 1dd2373..d1d7499 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -44,8 +44,8 @@ We follow [coordinated vulnerability disclosure](https://en.wikipedia.org/wiki/C
## Security practices in this repo
-- **Dependency monitoring:** automated via Dependabot (see
- `.github/dependabot.yml`).
+- **Dependency monitoring:** vulnerable dependencies are detected by
+ `govulncheck`, which runs on every CI build (see "Vulnerability scanning").
- **Static analysis:** `golangci-lint` / `ruff` / `mypy` enforced in CI.
- **Vulnerability scanning:** `govulncheck` (Go) / `pip-audit` (Python) run
on every CI build.
diff --git a/autofix_test.go b/autofix_test.go
index 54c5135..83e7335 100644
--- a/autofix_test.go
+++ b/autofix_test.go
@@ -160,7 +160,7 @@ func TestExtractRelevantDiff_LineWindowExtraction(t *testing.T) {
b.WriteString("diff --git a/big.go b/big.go\n--- a/big.go\n+++ b/big.go\n")
b.WriteString("@@ -1,20 +1,20 @@\n")
for i := 1; i <= 20; i++ {
- b.WriteString(fmt.Sprintf(" line %d context\n", i))
+ fmt.Fprintf(&b, " line %d context\n", i)
}
b.WriteString("+added line\n")
@@ -189,7 +189,7 @@ func TestExtractRelevantDiff_Truncation(t *testing.T) {
b.WriteString("diff --git a/big.go b/big.go\n--- a/big.go\n+++ b/big.go\n")
b.WriteString("@@ -1,50 +1,50 @@\n")
for i := 1; i <= 50; i++ {
- b.WriteString(fmt.Sprintf(" this is a long context line number %d with extra padding text to make it longer\n", i))
+ fmt.Fprintf(&b, " this is a long context line number %d with extra padding text to make it longer\n", i)
}
result := extractRelevantDiff(b.String(), "big.go", 25)
diff --git a/checks.go b/checks.go
index 9120f29..be257c2 100644
--- a/checks.go
+++ b/checks.go
@@ -182,7 +182,7 @@ func parseFrontmatter(check *CustomCheck, fm string) {
}
}
case "enabled":
- check.Enabled = strings.ToLower(value) != "false"
+ check.Enabled = !strings.EqualFold(value, "false")
}
}
}
diff --git a/dedup.go b/dedup.go
index 6bf3938..691e90e 100644
--- a/dedup.go
+++ b/dedup.go
@@ -192,11 +192,7 @@ func buildReason(rep Finding, dupes []Finding, config DedupConfig) string {
parts = append(parts, "same file")
}
- if len(dupes) == 1 {
- parts = append(parts, "similar concern/message text")
- } else {
- parts = append(parts, "similar concern/message text")
- }
+ parts = append(parts, "similar concern/message text")
if rep.File != "" && len(dupes) > 0 && dupes[0].File == rep.File {
parts = append(parts, "within line distance threshold")
diff --git a/describe.go b/describe.go
index 9fc8459..7f25ac2 100644
--- a/describe.go
+++ b/describe.go
@@ -79,11 +79,12 @@ func buildDescribePrompt(files []diff.File, maxTokens int) string {
for _, f := range files {
prefix := ""
- if f.Added {
+ switch {
+ case f.Added:
prefix = " (new)"
- } else if f.Deleted {
+ case f.Deleted:
prefix = " (deleted)"
- } else if f.Renamed {
+ case f.Renamed:
prefix = " (renamed from " + f.OldPath + ")"
}
b.WriteString("- " + f.Path + prefix + "\n")
diff --git a/filter.go b/filter.go
index 6ea9d0f..bdef086 100644
--- a/filter.go
+++ b/filter.go
@@ -138,10 +138,7 @@ REASONING: brief explanation`, f.Concern, f.Severity, f.File, f.Line, f.Message,
func parseFilterResponse(f Finding, response string) FilterResult {
lower := strings.ToLower(response)
- confirmed := true
- if strings.Contains(lower, "confirmed: no") || strings.Contains(lower, "false positive") {
- confirmed = false
- }
+ confirmed := !(strings.Contains(lower, "confirmed: no") || strings.Contains(lower, "false positive"))
confidence := 0.7
if idx := strings.Index(lower, "confidence:"); idx >= 0 {
diff --git a/incremental.go b/incremental.go
index 917d31d..37c077c 100644
--- a/incremental.go
+++ b/incremental.go
@@ -157,9 +157,9 @@ func enrichDiffWithContext(ctx context.Context, diffText string, contextLines in
// Add surrounding context before the hunk
contextBefore := loadFileLines(ctx, currentFile, startLine-contextLines, startLine-1)
if len(contextBefore) > 0 {
- enriched.WriteString(fmt.Sprintf("\n--- Context before (lines %d-%d) ---\n", startLine-contextLines, startLine-1))
+ fmt.Fprintf(&enriched, "\n--- Context before (lines %d-%d) ---\n", startLine-contextLines, startLine-1)
for i, cl := range contextBefore {
- enriched.WriteString(fmt.Sprintf(" %d | %s\n", startLine-contextLines+i, cl))
+ fmt.Fprintf(&enriched, " %d | %s\n", startLine-contextLines+i, cl)
}
}
diff --git a/internal/comment/comment.go b/internal/comment/comment.go
index a251518..edaea3a 100644
--- a/internal/comment/comment.go
+++ b/internal/comment/comment.go
@@ -156,10 +156,10 @@ func buildComment(f FindingInput) Inline {
sev = sevLabels[f.Severity]
}
- body.WriteString(fmt.Sprintf("**[%s]** %s\n", sev, f.Message))
+ fmt.Fprintf(&body, "**[%s]** %s\n", sev, f.Message)
if f.Reasoning != "" {
- body.WriteString(fmt.Sprintf("\n> %s\n", f.Reasoning))
+ fmt.Fprintf(&body, "\n> %s\n", f.Reasoning)
}
c := Inline{
diff --git a/internal/context/git.go b/internal/context/git.go
index 174ebd2..c9c6936 100644
--- a/internal/context/git.go
+++ b/internal/context/git.go
@@ -60,12 +60,12 @@ func FormatContext(contexts []FileContext) string {
if len(fc.RecentCommits) == 0 {
continue
}
- b.WriteString(fmt.Sprintf("### %s — Recent changes:\n", fc.Path))
+ fmt.Fprintf(&b, "### %s — Recent changes:\n", fc.Path)
for _, c := range fc.RecentCommits {
- b.WriteString(fmt.Sprintf(" - %s\n", c))
+ fmt.Fprintf(&b, " - %s\n", c)
}
if fc.BlameSnippet != "" {
- b.WriteString(fmt.Sprintf(" Blame: %s\n", fc.BlameSnippet))
+ fmt.Fprintf(&b, " Blame: %s\n", fc.BlameSnippet)
}
b.WriteString("\n")
}
diff --git a/internal/output/output.go b/internal/output/output.go
index 1328b16..e16b071 100644
--- a/internal/output/output.go
+++ b/internal/output/output.go
@@ -50,9 +50,9 @@ func FormatTerminal(findings []Finding, stats Stats) string {
b.WriteString("\n")
b.WriteString(bold + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + reset + "\n")
b.WriteString(bold + " SIGHT CODE REVIEW" + reset + "\n")
- b.WriteString(fmt.Sprintf(" %d files, %d hunks analyzed", stats.FilesReviewed, stats.HunksAnalyzed))
+ fmt.Fprintf(&b, " %d files, %d hunks analyzed", stats.FilesReviewed, stats.HunksAnalyzed)
if stats.TokensUsed > 0 {
- b.WriteString(fmt.Sprintf(" (%d tokens used)", stats.TokensUsed))
+ fmt.Fprintf(&b, " (%d tokens used)", stats.TokensUsed)
}
b.WriteString("\n")
b.WriteString(bold + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + reset + "\n\n")
@@ -82,7 +82,7 @@ func FormatTerminal(findings []Finding, stats Stats) string {
name = severityNames[sev]
}
- b.WriteString(fmt.Sprintf(" %s%s%s (%d)\n\n", color+bold, name, reset, len(items)))
+ fmt.Fprintf(&b, " %s%s%s (%d)\n\n", color+bold, name, reset, len(items))
for _, f := range items {
loc := f.File
@@ -93,25 +93,25 @@ func FormatTerminal(findings []Finding, stats Stats) string {
}
}
- b.WriteString(fmt.Sprintf(" %s%s%s %s\n", color, "●", reset, f.Message))
- b.WriteString(fmt.Sprintf(" %s%s%s", dim, loc, reset))
+ fmt.Fprintf(&b, " %s%s%s %s\n", color, "●", reset, f.Message)
+ fmt.Fprintf(&b, " %s%s%s", dim, loc, reset)
if f.Concern != "" {
- b.WriteString(fmt.Sprintf(" %s[%s]%s", dim, f.Concern, reset))
+ fmt.Fprintf(&b, " %s[%s]%s", dim, f.Concern, reset)
}
b.WriteString("\n")
if f.Reasoning != "" {
- b.WriteString(fmt.Sprintf(" %s▸ %s%s\n", dim, f.Reasoning, reset))
+ fmt.Fprintf(&b, " %s▸ %s%s\n", dim, f.Reasoning, reset)
}
if f.Fix != "" {
- b.WriteString(fmt.Sprintf(" %s⚡ Fix: %s%s\n", "\033[32m", f.Fix, reset))
+ fmt.Fprintf(&b, " %s⚡ Fix: %s%s\n", "\033[32m", f.Fix, reset)
}
b.WriteString("\n")
}
}
b.WriteString(bold + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + reset + "\n")
- b.WriteString(fmt.Sprintf(" SUMMARY: %d findings", len(findings)))
+ fmt.Fprintf(&b, " SUMMARY: %d findings", len(findings))
parts := []string{}
for _, sev := range order {
@@ -131,7 +131,7 @@ func FormatTerminal(findings []Finding, stats Stats) string {
for name, d := range stats.DurationPerConcern {
dParts = append(dParts, fmt.Sprintf("%s:%s", name, d.Round(time.Millisecond)))
}
- b.WriteString(fmt.Sprintf(" %sTiming: %s%s\n", dim, strings.Join(dParts, " | "), reset))
+ fmt.Fprintf(&b, " %sTiming: %s%s\n", dim, strings.Join(dParts, " | "), reset)
}
b.WriteString(bold + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + reset + "\n")
@@ -309,7 +309,7 @@ func FormatGitHubReview(findings []Finding) string {
}
var b strings.Builder
- b.WriteString(fmt.Sprintf("## Sight Review — %d findings\n\n", len(findings)))
+ fmt.Fprintf(&b, "## Sight Review — %d findings\n\n", len(findings))
for _, f := range findings {
sev := "INFO"
@@ -320,9 +320,9 @@ func FormatGitHubReview(findings []Finding) string {
if f.Line > 0 {
loc = fmt.Sprintf("%s:%d", f.File, f.Line)
}
- b.WriteString(fmt.Sprintf("- **[%s]** `%s` — %s\n", sev, loc, f.Message))
+ fmt.Fprintf(&b, "- **[%s]** `%s` — %s\n", sev, loc, f.Message)
if f.Fix != "" {
- b.WriteString(fmt.Sprintf(" - Fix: %s\n", f.Fix))
+ fmt.Fprintf(&b, " - Fix: %s\n", f.Fix)
}
}
diff --git a/internal/review/prompt.go b/internal/review/prompt.go
index c6dfa9e..9a794d7 100644
--- a/internal/review/prompt.go
+++ b/internal/review/prompt.go
@@ -55,9 +55,9 @@ func BuildPrompt(concern Concern, files []diff.File, contextLines int) string {
if len(file.Hunks) == 0 && !file.Added && !file.Renamed {
continue
}
- b.WriteString(fmt.Sprintf("## File: %s\n", file.Path))
+ fmt.Fprintf(&b, "## File: %s\n", file.Path)
if file.Renamed {
- b.WriteString(fmt.Sprintf("(renamed from %s)\n", file.OldPath))
+ fmt.Fprintf(&b, "(renamed from %s)\n", file.OldPath)
}
if file.Added {
b.WriteString("(new file)\n")
@@ -65,19 +65,19 @@ func BuildPrompt(concern Concern, files []diff.File, contextLines int) string {
b.WriteString("\n```diff\n")
for _, hunk := range file.Hunks {
- b.WriteString(fmt.Sprintf("@@ -%d,%d +%d,%d @@ %s\n",
+ fmt.Fprintf(&b, "@@ -%d,%d +%d,%d @@ %s\n",
hunk.OldStart, hunk.OldCount,
hunk.NewStart, hunk.NewCount,
- hunk.Header))
+ hunk.Header)
for _, line := range hunk.Lines {
switch line.Type {
case diff.LineAdded:
- b.WriteString(fmt.Sprintf("+%s\n", line.Content))
+ fmt.Fprintf(&b, "+%s\n", line.Content)
case diff.LineRemoved:
- b.WriteString(fmt.Sprintf("-%s\n", line.Content))
+ fmt.Fprintf(&b, "-%s\n", line.Content)
case diff.LineContext:
- b.WriteString(fmt.Sprintf(" %s\n", line.Content))
+ fmt.Fprintf(&b, " %s\n", line.Content)
}
}
}
@@ -86,7 +86,7 @@ func BuildPrompt(concern Concern, files []diff.File, contextLines int) string {
}
b.WriteString("\n\n")
- b.WriteString(fmt.Sprintf("Focus on: %s\n", concern.Name))
+ fmt.Fprintf(&b, "Focus on: %s\n", concern.Name)
b.WriteString("Respond with a JSON array of findings.\n")
return b.String()
@@ -163,13 +163,13 @@ func detectLanguages(files []diff.File) string {
var b strings.Builder
b.WriteString("## Context\n")
- b.WriteString(fmt.Sprintf("Primary language: %s\n", primaryLang))
+ fmt.Fprintf(&b, "Primary language: %s\n", primaryLang)
b.WriteString("Files: ")
for i, e := range entries {
if i > 0 {
b.WriteString(", ")
}
- b.WriteString(fmt.Sprintf("%d %s", e.count, e.ext))
+ fmt.Fprintf(&b, "%d %s", e.count, e.ext)
}
b.WriteString("\n")
return b.String()
@@ -198,9 +198,9 @@ func BuildPromptEnhanced(concern Concern, files []diff.File, contextLines int) s
if len(file.Hunks) == 0 && !file.Added && !file.Renamed {
continue
}
- b.WriteString(fmt.Sprintf("## File: %s\n", file.Path))
+ fmt.Fprintf(&b, "## File: %s\n", file.Path)
if file.Renamed {
- b.WriteString(fmt.Sprintf("(renamed from %s)\n", file.OldPath))
+ fmt.Fprintf(&b, "(renamed from %s)\n", file.OldPath)
}
if file.Added {
b.WriteString("(new file)\n")
@@ -208,19 +208,19 @@ func BuildPromptEnhanced(concern Concern, files []diff.File, contextLines int) s
b.WriteString("\n")
for _, hunk := range file.Hunks {
- b.WriteString(fmt.Sprintf("@@ -%d,%d +%d,%d @@ %s\n\n",
+ fmt.Fprintf(&b, "@@ -%d,%d +%d,%d @@ %s\n\n",
hunk.OldStart, hunk.OldCount,
hunk.NewStart, hunk.NewCount,
- hunk.Header))
+ hunk.Header)
// __new hunk__ section: added lines and context lines with new-file line numbers
b.WriteString("__new hunk__\n")
for _, line := range hunk.Lines {
switch line.Type {
case diff.LineAdded:
- b.WriteString(fmt.Sprintf("%d +%s\n", line.NewNum, line.Content))
+ fmt.Fprintf(&b, "%d +%s\n", line.NewNum, line.Content)
case diff.LineContext:
- b.WriteString(fmt.Sprintf("%d %s\n", line.NewNum, line.Content))
+ fmt.Fprintf(&b, "%d %s\n", line.NewNum, line.Content)
}
}
b.WriteString("\n")
@@ -230,9 +230,9 @@ func BuildPromptEnhanced(concern Concern, files []diff.File, contextLines int) s
for _, line := range hunk.Lines {
switch line.Type {
case diff.LineRemoved:
- b.WriteString(fmt.Sprintf("%d -%s\n", line.OldNum, line.Content))
+ fmt.Fprintf(&b, "%d -%s\n", line.OldNum, line.Content)
case diff.LineContext:
- b.WriteString(fmt.Sprintf("%d %s\n", line.OldNum, line.Content))
+ fmt.Fprintf(&b, "%d %s\n", line.OldNum, line.Content)
}
}
b.WriteString("\n")
@@ -240,7 +240,7 @@ func BuildPromptEnhanced(concern Concern, files []diff.File, contextLines int) s
}
b.WriteString("\n\n")
- b.WriteString(fmt.Sprintf("Focus on: %s\n", concern.Name))
+ fmt.Fprintf(&b, "Focus on: %s\n", concern.Name)
b.WriteString("Respond with a JSON array of findings.\n")
return b.String()
diff --git a/internal/review/reflect.go b/internal/review/reflect.go
index beee5e3..75bb6ce 100644
--- a/internal/review/reflect.go
+++ b/internal/review/reflect.go
@@ -56,10 +56,10 @@ func BuildReflectPrompt(findings []Finding, diffContext string) string {
b.WriteString("## Findings to validate:\n\n")
for i, f := range findings {
- b.WriteString(fmt.Sprintf("%d. [%s][%s] %s:%d — %s\n",
- i, severityStr(f.Severity), f.Concern, f.File, f.Line, f.Message))
+ fmt.Fprintf(&b, "%d. [%s][%s] %s:%d — %s\n",
+ i, severityStr(f.Severity), f.Concern, f.File, f.Line, f.Message)
if f.Fix != "" {
- b.WriteString(fmt.Sprintf(" Fix: %s\n", f.Fix))
+ fmt.Fprintf(&b, " Fix: %s\n", f.Fix)
}
}
diff --git a/reviewer.go b/reviewer.go
index 8646136..ff77bcc 100644
--- a/reviewer.go
+++ b/reviewer.go
@@ -378,7 +378,7 @@ func toPublicFindings(internal []review.Finding) []Finding {
}
out[i] = Finding{
Concern: f.Concern,
- Severity: Severity(f.Severity),
+ Severity: f.Severity,
File: f.File,
Line: f.Line,
EndLine: f.EndLine,
@@ -530,7 +530,7 @@ func (r *Reviewer) reflect(ctx context.Context, findings []Finding, rawDiff stri
for i, f := range findings {
internalFindings[i] = review.Finding{
Concern: f.Concern,
- Severity: review.Severity(f.Severity),
+ Severity: f.Severity,
File: f.File,
Line: f.Line,
EndLine: f.EndLine,
diff --git a/sast_fusion.go b/sast_fusion.go
index 25c4214..0d162b7 100644
--- a/sast_fusion.go
+++ b/sast_fusion.go
@@ -50,7 +50,7 @@ func (sf *SASTFusion) FormatSASTForPrompt(findings []Finding) string {
b.WriteString("2. DISMISS it if it is a false positive or not actionable.\n")
b.WriteString("If you validate a finding, include it in your response with the original finding's details. ")
b.WriteString("If you dismiss it, include it in your response with action \"dismiss\" and explain why.\n\n")
- b.WriteString(fmt.Sprintf("Found %d potential issues:\n\n", len(findings)))
+ fmt.Fprintf(&b, "Found %d potential issues:\n\n", len(findings))
for i := 0; i < limit; i++ {
f := findings[i]
@@ -67,20 +67,20 @@ func (sf *SASTFusion) FormatSASTForPrompt(findings []Finding) string {
if sf.MaxEvidenceLen > 0 && len(msg) > sf.MaxEvidenceLen {
msg = msg[:sf.MaxEvidenceLen] + "..."
}
- b.WriteString(fmt.Sprintf("- [%s] %s (%s)\n", severity, msg, f.Concern))
- b.WriteString(fmt.Sprintf(" Location: %s\n", loc))
+ fmt.Fprintf(&b, "- [%s] %s (%s)\n", severity, msg, f.Concern)
+ fmt.Fprintf(&b, " Location: %s\n", loc)
if f.Fix != "" {
fix := f.Fix
if sf.MaxEvidenceLen > 0 && len(fix) > sf.MaxEvidenceLen {
fix = fix[:sf.MaxEvidenceLen] + "..."
}
- b.WriteString(fmt.Sprintf(" Fix: %s\n", fix))
+ fmt.Fprintf(&b, " Fix: %s\n", fix)
}
b.WriteString("\n")
}
if len(findings) > limit {
- b.WriteString(fmt.Sprintf("... and %d more findings omitted.\n\n", len(findings)-limit))
+ fmt.Fprintf(&b, "... and %d more findings omitted.\n\n", len(findings)-limit)
}
return b.String()
diff --git a/sast_integration.go b/sast_integration.go
index 28231c5..40238ad 100644
--- a/sast_integration.go
+++ b/sast_integration.go
@@ -72,10 +72,10 @@ func (s *SASTIntegration) BuildReviewPrompt(sastFindings []SASTFinding, diff str
if len(sastFindings) == 0 {
prompt.WriteString("No SAST findings detected. Focus on code quality and logic.\n\n")
} else {
- prompt.WriteString(fmt.Sprintf("Found %d potential issues:\n\n", len(sastFindings)))
+ fmt.Fprintf(&prompt, "Found %d potential issues:\n\n", len(sastFindings))
for _, f := range sastFindings {
- prompt.WriteString(fmt.Sprintf("- **%s** [%s] in %s:%d\n %s\n Evidence: `%s`\n\n",
- f.Rule, f.Severity, f.File, f.Line, f.Message, truncate(f.Evidence, 100)))
+ fmt.Fprintf(&prompt, "- **%s** [%s] in %s:%d\n %s\n Evidence: `%s`\n\n",
+ f.Rule, f.Severity, f.File, f.Line, f.Message, truncate(f.Evidence, 100))
}
}