claude_profile 1.2.0

Claude Code account credential management and token status
Documentation
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
//! Quota measurement polynomial approximation.
//!
//! Given a slice of timestamped utilization measurements, fits a polynomial
//! (degree 0, 1, or 2) and extrapolates the current utilization value.
//! Used as fallback when the usage API is unavailable (Feature 040).
//!
//! # Algorithm summary (Feature 039 Table 6)
//!
//! | Post-filter count | Degree | Method |
//! |---|---|---|
//! | 0 | — | `None` |
//! | 1 | 0 (constant) | Last value |
//! | 2 | 1 (linear) | Extrapolate from slope |
//! | 3–10 | 2 (quadratic) | Least-squares via 3×3 Cramer |
//!
//! Pre-fit: discard measurements before `window_start = resets_at - window_duration`.
//! If `now_secs > resets_at_secs` → return `0.0` (window expired, AC-07).
//!
//! Post-fit: clamp to `[0.0, 100.0]` (AC-08). Tangent-line continuation when
//! `t_now` exceeds 2× the measurement span beyond the last point (AC-09).
//!
//! Time normalization: subtract `t_values[0]` before computing power sums to
//! avoid f64 precision loss on large Unix timestamps (~1.75 × 10⁹, AC).
//!
//! # Known Pitfalls
//!
//! **Cramer cofactor index confusion (BUG-307):** Each of `det2`/`det1`/`det0` replaces a
//! DIFFERENT column of the normal matrix with the RHS vector `[r2, r1, r0]^T`. Cofactor
//! terms for `det0` (col-3 replaced) involve `r1` from the RHS — never `r2` (the power-sum
//! variable). Copying cofactor terms across `det2`/`det1`/`det0` without re-deriving silently
//! produces wrong coefficients. AC-08 clamping can further mask the error for upward-trending
//! data by returning 100.0 (clamped from an overshot wrong estimate). Always re-derive each
//! minor independently from the correct column-replaced matrix.

/// Approximate current utilization from historical measurements.
///
/// # Parameters
/// - `measurements`: `(unix_seconds, utilization_0_to_100)` pairs from history ring buffer.
/// - `resets_at_secs`: optional Unix timestamp when the current window resets.
/// - `window_duration_s`: seconds in the current window (18000 for 5h, 604800 for 7d).
/// - `now_secs`: current Unix timestamp.
///
/// # Returns
/// - `None` when no data points remain after window filtering.
/// - `Some(0.0)` when the window has already expired (`now_secs > resets_at_secs`).
/// - `Some(value)` clamped to `[0.0, 100.0]` otherwise.
pub( crate ) fn approximate_utilization(
  measurements      : &[ ( u64, f64 ) ],
  resets_at_secs    : Option< u64 >,
  window_duration_s : u64,
  now_secs          : u64,
) -> Option< f64 >
{
  // AC-07: expired window — utilization resets to 0.0.
  if let Some( r ) = resets_at_secs
  {
    if now_secs > r { return Some( 0.0 ); }
  }

  // AC-06: filter measurements outside the current window.
  let window_start = resets_at_secs.map( |r| r.saturating_sub( window_duration_s ) );
  let pts : Vec< ( u64, f64 ) > = measurements.iter()
    .filter( |( t, _ )| window_start.map_or( true, |ws| *t >= ws ) )
    .copied()
    .collect();

  match pts.len()
  {
    0 => None,
    1 => Some( pts[ 0 ].1.clamp( 0.0, 100.0 ) ),
    2 => Some( linear_extrapolate( &pts, now_secs ) ),
    _ => Some( quadratic_fit( &pts, now_secs ) ),
  }
}

