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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//! Prometheus counter for the `#799` signed-root step's outcome.
//!
//! Registered into the process default registry — the same pattern
//! `polyc-agent`'s `metrics.rs` and `polyc-llm`'s follow: no separate scrape
//! endpoint and no registry plumbing.
//!
//! # Why this counter exists
//!
//! A batch can end up durable and unattested, and this counts how often.
//!
//! `append_batch_one` prepares the signed root BEFORE its first append, so a
//! preparation failure is definite: nothing of the batch is durable, the
//! caches are evicted, and the caller sees a plain refusal. That path is
//! counted as `rebuild_failed` or `extend_sign_failed`, and it counts a
//! refused attempt rather than durable content — a caller retrying the same
//! logical commit counts again.
//!
//! The marker append is different. It runs after every event is written, so a
//! failure there leaves content the best-effort commit may well have made
//! durable, with no root covering it. That is `marker_append_failed`.
//!
//! Nothing measured how often that happens. A partition holding no signed-root
//! marker verifies trivially — the forensics report says `NoMarkers`, not a
//! failure — so an unattested tail passes every check the journal ships. The
//! journal-format amendment records this as its risk 9, and states that
//! widening the leaf does not close it: a widened leaf attests up to the last
//! signed root, never past it.
//!
//! Deciding what to do about that needs the rate first. This counter is that
//! measurement, and it is deliberately independent of the amendment.
//!
//! # Reading it
//!
//! Both halves are counted, so a rate is a division at query time rather than
//! a pre-computed ratio here.
//!
//! Read the result precisely: it is the share of recorded batch OUTCOMES that
//! are not `signed`. It is NOT the share of durable content left unattested,
//! and the difference matters. A partial batch that fails and is retried
//! records `unattested_partial_batch` and then `signed`, so one logical commit
//! contributes two outcomes and reads as 50% — while the content it left
//! behind was attested by that very retry.
//!
//! ```promql
//! sum(rate(polychrome_eventlog_attestation_total{outcome!="signed"}[1h]))
//! / sum(rate(polychrome_eventlog_attestation_total[1h]))
//! ```
//!
//! Zero for every failure label is the expected reading, and [`force`] is what
//! makes that zero visible rather than absent.
//!
//! This module is the INSTRUMENT for the amendment's risk 9, not the answer to
//! it. No overlay in this repository composes the scrape config, so nothing
//! reads these series by default. Risk 9 stays open until something does.
//!
//! A nonzero reading names a stage. Read the variants for what each covers —
//! the split is by where the failure surfaces, and a cold-start tree rebuild
//! surfaces under extend/sign rather than under rebuild.
//!
//! # What this does NOT measure
//!
//! This is not a census of unattested content. It counts the outcome of one
//! step on one path, and several other paths leave content unattested without
//! ever reaching that step:
//!
//! - A migration destination. `migrate_append_into` appends without signing,
//! and evicts the cached tree so the next batch re-roots. Mechanically the
//! same transient window `unattested_partial_batch` counts, and it is not
//! counted here.
//! - A restore after a rewrite. `append_repair_copy` commits best-effort on a
//! per-event failure and returns, so a prefix of the restored content can
//! land with no trailing marker — onto a partition whose original content
//! was already emptied. That one does not self-heal the same way.
//! - A batch whose signing SUCCEEDED and whose final commit failed. Nothing is
//! recorded: `signed` is held until the commit lands, so a batch that never
//! landed is never counted as attested.
//! - A partial batch whose best-effort commit ALSO failed. Earlier appends may
//! still have reached the blob, and nothing is recorded.
use OnceLock;
use ;
/// What the signed-root step did for one batch.
pub
/// Force-register [`attestations`] with every `outcome` label pre-created
/// (zero-valued), so each appears in a `/metrics` scrape before any batch
/// commits. See [`crate::init_metrics`].
///
/// An `IntCounterVec` produces NO scrape output for a label value that has
/// never been touched — registering the vec alone is not enough.
/// `with_label_values` creates the zero-valued child without incrementing it,
/// which is what makes it appear.
///
/// This matters more here than for most metrics. The expected healthy reading
/// is zero for every failure label, so without this the numerator of the query
/// above selects nothing, the division returns an EMPTY vector, and the panel
/// reads "no data" — indistinguishable from a build where the counter was
/// never wired. The reading this exists to produce is exactly the one that
/// would break.
pub
/// Signed-root outcomes, labeled `outcome`.
/// Count one batch's signed-root outcome.
///
/// Call this only AFTER the batch's commit succeeds. The signing step runs
/// before that commit, so counting at the signing site would report a batch
/// that never landed — and would count again on a caller's retry of the same
/// logical commit. Both bias the failure ratio downward, which is the one
/// direction that matters here.
///
/// Never fails and never blocks: a counter increment takes a read lock on the
/// vec's children map and nothing the write path itself needs.
pub
/// Read one outcome's current count.
///
/// Exists so a test can prove the counter is WIRED to the append path, not
/// merely that it counts when called directly. A metric nothing increments is
/// the same defect as a guard nothing reaches.
pub