refactor(ax): round 6 AX sweep — usage examples, test coverage, package docs
Some checks failed
Security Scan / security (push) Successful in 9s
Test / test (push) Failing after 36s

- Add usage-example comments (AX-2) to all private run* and add*Command
  functions in cmd/security and cmd/metrics
- Add package-level doc comment to empty cmd/security/cmd.go (AX-3)
- Add usage-example comment to cmd/rag/cmd.go re-export
- Add Bad and Ugly test categories to ai/metrics_test.go (AX-10):
  TestMetrics_Record_Bad_DirectoryAsFile, TestMetrics_ReadEvents_Bad_InvalidHome,
  TestMetrics_Record_Ugly_ConcurrentWrites
- Document the embed-bench init() side-effect with intent comment (AX-5)

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-03-31 14:12:12 +01:00
parent bc3b36c3da
commit 45e76101bf
10 changed files with 110 additions and 1 deletions

View file

@ -156,6 +156,64 @@ func TestMetrics_ReadEvents_Good_FiltersBySince(t *testing.T) {
}
}
func TestMetrics_Record_Bad_DirectoryAsFile(t *testing.T) {
// If the home directory resolution fails, Record must return an error.
origHome := os.Getenv("HOME")
os.Setenv("HOME", "/dev/null/nonexistent")
t.Cleanup(func() { os.Setenv("HOME", origHome) })
event := Event{Type: "bad_test"}
err := Record(event)
if err == nil {
t.Error("expected error when home directory is invalid, got nil")
}
}
func TestMetrics_ReadEvents_Bad_InvalidHome(t *testing.T) {
// ReadEvents must propagate the error when home resolution fails.
origHome := os.Getenv("HOME")
os.Setenv("HOME", "/dev/null/nonexistent")
t.Cleanup(func() { os.Setenv("HOME", origHome) })
_, err := ReadEvents(time.Now().Add(-time.Hour))
if err == nil {
t.Error("expected error when home directory is invalid, got nil")
}
}
func TestMetrics_Record_Ugly_ConcurrentWrites(t *testing.T) {
// Concurrent writes must not corrupt the JSONL file — all events must be readable.
withTempHome(t)
const goroutines = 10
const eventsPerGoroutine = 20
done := make(chan struct{}, goroutines)
for range goroutines {
go func() {
defer func() { done <- struct{}{} }()
for range eventsPerGoroutine {
if err := Record(Event{Type: "concurrent"}); err != nil {
t.Errorf("concurrent Record: %v", err)
return
}
}
}()
}
for range goroutines {
<-done
}
events, err := ReadEvents(time.Now().Add(-time.Hour))
if err != nil {
t.Fatalf("ReadEvents after concurrent writes: %v", err)
}
expected := goroutines * eventsPerGoroutine
if len(events) != expected {
t.Errorf("expected %d events after concurrent writes, got %d", expected, len(events))
}
}
func TestMetrics_ReadMetricsFile_Good_MalformedLines(t *testing.T) {
withTempHome(t)

View file

@ -330,5 +330,7 @@ func truncate(text string, limit int) string {
}
func init() {
os.Stderr.Sync()
// Flush stderr before flag parsing so any buffered output is visible if the process is
// interrupted during startup (e.g. Ollama not running).
os.Stderr.Sync() //nolint:errcheck // sync on startup, error is not actionable
}

View file

@ -28,6 +28,9 @@ var metricsCmd = &cli.Command{
},
}
// initMetricsFlags binds the --since and --json flags to the metrics command.
//
// initMetricsFlags() // called once by AddMetricsCommand
func initMetricsFlags() {
metricsCmd.Flags().StringVar(&metricsSince, "since", "7d", i18n.T("cmd.ai.metrics.flag.since"))
metricsCmd.Flags().BoolVar(&metricsJSON, "json", false, i18n.T("common.flag.json"))
@ -41,6 +44,10 @@ func AddMetricsCommand(parent *cli.Command) {
parent.AddCommand(metricsCmd)
}
// runMetrics reads and displays AI event metrics for the configured time window.
//
// // via CLI: core ai metrics --since 7d --json
// runMetrics()
func runMetrics() error {
sinceDuration, err := parseDuration(metricsSince)
if err != nil {

View file

@ -4,4 +4,6 @@ package rag
import ragcmd "forge.lthn.ai/core/go-rag/cmd/rag"
// AddRAGSubcommands registers RAG commands as subcommands of parent.
//
// rag.AddRAGSubcommands(aiCmd) // → core ai rag index|query|status
var AddRAGSubcommands = ragcmd.AddRAGSubcommands

View file

@ -1 +1,6 @@
// Package security implements the security command tree for the Core CLI.
//
// Commands registered:
//
// security.AddSecurityCommands(rootCmd) // → core security alerts|deps|scan|secrets|jobs
package security

View file

@ -8,6 +8,9 @@ import (
"forge.lthn.ai/core/cli/pkg/cli"
)
// addAlertsCommand registers the alerts subcommand under parent.
//
// addAlertsCommand(securityCmd) // → core security alerts --repo core-php --severity high
func addAlertsCommand(parent *cli.Command) {
command := &cli.Command{
Use: "alerts",
@ -41,6 +44,10 @@ type AlertOutput struct {
Message string `json:"message"`
}
// runAlerts fetches and displays unified security alerts across all repos or a single target.
//
// // via CLI: core security alerts --repo core-php --severity high
// runAlerts()
func runAlerts() error {
if err := checkGH(); err != nil {
return err

View file

@ -8,6 +8,9 @@ import (
"forge.lthn.ai/core/cli/pkg/cli"
)
// addDepsCommand registers the deps subcommand under parent.
//
// addDepsCommand(securityCmd) // → core security deps --repo core-php --severity critical
func addDepsCommand(parent *cli.Command) {
command := &cli.Command{
Use: "deps",
@ -42,6 +45,10 @@ type DepAlert struct {
Summary string `json:"summary"`
}
// runDeps fetches and displays Dependabot vulnerability alerts across all repos or a single target.
//
// // via CLI: core security deps --repo core-php --severity critical
// runDeps()
func runDeps() error {
if err := checkGH(); err != nil {
return err

View file

@ -19,6 +19,9 @@ var (
jobsCopies int
)
// addJobsCommand registers the jobs subcommand under parent.
//
// addJobsCommand(securityCmd) // → core security jobs --targets wailsapp/wails --issue-repo host-uk/core
func addJobsCommand(parent *cli.Command) {
command := &cli.Command{
Use: "jobs",
@ -37,6 +40,10 @@ func addJobsCommand(parent *cli.Command) {
parent.AddCommand(command)
}
// runJobs aggregates security findings for each target and creates GitHub issues.
//
// // via CLI: core security jobs --targets wailsapp/wails,facebook/react --dry-run
// runJobs()
func runJobs() error {
if err := checkGH(); err != nil {
return err

View file

@ -14,6 +14,9 @@ var (
scanTool string
)
// addScanCommand registers the scan subcommand under parent.
//
// addScanCommand(securityCmd) // → core security scan --repo core-php --tool gosec
func addScanCommand(parent *cli.Command) {
command := &cli.Command{
Use: "scan",
@ -48,6 +51,10 @@ type ScanAlert struct {
Message string `json:"message"`
}
// runScan fetches and displays code-scanning alerts across all repos or a single target.
//
// // via CLI: core security scan --repo core-php --tool gosec
// runScan()
func runScan() error {
if err := checkGH(); err != nil {
return err

View file

@ -8,6 +8,9 @@ import (
"forge.lthn.ai/core/cli/pkg/cli"
)
// addSecretsCommand registers the secrets subcommand under parent.
//
// addSecretsCommand(securityCmd) // → core security secrets --repo core-php --json
func addSecretsCommand(parent *cli.Command) {
command := &cli.Command{
Use: "secrets",
@ -38,6 +41,10 @@ type SecretAlert struct {
PushProtection bool `json:"push_protection_bypassed"`
}
// runSecrets fetches and displays secret-scanning alerts across all repos or a single target.
//
// // via CLI: core security secrets --repo core-php
// runSecrets()
func runSecrets() error {
if err := checkGH(); err != nil {
return err