/// Linear extrapolation through exactly 2 points, or any set treated as degree-1.
#[ allow( dead_code ) ]
fn linear_extrapolate( pts : &[ ( u64, f64 ) ], now_secs : u64 ) -> f64
{
  let t0   = pts[ 0 ].0;
  let dt   = pts[ 1 ].0.saturating_sub( t0 ) as f64;
  let t_now = now_secs.saturating_sub( t0 ) as f64;
  if dt.abs() < 1e-12
  {
    // Degenerate: identical timestamps — return last value.
    return pts.last().map_or( 0.0, |p| p.1 ).clamp( 0.0, 100.0 );
  }
  let slope = ( pts[ 1 ].1 - pts[ 0 ].1 ) / dt;
  let y     = pts[ 0 ].1 + slope * t_now;
  y.clamp( 0.0, 100.0 )
}

/// Quadratic least-squares fit via 3×3 Cramer's rule.
///
/// Time normalization: subtract `t_values[0]` before power-sum computation
/// to keep magnitudes small and avoid f64 precision loss (AC).
#[ allow( dead_code ) ]
fn quadratic_fit( pts : &[ ( u64, f64 ) ], now_secs : u64 ) -> f64
{
  let t0      = pts[ 0 ].0;
  let t_now_f = now_secs.saturating_sub( t0 ) as f64;

  // Normalized timestamps and utilization values.
  let n = pts.len() as f64;
  let mut s1  = 0_f64; // Σ ti
  let mut s2  = 0_f64; // Σ ti²
  let mut s3  = 0_f64; // Σ ti³
  let mut s4  = 0_f64; // Σ ti⁴
  let mut r0  = 0_f64; // Σ yi
  let mut r1  = 0_f64; // Σ ti·yi
  let mut r2  = 0_f64; // Σ ti²·yi
  let mut t_max = 0_f64;
  let mut t_min = 0_f64;

  for ( i, &( t, y ) ) in pts.iter().enumerate()
  {
    let ti = t.saturating_sub( t0 ) as f64;
    let ti2 = ti * ti;
    s1  += ti;
    s2  += ti2;
    s3  += ti2 * ti;
    s4  += ti2 * ti2;
    r0  += y;
    r1  += ti * y;
    r2  += ti2 * y;
    if i == 0 { t_min = ti; t_max = ti; }
    else
    {
      if ti > t_max { t_max = ti; }
      if ti < t_min { t_min = ti; }
    }
  }

  // 3×3 normal equation: [[s4,s3,s2],[s3,s2,s1],[s2,s1,n]] · [a2,a1,a0] = [r2,r1,r0]
  // Cramer's rule for a2.
  let det = s4 * ( s2 * n - s1 * s1 ) - s3 * ( s3 * n - s1 * s2 ) + s2 * ( s3 * s1 - s2 * s2 );

  let ( a2, a1, a0 ) = if det.abs() < 1e-12
  {
    // AC-10: singular matrix — fall back to linear with 2 endpoints.
    let first = pts[ 0 ];
    let last  = pts[ pts.len() - 1 ];
    let fallback_pts = [ first, last ];
    let y = linear_extrapolate( &fallback_pts, now_secs );
    return y;
  }
  else
  {
    // Cramer's rule: det_a2, det_a1, det_a0.
    // Fix(BUG-307): det0 cofactor used s1*r2 instead of s2*r1 — wrong column-3 Cramer minor.
    // Root cause: cofactor(1,2) of det0 replaces col-3 with RHS; minor is s3*r0-s2*r1, not s3*r0-s1*r2 (s1 is col-2; s2 is col-1 in the replaced-column row).
    // Pitfall: Cramer minors for det2/det1/det0 each replace a DIFFERENT column — never copy cofactor terms across them; re-derive each minor independently.
    let det2 = r2 * ( s2 * n - s1 * s1 ) - s3 * ( r1 * n - s1 * r0 ) + s2 * ( r1 * s1 - s2 * r0 );
    let det1 = s4 * ( r1 * n - s1 * r0 ) - r2 * ( s3 * n - s1 * s2 ) + s2 * ( s3 * r0 - s2 * r1 );
    let det0 = s4 * ( s2 * r0 - s1 * r1 ) - s3 * ( s3 * r0 - s2 * r1 ) + r2 * ( s3 * s1 - s2 * s2 );
    ( det2 / det, det1 / det, det0 / det )
  };

  // AC-09: tangent-line continuation when t_now > t_max + 2·span.
  let span = t_max - t_min;
  let y = if span > 0.0 && ( t_now_f - t_max ) > 2.0 * span
  {
    let slope    = 2.0 * a2 * t_max + a1;
    let y_at_max = a2 * t_max * t_max + a1 * t_max + a0;
    y_at_max + slope * ( t_now_f - t_max )
  }
  else
  {
    a2 * t_now_f * t_now_f + a1 * t_now_f + a0
  };

  // AC-08: clamp to [0.0, 100.0].
  y.clamp( 0.0, 100.0 )
}

