Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions internal/cli/cli.go

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of a helper function for one print statement?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair question. Without extracting it, the only way to test the exact composed string is to run the whole runCheck → Engine.Run → llm.AnalyzeDrift pipeline for real, which is what the first version of this PR did — and that's exactly what paid the 14s backoff tax and duplicated coverage internal/analysis already has. This isn't meant as a general-purpose abstraction, just a minimal seam so the Printf's exact wording is callable in isolation. Happy to revert to the integration-style test (eating the 14s) or drop this test angle entirely if you'd rather not have the extra functions — your call.

Original file line number Diff line number Diff line change
Expand Up @@ -495,15 +495,25 @@ func runCheck(cfg *config.Config, chatProvider, embedProvider llm.Provider, inde
if err := engine.CollectedBaseline.Save(baseline.Path); err != nil {
return ExitError, fmt.Errorf("failed to write baseline file %s: %v", baseline.Path, err)
}
fmt.Printf("Baseline scan complete: %d violation(s) recorded, %d file(s) skipped due to errors, %d ADR check(s) skipped due to LLM errors.\n", len(engine.CollectedBaseline.Entries), engine.SkippedFiles, engine.SkippedADRChecks)
fmt.Printf("Baseline written to %s (%d violation(s) recorded).\n", baseline.Path, len(engine.CollectedBaseline.Entries))
fmt.Println(formatBaselineScanSummary(len(engine.CollectedBaseline.Entries), engine.SkippedFiles, engine.SkippedADRChecks))
fmt.Println(formatBaselineWrittenSummary(baseline.Path, len(engine.CollectedBaseline.Entries)))
return ExitSuccess, nil
}

fmt.Println("No new architectural violations found.")
return ExitSuccess, nil
}

// formatBaselineScanSummary is its own function so runCheck's exact summary
// wording is unit-testable without the engine/LLM pipeline that feeds it.
func formatBaselineScanSummary(violations, skippedFiles, skippedADRChecks int) string {
return fmt.Sprintf("Baseline scan complete: %d violation(s) recorded, %d file(s) skipped due to errors, %d ADR check(s) skipped due to LLM errors.", violations, skippedFiles, skippedADRChecks)
}

func formatBaselineWrittenSummary(path string, violations int) string {
return fmt.Sprintf("Baseline written to %s (%d violation(s) recorded).", path, violations)
}

// resolveContentProvider picks the ContentProvider for a check run.
// updateBaseline forces a full-repo scan, overriding any other flag.
func resolveContentProvider(files []string, staged, all, updateBaseline bool) analysis.ContentProvider {
Expand Down
37 changes: 37 additions & 0 deletions internal/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,40 @@ func TestExecute_NormalizesPositionalArgPath_EvenWhenCwdEqualsRepoRoot(t *testin
t.Errorf("expected the uncleaned positional path to be normalized to %q by Execute itself even though cwd == repoRoot, got %q", "file.go", os.Args[2])
}
}

func TestFormatBaselineScanSummary(t *testing.T) {
tests := []struct {
name string
violations, skippedFiles, skippedADRChecks int
want string
}{
{
name: "all zero", violations: 0, skippedFiles: 0, skippedADRChecks: 0,
want: "Baseline scan complete: 0 violation(s) recorded, 0 file(s) skipped due to errors, 0 ADR check(s) skipped due to LLM errors.",
},
{
name: "nonzero ADR checks skipped", violations: 1, skippedFiles: 0, skippedADRChecks: 1,
want: "Baseline scan complete: 1 violation(s) recorded, 0 file(s) skipped due to errors, 1 ADR check(s) skipped due to LLM errors.",
},
{
name: "all nonzero, distinct values", violations: 3, skippedFiles: 2, skippedADRChecks: 5,
want: "Baseline scan complete: 3 violation(s) recorded, 2 file(s) skipped due to errors, 5 ADR check(s) skipped due to LLM errors.",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := formatBaselineScanSummary(tt.violations, tt.skippedFiles, tt.skippedADRChecks)
if got != tt.want {
t.Errorf("formatBaselineScanSummary(%d, %d, %d) = %q, want %q", tt.violations, tt.skippedFiles, tt.skippedADRChecks, got, tt.want)
}
})
}
}

func TestFormatBaselineWrittenSummary(t *testing.T) {
got := formatBaselineWrittenSummary("archguard-baseline.json", 3)
want := "Baseline written to archguard-baseline.json (3 violation(s) recorded)."
if got != want {
t.Errorf("formatBaselineWrittenSummary(...) = %q, want %q", got, want)
}
}