;; lib/mod/offenders.sx — repeat-offender escalation (audit log as evidence). ;; ;; The append-only audit trail is itself a source of evidence: a subject already ;; sanctioned several times is a repeat offender. mod/decide-escalating decides a ;; report normally, then — if the action is a sanction and the subject has at ;; least k PRIOR sanctions in the audit log — upgrades it to :ban. This is the one ;; place a decision depends on history beyond the single report, and it reads that ;; history from the audit log rather than re-deriving it. (define mod/sanction? (fn (action) (mod/any? (fn (a) (= a action)) (list "hide" "remove" "ban")))) ;; count of prior sanctioning decisions in the audit log about a subject (define mod/subject-sanctions (fn (subject) (reduce (fn (acc e) (let ((r (mod/get-report (get e :report-id)))) (if (nil? r) acc (if (if (= (mod/report-about r) subject) (mod/sanction? (get e :action)) false) (+ acc 1) acc)))) 0 (mod/audit-all)))) (define mod/repeat-offender? (fn (subject k) (<= k (mod/subject-sanctions subject)))) (define mod/decide-escalating (fn (id k) (let ((r (mod/get-report id))) (if (nil? r) nil (let ((priors (mod/subject-sanctions (mod/report-about r)))) (let ((d (mod/decide id))) (if (if (mod/sanction? (get d :action)) (<= k priors) false) {:action "ban" :proof {:goals (get (get d :proof) :goals) :prior-sanctions priors :evidence (get (get d :proof) :evidence) :conditions (list) :rule "repeat-offender-ban" :count (get (get d :proof) :count)} :report-id id :rule "repeat-offender-ban" :strategy "escalating"} d)))))))