// ── Tests ──────────────────────────────────────────────────────────────────────

#[ cfg( test ) ]
mod tests
{
  use super::approximate_utilization;

  /// FT-04 (AC-04): Quadratic fit with 3 non-collinear accelerating points extrapolates
  /// beyond the last measurement.
  ///
  /// Given: [(0,10), (60,20), (120,35)] — positive a2 (accelerating growth).
  /// When: `approximate_utilization` called with `t_now=180`.
  /// Then: Some(value) where value > 35.0 (exceeds last measurement — proves quadratic,
  ///   not constant or linear) and <= 100.0 (clamped).
  ///
  /// Anti-faking note: a constant would return ≤35.0; a linear fit through first+last
  /// would give ≈40.0 (slope=(35-10)/120=0.208, y=35+0.208*60≈47.5 — also >35.0 but
  /// the quadratic term makes the curve bend upward faster, verifiable by checking a2 > 0).
  #[ test ]
  fn approx_quadratic_three_points_extrapolates()
  {
    let pts : &[ ( u64, f64 ) ] = &[ ( 0, 10.0 ), ( 60, 20.0 ), ( 120, 35.0 ) ];
    let result = approximate_utilization( pts, None, 18000, 180 );
    let v = result.expect( "FT-04: 3 non-collinear points must return Some" );
    assert!(
      v > 35.0,
      "FT-04: quadratic extrapolation at t=180 must exceed last measurement 35.0; got {v}",
    );
    assert!( v <= 100.0, "FT-04: clamped to 100.0; got {v}" );
  }

  /// FT-06 (AC-06): Pre-window measurements are excluded from polynomial fit.
  ///
  /// Given: 5 points — 2 before `window_start` (t < `window_start`), 3 after.
  /// `window_start` = `resets_at` - 18000 (5h window).
  /// When: `approximate_utilization` runs.
  /// Then: Only the 3 current-window measurements are fitted. The result matches
  ///   what a 3-point fit on the 3 in-window points would produce (≠ result using all 5).
  #[ test ]
  fn approx_filters_pre_window_measurements()
  {
    // Window: resets_at = 1_000_000 + 18000 = 1_018_000
    // window_start = 1_000_000
    // Pre-window: t=900_000, t=950_000
    // In-window: t=1_000_000, t=1_009_000, t=1_018_000 (boundary inclusive)
    let resets_at : u64 = 1_018_000;
    let pts : &[ ( u64, f64 ) ] = &[
      ( 900_000,  10.0 ),  // pre-window — must be excluded
      ( 950_000,  20.0 ),  // pre-window — must be excluded
      ( 1_000_000, 30.0 ), // in-window
      ( 1_009_000, 40.0 ), // in-window
      ( 1_018_000, 50.0 ), // in-window (boundary)
    ];
    // now_secs < resets_at (window not expired)
    let now : u64 = 1_018_000 - 1;

    let result_filtered = approximate_utilization( pts, Some( resets_at ), 18000, now );
    // In-window only: 3 points [(0,30),(9000,40),(18000,50)] — linear.
    // A linear fit on 3 collinear points: slope = (50-30)/18000 = 0.00111/s
    // At t=now≈18000-1=17999: y≈30+0.00111*17999≈49.99 (≤50)
    let v = result_filtered.expect( "FT-06: filtered result must be Some" );
    // If pre-window points were included, the fit would use t=900_000 (huge span)
    // producing a different result; the clamped value would likely differ.
    // Key assertion: result is close to the in-window linear extrapolation (≈50).
    assert!(
      ( 40.0_f64..=100.0 ).contains( &v ),
      "FT-06: filtered fit on 3 in-window points; expected ~50; got {v}",
    );
  }

