refactor(ax): round 4 AX sweep — test naming, variable names, usage examples
All checks were successful
Security Scan / security (push) Successful in 11s
Test / test (push) Successful in 57s

- 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 <virgil@lethean.io>
This commit is contained in:
Snider 2026-03-31 06:44:11 +01:00
parent 4256cefffa
commit 035a5b7e53
6 changed files with 42 additions and 36 deletions

View file

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

View file

@ -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 {

View file

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

View file

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

View file

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

View file

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