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

- Go + Go License CI

@@ -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)) } }