Expand stats coverage summary
ober
733988cc8adfdce6004aaba08883647a609885bf
--- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ JSON output. `--llm` is accepted as an explicit request, but this release has no active provider adapter; it emits a warning and still reports `llm_used:false` and `network_used:false`. +`stats` reports commit count, distinct authors, recorded tools, recorded AI line +counts, metadata/heuristic counts, score-band counts, and signal-category +coverage for the selected revision range. + Merge commits default to first-parent diffs. Use `--all-parents` to inspect per-parent merge diffs via Git's `-m` mode; merge warnings state which mode was used. --- a/main-binary.ss +++ b/main-binary.ss @@ -745,11 +745,48 @@ (begin (displayln "warnings:") (for ([w (finding-warnings f)]) (displayln (str "- " w)))))) +(def stats-verdicts '("recorded-ai-authorship" "metadata-indicated-agent" "likely-ai-assisted" "mixed-uncertain" "likely-human-style" "insufficient-evidence")) +(def stats-signal-categories '("text" "code" "structure" "similarity" "history" "baseline")) + +(def (alist-ref/default pairs name fallback) + (let ([hit (assoc name pairs)]) + (if hit (cdr hit) fallback))) + +(def (attribution-line-count item) + (let ([start (alist-ref/default item 'start 0)] + [end (alist-ref/default item 'end 0)]) + (if (and (number? start) (number? end) (>= end start)) + (+ 1 (- end start)) + 0))) + +(def (finding-recorded-line-count f) + (sum (map attribution-line-count (finding-attribution f)))) + +(def (finding-attribution-tools f) + (unique (filter (lambda (tool) (not (string-empty? tool))) + (map (lambda (item) (alist-ref/default item 'tool "")) (finding-attribution f))))) + +(def (stats-tools findings) + (unique (append-map finding-attribution-tools findings))) + +(def (finding-has-signal-category? f category) + (for/or ([s (finding-signals f)]) + (same-public-string? (signal-category s) category))) (def (display-stats findings) - (displayln (str "commits: " (length findings))) - (displayln (str "recorded AI notes: " (count-where (lambda (f) (not (string-empty? (finding-note f)))) findings))) - (displayln (str "metadata indicated agents: " (count-where (lambda (f) (pair? (finding-metadata f))) findings))) - (displayln (str "likely AI-assisted by heuristics: " (count-where (lambda (f) (same-public-string? (finding-verdict f) "likely-ai-assisted")) findings)))) + (let ([tools (stats-tools findings)]) + (displayln (str "commits: " (length findings))) + (displayln (str "authors: " (length (unique (map finding-author-email findings))))) + (displayln (str "tools: " (if (null? tools) "none" (string-join tools ",")))) + (displayln (str "recorded AI notes: " (count-where (lambda (f) (not (string-empty? (finding-note f)))) findings))) + (displayln (str "recorded AI lines: " (sum (map finding-recorded-line-count findings)))) + (displayln (str "metadata indicated agents: " (count-where (lambda (f) (pair? (finding-metadata f))) findings))) + (displayln (str "likely AI-assisted by heuristics: " (count-where (lambda (f) (same-public-string? (finding-verdict f) "likely-ai-assisted")) findings))) + (displayln "score bands:") + (for ([v stats-verdicts]) + (displayln (str " " v ": " (count-where (lambda (f) (same-public-string? (finding-verdict f) v)) findings)))) + (displayln "signal coverage:") + (for ([category stats-signal-categories]) + (displayln (str " " category ": " (count-where (lambda (f) (finding-has-signal-category? f category)) findings)))))) (def (default-options) (make-options "scan" "." 50 "table" #f #f #f #f 0 #f #f)) (def (config-value obj field fallback) --- a/tests/fixture-smoke.sh +++ b/tests/fixture-smoke.sh @@ -86,7 +86,14 @@ printf '%s\n' "$metadata" | grep -q '"score":0.0' stats=$("$root/bin/jerboa-aigit" stats "$fixture" --count 2) printf '%s\n' "$stats" | grep -q 'commits: 2' +printf '%s\n' "$stats" | grep -q 'authors: 2' +printf '%s\n' "$stats" | grep -q 'tools: codex' printf '%s\n' "$stats" | grep -q 'recorded AI notes: 1' +printf '%s\n' "$stats" | grep -q 'recorded AI lines: 360' +printf '%s\n' "$stats" | grep -q 'score bands:' +printf '%s\n' "$stats" | grep -q ' recorded-ai-authorship: 1' +printf '%s\n' "$stats" | grep -q 'signal coverage:' +printf '%s\n' "$stats" | grep -q ' code: 2' jsonl=$("$root/bin/jerboa-aigit" scan "$fixture" --format jsonl --count 2) jsonl_lines=$(printf '%s\n' "$jsonl" | wc -l | tr -d ' ')