Current definition resrisk-v2. Charts stamped with it were computed by src/resolution/risk_score.py, and every value plotted for a past date could have been computed on that date.
compute(df, **params) -> pd.Series # 0-1 per market, indexed venue:market_id evidence(df, **params) -> pd.DataFrame # one row per raised flag, with its clause
SPEC.md § 7 makes the second function binding, not optional:
Never publish a resolution-risk score without the clause that produced it. An unexplained score about someone else's contract is an accusation, not analysis.
So the score and its evidence are one module and one version. compute does not invent a second scoring rule — it delegates the arithmetic to flags.py, which owns the five-flag taxonomy and DEFAULT_WEIGHTS. This module adds the part flags.py never had: where in the rules text each flag came from.
The five flags, and what evidence each can produce:
subjective PRESENT in the text -> the sentence containing the term no_named_source ABSENT from the text -> no clause; the absence is the finding no_edge_cases ABSENT from the text -> no clause; the absence is the finding no_timezone ABSENT from the text -> no clause; the absence is the finding prior_dispute from the RECORD -> the UMA status sequence, not the rules
Three of the five fire on absence. There is no sentence to quote for "this contract never says what happens if the event is postponed" — the honest rendering is the absence itself, stated with the length of text it is absent from, which is why every evidence row carries basis and rules_chars. A UI that only knows how to show quotes will silently drop three flags out of five.
This is a ranking device, not a probability. It has never been calibrated against realised disputes: the observable dispute sample is 758 markets on one venue over 17 months, and fitting weights to it would fit noise. A high score means "read this one first".
Newest first. Each entry says what changed and whether values that had already been published moved with it, followed by the sentence from the module that decided the verdict.
follows flags-v2's word-boundary matching. SCORES MOVE, but narrowly: 4.2% of the corpus changes, mean 0.3263 -> 0.3289, rank correlation 0.995. The change is a matching fix — flags-v1's "tie" matched "parties" and credited 2,434 markets with edge-case coverage they never had. Weights unchanged. PHASE4_THRESHOLDS.md records the before/after and which flags survive a volume control. Evidence spans now come from flags.find(), the same matcher that scores, so a quoted clause cannot disagree with the number.
At least one value that had already been published is different now. Charts drawn before this version do not match charts drawn after it.
SCORES MOVE, but narrowly: 4.2% of the corpus changes, mean 0.3263 -> 0.3289, rank correlation 0.995.
Weights unchanged.
wraps flags-v1's taxonomy and weights; adds clause extraction, absence basis, and the record basis for dispute history. Score values identical to flags-v1 — this version adds evidence, it does not re-tune.
The first version of this metric. There is no earlier definition to restate.
3 charts name this metric in their readout line.