From 035a5b7e53674837a2eef52ee3858454214a1c9f Mon Sep 17 00:00:00 2001 From: Snider Date: Tue, 31 Mar 2026 06:44:11 +0100 Subject: [PATCH] =?UTF-8?q?refactor(ax):=20round=204=20AX=20sweep=20?= =?UTF-8?q?=E2=80=94=20test=20naming,=20variable=20names,=20usage=20exampl?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename all test functions in metrics_test.go to TestFilename_Function_{Good,Bad,Ugly} convention (TestMetrics_Record_*, TestMetrics_ReadEvents_*, etc.) - Rename cmd_test.go tests to TestCmd_ParseDuration_{Good,Bad} - Rename bench test TestMetricsBench_RecordAndRead_10K_Good and replace inline HOME setup with withTempHome helper - Replace short vars sev/unit/value with severityLower/unitChar/numericPart in filterBySeverity and parseDuration - Add usage-example comments to embed/avg/qualityLabel/truncate/modelAvailable in embed-bench Co-Authored-By: Virgil --- ai/metrics_bench_test.go | 16 +++------------- ai/metrics_test.go | 26 +++++++++++++------------- cmd/embed-bench/main.go | 16 ++++++++++++++++ cmd/metrics/cmd.go | 10 +++++----- cmd/metrics/cmd_test.go | 4 ++-- cmd/security/cmd_security.go | 6 +++--- 6 files changed, 42 insertions(+), 36 deletions(-) diff --git a/ai/metrics_bench_test.go b/ai/metrics_bench_test.go index 6d90088..fe16bb7 100644 --- a/ai/metrics_bench_test.go +++ b/ai/metrics_bench_test.go @@ -189,19 +189,9 @@ func BenchmarkMetricsRecordAndQuery(b *testing.B) { // --- Unit tests for metrics at scale --- -// TestMetricsRecordAndRead_10K_Good writes 10K events and reads them back. -func TestMetricsRecordAndRead_10K_Good(t *testing.T) { - // Override HOME to temp dir - origHome := os.Getenv("HOME") - tmpHome := t.TempDir() - metricsPath := filepath.Join(tmpHome, ".core", "ai", "metrics") - if err := coreio.Local.EnsureDir(metricsPath); err != nil { - t.Fatalf("Failed to create metrics dir: %v", err) - } - os.Setenv("HOME", tmpHome) - t.Cleanup(func() { - os.Setenv("HOME", origHome) - }) +// TestMetricsBench_RecordAndRead_10K_Good writes 10K events and reads them back. +func TestMetricsBench_RecordAndRead_10K_Good(t *testing.T) { + withTempHome(t) now := time.Now() const n = 10_000 diff --git a/ai/metrics_test.go b/ai/metrics_test.go index d4363c2..45431ed 100644 --- a/ai/metrics_test.go +++ b/ai/metrics_test.go @@ -24,7 +24,7 @@ func withTempHome(t *testing.T) { // --- Record --- -func TestRecord_Good(t *testing.T) { +func TestMetrics_Record_Good(t *testing.T) { withTempHome(t) ev := Event{ @@ -52,7 +52,7 @@ func TestRecord_Good(t *testing.T) { } } -func TestRecord_Good_AutoTimestamp(t *testing.T) { +func TestMetrics_Record_Good_AutoTimestamp(t *testing.T) { withTempHome(t) before := time.Now() @@ -75,7 +75,7 @@ func TestRecord_Good_AutoTimestamp(t *testing.T) { } } -func TestRecord_Good_PresetTimestamp(t *testing.T) { +func TestMetrics_Record_Good_PresetTimestamp(t *testing.T) { withTempHome(t) fixed := time.Date(2026, 3, 15, 10, 0, 0, 0, time.UTC) @@ -98,7 +98,7 @@ func TestRecord_Good_PresetTimestamp(t *testing.T) { // --- ReadEvents --- -func TestReadEvents_Good_Empty(t *testing.T) { +func TestMetrics_ReadEvents_Good_Empty(t *testing.T) { withTempHome(t) events, err := ReadEvents(time.Now().Add(-24 * time.Hour)) @@ -110,7 +110,7 @@ func TestReadEvents_Good_Empty(t *testing.T) { } } -func TestReadEvents_Good_MultiDay(t *testing.T) { +func TestMetrics_ReadEvents_Good_MultiDay(t *testing.T) { withTempHome(t) now := time.Now() @@ -138,7 +138,7 @@ func TestReadEvents_Good_MultiDay(t *testing.T) { } } -func TestReadEvents_Good_FiltersBySince(t *testing.T) { +func TestMetrics_ReadEvents_Good_FiltersBySince(t *testing.T) { withTempHome(t) now := time.Now() @@ -167,7 +167,7 @@ func TestReadEvents_Good_FiltersBySince(t *testing.T) { // --- readMetricsFile --- -func TestReadMetricsFile_Good_MalformedLines(t *testing.T) { +func TestMetrics_ReadMetricsFile_Good_MalformedLines(t *testing.T) { withTempHome(t) dir, err := metricsDir() @@ -195,7 +195,7 @@ not-json } } -func TestReadMetricsFile_Good_NonExistent(t *testing.T) { +func TestMetrics_ReadMetricsFile_Good_NonExistent(t *testing.T) { events, err := readMetricsFile("/tmp/nonexistent-metrics-file.jsonl", time.Time{}) if err != nil { t.Fatalf("expected nil error for missing file, got: %v", err) @@ -207,7 +207,7 @@ func TestReadMetricsFile_Good_NonExistent(t *testing.T) { // --- metricsFilePath --- -func TestMetricsFilePath_Good(t *testing.T) { +func TestMetrics_MetricsFilePath_Good(t *testing.T) { ts := time.Date(2026, 3, 17, 14, 30, 0, 0, time.UTC) got := metricsFilePath("/base", ts) want := "/base/2026-03-17.jsonl" @@ -218,7 +218,7 @@ func TestMetricsFilePath_Good(t *testing.T) { // --- Summary --- -func TestSummary_Good_Empty(t *testing.T) { +func TestMetrics_Summary_Good_Empty(t *testing.T) { s := Summary(nil) total, ok := s["total"].(int) if !ok || total != 0 { @@ -226,7 +226,7 @@ func TestSummary_Good_Empty(t *testing.T) { } } -func TestSummary_Good(t *testing.T) { +func TestMetrics_Summary_Good(t *testing.T) { events := []Event{ {Type: "build", Repo: "core-php", AgentID: "agent-1"}, {Type: "build", Repo: "core-php", AgentID: "agent-2"}, @@ -252,14 +252,14 @@ func TestSummary_Good(t *testing.T) { // --- sortedMap --- -func TestSortedMap_Good_Empty(t *testing.T) { +func TestMetrics_SortedMap_Good_Empty(t *testing.T) { result := sortedMap(map[string]int{}) if len(result) != 0 { t.Errorf("expected empty slice, got %d entries", len(result)) } } -func TestSortedMap_Good_Ordering(t *testing.T) { +func TestMetrics_SortedMap_Good_Ordering(t *testing.T) { m := map[string]int{"a": 1, "b": 3, "c": 2} result := sortedMap(m) if len(result) != 3 { diff --git a/cmd/embed-bench/main.go b/cmd/embed-bench/main.go index ff7f3e1..d59ae6b 100644 --- a/cmd/embed-bench/main.go +++ b/cmd/embed-bench/main.go @@ -233,6 +233,9 @@ type embedResponse struct { Embedding []float64 `json:"embedding"` } +// embed requests a vector embedding from Ollama for the given model and text. +// +// vec, _ := embed("nomic-embed-text", "how does the brain recall work?") func embed(model, text string) ([]float64, error) { body, _ := json.Marshal(embedRequest{Model: model, Prompt: text}) resp, err := httpClient.Post(*ollamaURL+"/api/embeddings", "application/json", bytes.NewReader(body)) @@ -253,6 +256,9 @@ func embed(model, text string) ([]float64, error) { return result.Embedding, nil } +// modelAvailable returns true if the model is listed in Ollama's local tag registry. +// +// modelAvailable("nomic-embed-text") // → true if pulled func modelAvailable(model string) bool { resp, err := httpClient.Get(*ollamaURL + "/api/tags") if err != nil { @@ -292,6 +298,9 @@ func cosine(a, b []float64) float64 { return dot / denom } +// avg returns the arithmetic mean of a float64 slice, or 0 for an empty slice. +// +// avg([]float64{0.8, 0.6, 0.9}) // → 0.7666... func avg(vals []float64) float64 { if len(vals) == 0 { return 0 @@ -303,6 +312,10 @@ func avg(vals []float64) float64 { return sum / float64(len(vals)) } +// qualityLabel maps a cosine separation gap to a human-readable quality band. +// +// qualityLabel(0.18) // → "(excellent)" +// qualityLabel(0.03) // → "(poor)" func qualityLabel(gap float64) string { switch { case gap > 0.15: @@ -316,6 +329,9 @@ func qualityLabel(gap float64) string { } } +// truncate shortens s to at most n characters, appending "..." if truncated. +// +// truncate("How does the emotional scoring work?", 20) // → "How does the emot..." func truncate(s string, n int) string { if len(s) <= n { return s diff --git a/cmd/metrics/cmd.go b/cmd/metrics/cmd.go index c3f63e3..811ba87 100644 --- a/cmd/metrics/cmd.go +++ b/cmd/metrics/cmd.go @@ -110,11 +110,11 @@ func parseDuration(s string) (time.Duration, error) { return 0, coreerr.E("metrics.parseDuration", fmt.Sprintf("invalid duration: %s", s), nil) } - unit := s[len(s)-1] - value := s[:len(s)-1] + unitChar := s[len(s)-1] + numericPart := s[:len(s)-1] var count int - if _, err := fmt.Sscanf(value, "%d", &count); err != nil { + if _, err := fmt.Sscanf(numericPart, "%d", &count); err != nil { return 0, coreerr.E("metrics.parseDuration", fmt.Sprintf("invalid duration: %s", s), nil) } @@ -122,7 +122,7 @@ func parseDuration(s string) (time.Duration, error) { return 0, coreerr.E("metrics.parseDuration", fmt.Sprintf("duration must be positive: %s", s), nil) } - switch unit { + switch unitChar { case 'd': return time.Duration(count) * 24 * time.Hour, nil case 'h': @@ -130,6 +130,6 @@ func parseDuration(s string) (time.Duration, error) { case 'm': return time.Duration(count) * time.Minute, nil default: - return 0, coreerr.E("metrics.parseDuration", fmt.Sprintf("unknown unit %c in duration: %s", unit, s), nil) + return 0, coreerr.E("metrics.parseDuration", fmt.Sprintf("unknown unit %c in duration: %s", unitChar, s), nil) } } diff --git a/cmd/metrics/cmd_test.go b/cmd/metrics/cmd_test.go index 7fb9c78..4712151 100644 --- a/cmd/metrics/cmd_test.go +++ b/cmd/metrics/cmd_test.go @@ -5,7 +5,7 @@ import ( "time" ) -func TestParseDuration_Good(t *testing.T) { +func TestCmd_ParseDuration_Good(t *testing.T) { tests := []struct { input string want time.Duration @@ -29,7 +29,7 @@ func TestParseDuration_Good(t *testing.T) { } } -func TestParseDuration_Bad(t *testing.T) { +func TestCmd_ParseDuration_Bad(t *testing.T) { bad := []string{ "", // too short "d", // too short diff --git a/cmd/security/cmd_security.go b/cmd/security/cmd_security.go index e161714..5428b6f 100644 --- a/cmd/security/cmd_security.go +++ b/cmd/security/cmd_security.go @@ -188,9 +188,9 @@ func filterBySeverity(severity, filter string) bool { return true } - sev := strings.ToLower(severity) - return slices.ContainsFunc(slices.Collect(strings.SplitSeq(strings.ToLower(filter), ",")), func(s string) bool { - return strings.TrimSpace(s) == sev + severityLower := strings.ToLower(severity) + return slices.ContainsFunc(slices.Collect(strings.SplitSeq(strings.ToLower(filter), ",")), func(filterEntry string) bool { + return strings.TrimSpace(filterEntry) == severityLower }) }