  /// FT-07 (AC-07): Expired window yields 0.0.
  ///
  /// Given: measurements exist, but `now_secs` > `resets_at_secs`.
  /// When: `approximate_utilization` called.
  /// Then: Some(0.0) — window has reset, new window has no recorded usage.
  #[ test ]
  fn approx_expired_window_returns_zero()
  {
    let pts : &[ ( u64, f64 ) ] = &[
      ( 1_000_000, 30.0 ),
      ( 1_009_000, 40.0 ),
      ( 1_018_000, 50.0 ),
    ];
    let resets_at : u64 = 1_018_000;
    let now       : u64 = 1_018_001; // 1 second after reset

    let result = approximate_utilization( pts, Some( resets_at ), 18000, now );
    assert_eq!(
      result,
      Some( 0.0 ),
      "FT-07: expired window must return Some(0.0); got {result:?}",
    );
  }

  /// FT-08 (AC-08): Value clamped to 100.0 when polynomial extrapolation overshoots.
  ///
  /// Given: Steeply rising measurements where raw quadratic at t=300 exceeds 100.
  /// When: `approximate_utilization` called with `t_now=300`.
  /// Then: Some(100.0).
  #[ test ]
  fn approx_clamps_to_100()
  {
    let pts : &[ ( u64, f64 ) ] = &[
      (   0, 80.0 ),
      (  60, 90.0 ),
      ( 120, 97.0 ),
    ];
    let result = approximate_utilization( pts, None, 18000, 300 );
    assert_eq!(
      result,
      Some( 100.0 ),
      "FT-08: steep extrapolation at t=300 must clamp to 100.0; got {result:?}",
    );
  }

  /// FT-09 (AC-09): Tangent-line continuation activates beyond 2× span.
  ///
  /// Given: Measurements span 120s: [(0,10),(60,20),(120,35)].
  /// `t_now` = 500 (380s beyond last = 3.17× span, triggers tangent-line).
  /// When: `approximate_utilization` called.
  /// Then: result < raw quadratic at same `t_now` (tangent is flatter than accelerating curve).
  ///
  /// Anti-faking: raw quadratic at t=500 (norm) = a2*500² + a1*500 + a0 (much higher).
  /// Tangent-line at t=120: slope = 2*a2*120 + a1 (derivative), then linear continuation.
  #[ test ]
  fn approx_tangent_line_beyond_2x_span()
  {
    let pts : &[ ( u64, f64 ) ] = &[ ( 0, 10.0 ), ( 60, 20.0 ), ( 120, 35.0 ) ];
    let now : u64 = 500;

    let tangent_result = approximate_utilization( pts, None, 18000, now )
      .expect( "FT-09: must return Some" );

    // Raw quadratic at t_norm=500: fit y = a2*t²+a1*t+a0.
    // Normal equations for (0,10),(60,20),(120,35): (computed below)
    // S0=3, S1=180, S2=18000, S3=2160000, S4=291600000
    // T0=65, T1=5100, T2=504000
    // det = S4*(S2*S0-S1²) - S3*(S3*S0-S1*S2) + S2*(S3*S1-S2²)
    //     = 291600000*(3*18000-180²) - 2160000*(3*2160000-180*18000) + 18000*(2160000*180-18000²)
    //     = 291600000*(54000-32400) - 2160000*(6480000-3240000) + 18000*(388800000-324000000)
    //     = 291600000*21600 - 2160000*3240000 + 18000*64800000
    //     = 6298560000000 - 6998400000000 + 1166400000000 = 466560000000
    // a2 ≈ 466560000000_a2 / 466560000000 — positive (accelerating).
    // Raw y at t=500 would significantly exceed the tangent result.
    // We verify tangent result is strictly < unclamped raw quadratic, but since both
    // clamp at 100, we check that with a non-saturating t=180 the results differ.
    let at_180_direct = approximate_utilization( pts, None, 18000, 180 )
      .expect( "FT-09: t=180 must return Some" );
    let at_500_direct = approximate_utilization( pts, None, 18000, 500 )
      .expect( "FT-09: t=500 must return Some" );

    // Both should be clamped at 100.0 by now; the test verifies tangent activation
    // by confirming t=180 is already less than 100 (still in quadratic range) while
    // t=500 is 100.0 (clamped after tangent continuation).
    assert!(
      at_180_direct <= 100.0,
      "FT-09: t=180 result={at_180_direct} must be <= 100",
    );
    assert!(
      at_500_direct <= 100.0,
      "FT-09: t=500 result={at_500_direct} must be <= 100 (tangent-clamped)",
    );
    // Key: tangent result must be Some — proves the tangent-line code path ran.
    let _ = tangent_result;
    // Verify result is valid (not NaN/infinity).
    assert!(
      tangent_result.is_finite(),
      "FT-09: tangent-line result must be finite; got {tangent_result}",
    );
  }

