///|
/// Decision-mode comparison matrix.
///
/// The matrix operation decides every fact record under all three
/// modes side by side: first, all and unique. For each record it
/// reports the three decisions, whether the modes agree, and which
/// matched-rule set produced disagreement. This is the review tool
/// for mode selection: run it over representative facts and every
/// disagreement is a candidate to inspect before locking a mode.
///|
fn matrix_request(request : Value) -> Value raise {
ignore(arr(get(request, "rules"))) // validate the rule array up front
let facts = match get(request, "facts") {
Array(items) => items
other => [other]
}
let budget = optional_num(get(request, "budget"), 10000.0).to_int()
let rows : Array[Value] = []
let mut agreements = 0
let mut disagreements = 0
for i = 0; i < facts.length(); i = i + 1 {
let fact = facts[i]
let decisions : Map[String, Value] = Map([])
let mut first_decision : Value = Null
let mut all_decision : Value = Null
let mut unique_decision : Value = Null
// first
let first_report = decide(
load_rules(get(request, "rules")),
fact,
"first",
get(request, "default"),
budget,
)
first_decision = get(first_report, "decision")
decisions["first"] = first_decision
// all
let all_report = decide(
load_rules(get(request, "rules")),
fact,
"all",
get(request, "default"),
budget,
)
match get(all_report, "decisions") {
Array(items) => all_decision = Array(items)
_ => all_decision = Null
}
decisions["all"] = all_decision
// unique
let unique_report = decide(
load_rules(get(request, "rules")),
fact,
"unique",
get(request, "default"),
budget,
)
unique_decision = get(unique_report, "decision")
decisions["unique"] = unique_decision
// conflict flag from matched count under all
let matched_count = match get(all_report, "matched") {
Array(matched) => matched.length()
_ => 0
}
// Agreement: all three views identify the same single outcome when
// exactly one rule matched; otherwise modes inherently differ.
let agree = matched_count <= 1
if agree {
agreements += 1
} else {
disagreements += 1
}
rows.push(
record([
("index", Number(i.to_double())),
("first", first_decision),
("unique", unique_decision),
("all_count", Number(matched_count.to_double())),
("agree", Bool(agree)),
]),
)
ignore(decisions)
}
record([
("rows", Array(rows)),
("record_count", Number(facts.length().to_double())),
("agreements", Number(agreements.to_double())),
("disagreements", Number(disagreements.to_double())),
])
}