Explain score contributions
ober
5cd6532f70102d9d68ac6ec3093b70a5377932c8
--- a/README.md +++ b/README.md @@ -63,6 +63,10 @@ and `network_used:false`. counts, metadata/heuristic counts, score-band counts, and signal-category coverage for the selected revision range. +`explain` prints the selected commit's thresholds, raw signals, weighted signal +contributions, corroboration bonus, counter-evidence from zero-score signals, +and warnings. + 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 @@ -729,18 +729,44 @@ (displayln (str "| `" (short-sha (finding-commit f)) "` | " (finding-score f) " | " (finding-verdict f) " | " (finding-author-email f) " | " (finding-subject f) " |")))) +(def (signal-contribution s) + (* (signal-score s) (signal-weight s))) + +(def (corroboration-bonus signals score) + (max 0.0 (- score (weighted-score signals)))) + +(def (threshold-description score) + (cond [(>= score (scan-config-ai-threshold current-config)) "ai threshold met"] + [(>= score (scan-config-human-threshold current-config)) "uncertain threshold met"] + [else "below heuristic thresholds"])) + +(def (zero-score-signals signals) + (filter (lambda (s) (= (signal-score s) 0.0)) signals)) (def (display-explain f) (displayln (str "commit: " (finding-commit f))) (displayln (str "verdict: " (finding-verdict f))) (displayln (str "score: " (finding-score f))) (displayln (str "author: " (finding-author-name f) " <" (finding-author-email f) ">")) (displayln (str "subject: " (finding-subject f))) + (displayln (str "thresholds: human=" (scan-config-human-threshold current-config) + " ai=" (scan-config-ai-threshold current-config) + " result=" (threshold-description (finding-score f)))) (displayln "signals:") (for ([s (finding-signals f)]) (displayln (str "- " (signal-name s) " [" (signal-category s) "] score=" (signal-score s) " weight=" (signal-weight s))) (for ([e (signal-evidence s)]) (displayln (str " evidence: " e)))) + (displayln "contributions:") + (for ([s (finding-signals f)]) + (displayln (str "- " (signal-name s) ": " (signal-contribution s)))) + (displayln (str "corroboration bonus: " (corroboration-bonus (finding-signals f) (finding-score f)))) + (let ([zeros (zero-score-signals (finding-signals f))]) + (if (pair? zeros) + (begin + (displayln "counter-evidence:") + (for ([s zeros]) + (displayln (str "- no positive " (signal-category s) " evidence from " (signal-name s))))))) (if (pair? (finding-warnings f)) (begin (displayln "warnings:") --- a/tests/fixture-smoke.sh +++ b/tests/fixture-smoke.sh @@ -109,6 +109,10 @@ printf '%s\n' "$root_json" | grep -q 'root commit; no parent diff baseline' explain=$("$root/bin/jerboa-aigit" explain "$head_rev" "$fixture") printf '%s\n' "$explain" | grep -q "commit: $head_rev" printf '%s\n' "$explain" | grep -q 'signals:' +printf '%s\n' "$explain" | grep -q 'thresholds:' +printf '%s\n' "$explain" | grep -q 'contributions:' +printf '%s\n' "$explain" | grep -q 'corroboration bonus:' +printf '%s\n' "$explain" | grep -q 'counter-evidence:' markdown=$("$root/bin/jerboa-aigit" scan "$fixture" --format markdown --count 1) printf '%s\n' "$markdown" | grep -q '| commit | score | verdict | author | subject |'