Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 47s
mod/explain renders a decision's proof tree into legible text: action + rule,
evidence line, and each derivation goal with [proved]/[unproved] and the
unification bindings that satisfied it (e.g. {B=ann, N=3, S=dave}). Pure SX over
the Phase-2 proof data — the audit trail's 'why' made readable. +10 tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
1.5 KiB
Plaintext
56 lines
1.5 KiB
Plaintext
;; lib/mod/explain.sx — human-readable proof explanation.
|
|
;;
|
|
;; Turns a decision (from mod/decide-report, or any audit entry) into a readable
|
|
;; multi-line "why": the action, the rule that fired, the evidence in play, and
|
|
;; the derivation goal-by-goal with [proved]/[unproved] marks and the unification
|
|
;; bindings that satisfied each goal. Pure SX over the Phase-2 proof tree.
|
|
|
|
(define
|
|
mod/explain-binds
|
|
(fn
|
|
(binds)
|
|
(mod/join-with
|
|
", "
|
|
(map (fn (k) (str k "=" (dict-get binds k))) (keys binds)))))
|
|
|
|
(define
|
|
mod/explain-goal
|
|
(fn
|
|
(g)
|
|
(let
|
|
((mark (if (get g :solved) " [proved] " " [unproved] "))
|
|
(binds (get g :bindings)))
|
|
(if
|
|
(empty? (keys binds))
|
|
(str mark (get g :goal))
|
|
(str mark (get g :goal) " {" (mod/explain-binds binds) "}")))))
|
|
|
|
(define
|
|
mod/explain-evidence
|
|
(fn
|
|
(evidence)
|
|
(if
|
|
(empty? evidence)
|
|
"Evidence: (none)"
|
|
(str "Evidence: " (mod/join-with ", " evidence)))))
|
|
|
|
(define
|
|
mod/explain
|
|
(fn
|
|
(decision)
|
|
(let
|
|
((id (get decision :report-id))
|
|
(action (get decision :action))
|
|
(rule (get decision :rule))
|
|
(proof (get decision :proof)))
|
|
(let
|
|
((goals (get proof :goals)) (evidence (get proof :evidence)))
|
|
(mod/join-with
|
|
"\n"
|
|
(append
|
|
(list
|
|
(str "Report " id ": " action " (rule: " rule ")")
|
|
(mod/explain-evidence evidence)
|
|
"Because:")
|
|
(map mod/explain-goal goals)))))))
|