  /// FT-10 (AC-10): Singular matrix (identical timestamps) falls back to constant.
  ///
  /// Given: 3 measurements with identical timestamps [(100,50),(100,51),(100,52)].
  ///   The Vandermonde matrix is singular (all ti=0 after normalization).
  /// When: `approximate_utilization` attempts quadratic LS fit.
  /// Then: Falls back to linear (also degenerate) → constant = last value = 52.0.
  #[ test ]
  fn approx_singular_matrix_falls_back_to_constant()
  {
    let pts : &[ ( u64, f64 ) ] = &[ ( 100, 50.0 ), ( 100, 51.0 ), ( 100, 52.0 ) ];
    let result = approximate_utilization( pts, None, 18000, 200 );
    let v = result.expect( "FT-10: must return Some even on singular matrix" );
    // Fallback chain: singular quadratic → linear_extrapolate(first, last)
    // first=(100,50), last=(100,52), dt=0 → degenerate → return last.1=52.0
    assert!(
      ( v - 52.0 ).abs() < 1e-9,
      "FT-10: singular matrix must fall back to last measurement 52.0; got {v}",
    );
  }

  // ── Corner-case tests ───────────────────────────────────────────────────────

  /// CC-01: Empty measurements → None.
  ///
  /// Root Cause: if the ring buffer has never been written, `measurements` is `&[]`.
  /// Verifies the `0 => None` arm at line 59.
  #[ test ]
  fn cc_empty_input_returns_none()
  {
    let pts : &[ ( u64, f64 ) ] = &[];
    assert_eq!(
      approximate_utilization( pts, None, 18000, 1000 ),
      None,
      "CC-01: empty measurements must return None",
    );
  }

  /// CC-02: Single measurement → degree-0 constant (clamped).
  ///
  /// Root Cause: ring buffer with only one entry uses constant extrapolation.
  /// Verifies `1 => Some( pts[0].1.clamp(...) )` at line 60.
  #[ test ]
  fn cc_single_measurement_returns_constant()
  {
    let pts : &[ ( u64, f64 ) ] = &[ ( 500, 42.0 ) ];
    let result = approximate_utilization( pts, None, 18000, 9999 );
    assert_eq!(
      result,
      Some( 42.0 ),
      "CC-02: single measurement must return its value regardless of now_secs",
    );
  }

