Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
mod/decision-diff compares one report's action under two rule sets; mod/policy-impact batches a set and returns only the reports whose decision flips; mod/impact-count / mod/impact-report summarize. Lets a mod team measure a policy change's blast radius before shipping (e.g. removing spam-hide flips r1 hide→keep). Pure SX over decide-report. +13 tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
118 lines
3.3 KiB
Plaintext
118 lines
3.3 KiB
Plaintext
;; lib/mod/tests/whatif.sx — Ext 10: policy what-if / impact analysis.
|
|
|
|
(define mod-wi-count 0)
|
|
(define mod-wi-pass 0)
|
|
(define mod-wi-fail 0)
|
|
(define mod-wi-failures (list))
|
|
|
|
(define
|
|
mod-wi-test!
|
|
(fn
|
|
(name got expected)
|
|
(begin
|
|
(set! mod-wi-count (+ mod-wi-count 1))
|
|
(if
|
|
(= got expected)
|
|
(set! mod-wi-pass (+ mod-wi-pass 1))
|
|
(begin
|
|
(set! mod-wi-fail (+ mod-wi-fail 1))
|
|
(append!
|
|
mod-wi-failures
|
|
(str name "\n expected: " expected "\n got: " got)))))))
|
|
|
|
;; rules-b is the default policy with spam-hide removed: spam now falls through
|
|
;; to default-keep. A spam report flips hide → keep; everything else is unchanged.
|
|
(define mod-wi-rules-a mod/default-rules)
|
|
(define
|
|
mod-wi-rules-b
|
|
(list
|
|
(mod/mk-rule
|
|
"reviewer-remove"
|
|
:remove (list (list :evidence "confirmed-abuse")))
|
|
(mod/mk-rule
|
|
"abuse-remove"
|
|
:remove (list (list :classification "abuse")))
|
|
(mod/mk-rule
|
|
"repeated-escalate"
|
|
:escalate (list (list :count-at-least 3)))
|
|
(mod/mk-rule "default-keep" :keep (list))))
|
|
|
|
(define mod-wi-spam (mod/mk-report "r1" "a" "bob" "this is spam"))
|
|
(define mod-wi-abuse (mod/mk-report "r2" "a" "carol" "harassment here"))
|
|
(define mod-wi-clean (mod/mk-report "r3" "a" "dave" "a fine post"))
|
|
|
|
;; ── single-report diff ──
|
|
|
|
(define
|
|
mod-wi-d
|
|
(mod/decision-diff
|
|
mod-wi-spam
|
|
(list mod-wi-spam)
|
|
mod-wi-rules-a
|
|
mod-wi-rules-b))
|
|
(mod-wi-test! "spam before = hide" (get mod-wi-d :before) "hide")
|
|
(mod-wi-test! "spam after = keep" (get mod-wi-d :after) "keep")
|
|
(mod-wi-test! "spam decision flips" (get mod-wi-d :changed) true)
|
|
(mod-wi-test! "diff carries report id" (get mod-wi-d :report-id) "r1")
|
|
|
|
(define
|
|
mod-wi-da
|
|
(mod/decision-diff
|
|
mod-wi-abuse
|
|
(list mod-wi-abuse)
|
|
mod-wi-rules-a
|
|
mod-wi-rules-b))
|
|
(mod-wi-test! "abuse unchanged (remove both)" (get mod-wi-da :changed) false)
|
|
(mod-wi-test! "abuse stays remove" (get mod-wi-da :after) "remove")
|
|
|
|
(define
|
|
mod-wi-dc
|
|
(mod/decision-diff
|
|
mod-wi-clean
|
|
(list mod-wi-clean)
|
|
mod-wi-rules-a
|
|
mod-wi-rules-b))
|
|
(mod-wi-test! "clean unchanged (keep both)" (get mod-wi-dc :changed) false)
|
|
|
|
;; ── batch impact ──
|
|
|
|
(define mod-wi-batch (list mod-wi-spam mod-wi-abuse mod-wi-clean))
|
|
(define
|
|
mod-wi-impact
|
|
(mod/policy-impact mod-wi-batch mod-wi-rules-a mod-wi-rules-b))
|
|
|
|
(mod-wi-test!
|
|
"impact lists only changed reports"
|
|
(len mod-wi-impact)
|
|
1)
|
|
(mod-wi-test!
|
|
"impacted report is the spam one"
|
|
(get (first mod-wi-impact) :report-id)
|
|
"r1")
|
|
(mod-wi-test!
|
|
"impact-count agrees"
|
|
(mod/impact-count mod-wi-batch mod-wi-rules-a mod-wi-rules-b)
|
|
1)
|
|
|
|
;; ── identical rule sets → no impact ──
|
|
|
|
(mod-wi-test!
|
|
"same rules → zero impact"
|
|
(mod/impact-count mod-wi-batch mod-wi-rules-a mod-wi-rules-a)
|
|
0)
|
|
(mod-wi-test!
|
|
"same rules → empty report"
|
|
(mod/impact-report mod-wi-batch mod-wi-rules-a mod-wi-rules-a)
|
|
"No decisions change.")
|
|
|
|
;; ── rendering ──
|
|
|
|
(mod-wi-test!
|
|
"impact-report renders the flip"
|
|
(mod/str-contains?
|
|
(mod/impact-report mod-wi-batch mod-wi-rules-a mod-wi-rules-b)
|
|
"r1: hide → keep")
|
|
true)
|
|
|
|
(define mod-whatif-tests-run! (fn () {:failures mod-wi-failures :total mod-wi-count :passed mod-wi-pass :failed mod-wi-fail}))
|