1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! The judgement core (RFC 13, v1.24) — one shape under every verdict.
//!
//! Every tool verdict in this workspace is a surface naming of one four-pole
//! shape:
//!
//! > `Established(yes) | Established(no) | Unestablished(NotAsked) |
//! > Unestablished(Unobservable{reason})`
//!
//! RFC 13 (v1.24) is the normative chapter for this shape; before v1.24 the
//! material lived in RFC 09 §5.1 (the O1–O7 observation rules), and the O#
//! citations across this crate still point there for the individual rules.
//! The poles:
//!
//! * [`Judgement::Established`] — Established(yes): the question was put and
//! the claim holds, conclusively.
//! * [`Judgement::NotEstablished`] — Established(no): the question was put
//! and the claim conclusively does not hold, with the reason.
//! * [`Judgement::NotAsked`] — Unestablished: the question was never put.
//! "Not asked" is not "answered no" (O4).
//! * [`Judgement::Unobservable`] — Unestablished: the question was put and
//! the observation could not carry the claim (a drop under a completeness
//! claim, a window shorter than the claim's span, an ask that failed),
//! with the reason. Neither "fine" nor "fire" (O6).
//!
//! Domain vocabularies — [`crate::report::CondState`],
//! [`crate::report::ExpectVerdict`], [`crate::report::CutoverVerdict`],
//! [`crate::report::WhyVerdict`], the `why` ladder's per-rung answer — remain
//! surface namings with documented mappings onto this core; each mapping
//! lives beside its vocabulary. The mapping convention every verdict-level
//! `to_judgement()` follows: **the judged claim is the finding** — a verdict
//! that found something maps to `Established`, a clean one to
//! `NotEstablished`. That convention is what makes the exit projection below
//! a pure function; a vocabulary whose own polarity is inverted
//! ([`crate::report::WhyVerdict`]: `Explained` is the *finding* and its CLI
//! historically exits 0) does the flip at its mapping, never downstream.
//!
//! ## Serialized form
//!
//! `Judgement` serializes with an `answer` tag —
//! `{"answer": "established"}`, `{"answer": "not_established", "reason": …}`,
//! `{"answer": "not_asked"}`, `{"answer": "unobservable", "reason": …}` —
//! byte-identical, for the three poles it had, to the `why` ladder's shipped
//! rung answer (#214), whose wire shape this type now carries directly.
use Serialize;
/// One question's judgement — the four-pole core every tool verdict maps
/// onto (RFC 13, v1.24; RFC 09 §5.1 pre-v1.24). See the module doc.
/// The RFC 13 (v1.24) exit projection: `0` = established-clean, `1` =
/// established-finding, `2` = unestablished (not asked, or unobservable).
///
/// The projection reads the core convention (module doc): the judged claim
/// is the **finding**, so `Established` is the finding exit and
/// `NotEstablished` the clean one. A vocabulary with inverted surface
/// polarity handles the flip in its own `to_judgement()` mapping
/// ([`crate::report::WhyVerdict`] is the documented case), never here — this
/// function has exactly one spelling per pole.