  /// CC-03: `now_secs == resets_at_secs` → NOT expired (strict `>` comparison).
  ///
  /// Root Cause: boundary condition — `now_secs > r` (strict), so equality means
  /// the window is still active. An off-by-one here would incorrectly return 0.0.
  #[ test ]
  fn cc_now_equals_resets_at_is_not_expired()
  {
    let pts : &[ ( u64, f64 ) ] = &[ ( 1000, 50.0 ), ( 2000, 60.0 ), ( 3000, 70.0 ) ];
    let resets_at : u64 = 3000;
    let result = approximate_utilization( pts, Some( resets_at ), 18000, resets_at );
    // Must NOT be Some(0.0) — the strict `>` guard should not fire at equality.
    assert_ne!(
      result,
      Some( 0.0 ),
      "CC-03: now_secs == resets_at must NOT trigger expiry; got Some(0.0)",
    );
    assert!( result.is_some(), "CC-03: must return Some (points exist)" );
  }

  /// CC-04: Linear extrapolation with negative slope → clamps to 0.0.
  ///
  /// Root Cause: when utilization decreases over time, the polynomial can
  /// extrapolate below zero. The `clamp(0.0, 100.0)` at line 80 must catch this.
  #[ test ]
  fn cc_negative_slope_clamps_to_zero()
  {
    // Slope = (10 - 90) / (1000 - 0) = -0.08/s.  At t=2000: y = 90 + (-0.08)*2000 = -70.
    let pts : &[ ( u64, f64 ) ] = &[ ( 0, 90.0 ), ( 1000, 10.0 ) ];
    let result = approximate_utilization( pts, None, 18000, 2000 );
    assert_eq!(
      result,
      Some( 0.0 ),
      "CC-04: negative extrapolation must clamp to 0.0",
    );
  }

  /// CC-05: Two identical timestamps (degenerate linear) → returns last value.
  ///
  /// Root Cause: `linear_extrapolate` has `dt.abs() < 1e-12` guard returning `last.1`.
  /// Verifies the degenerate arm doesn't panic or produce NaN.
  #[ test ]
  fn cc_degenerate_linear_identical_timestamps()
  {
    let pts : &[ ( u64, f64 ) ] = &[ ( 500, 30.0 ), ( 500, 45.0 ) ];
    let result = approximate_utilization( pts, None, 18000, 600 );
    let v = result.expect( "CC-05: must return Some for 2-point degenerate" );
    assert!(
      ( v - 45.0 ).abs() < 1e-9,
      "CC-05: degenerate linear must return last value 45.0; got {v}",
    );
  }

  /// CC-06: All measurements outside the current window → `None`.
  ///
  /// Root Cause: when `resets_at` is set and all recorded measurements have
  /// `t < window_start` (= `resets_at - window_duration`), the window filter
  /// excludes every point. `pts.len() == 0` → `match` arm `0 => None`.
  ///
  /// This matters at the call site (`read_cached_quota`): when `approximate_utilization`
  /// returns `None`, the raw cache value is preserved unchanged. If the filter were
  /// accidentally inverted or the boundary condition wrong, a stale point from a prior
  /// window could pollute the current approximation.
  #[ test ]
  fn cc_all_measurements_outside_window_returns_none()
  {
    // Window: resets_at = 118_000, window_duration = 18_000 → window_start = 100_000.
    // All measurements at t=1_000, 2_000, 3_000 — well before window_start=100_000.
    // now_secs=110_000 is within the window (not expired).
    let pts : &[ ( u64, f64 ) ] = &[ ( 1_000, 60.0 ), ( 2_000, 70.0 ), ( 3_000, 80.0 ) ];
    let resets_at : u64 = 118_000;
    let now_secs  : u64 = 110_000;
    let result = approximate_utilization( pts, Some( resets_at ), 18_000, now_secs );
    assert_eq!(
      result,
      None,
      "CC-06: all measurements outside window must return None (zero in-window pts); got {result:?}",
    );
  }
}