Skip to content

Gate data-status statistics on use_for_projections - #2237

Merged
moveson merged 3 commits into
masterfrom
oveson/claude/stats-use-for-projections
Aug 24, 2026
Merged

Gate data-status statistics on use_for_projections#2237
moveson merged 3 commits into
masterfrom
oveson/claude/stats-use-for-projections

Conversation

@moveson

Copy link
Copy Markdown
Collaborator

Summary

Implements #2169 using the use_for_projections flag from #2229 rather than course deep-copying. Three parts, one commit each:

1. SplitTimeQuery.typical_segment_time gains event scoping. The data-status statistics pool previously drew from every split time on a course — no event, concealment, or flag filter — which is how fabricated test times dragged a pooled segment average to ~880 days and flagged every real finisher "bad" in the incident. The begin-side subquery now joins efforts → events and requires use_for_projections is true, the same predicate Projection.sql uses (filtering one side of the st1/st2 pair suffices since they inner-join on effort_id). The pool also now discards negative segment pairs (st2.absolute_time >= st1.absolute_time; >= preserves legitimate zero-elapsed in-aid pass-throughs).

2. Simulated groups opt out automatically.SimulateInProgressEventGroup sets use_for_projections: false on the events it creates — this also closes a live hole where simulated events (default flag true) were feeding Projection. DuplicateEventGroup is deliberately unchanged: UI duplicates are next year's real races whose live times must feed the stream, and nothing warns in the false→true direction; a regression spec pins that behavior.

3. Degenerate baseline degrades to unknown, never all-bad.SegmentTimesContainer#limits returns empty limits for a non-positive typical time on scaling limit types, and DataStatus.determine returns nil for empty limits — so a garbage baseline now yields "unknown" statuses instead of flagging everything bad. zero_start (intentionally all-zero band) and in_aid (fixed 15-minute allowance keeps the band usable) are exempted, preserving current behavior.

Out of scope, per review of the plan: the TimePredictor pace-factor hardening (positive-pace guard for a latent FloatDomainError when the typical completed time is exactly 0.0, plus a clamp) — follow-up ticket to come. Also noted: SplitTimeQuery.effort_times still filters on concealment but is dead code (its only wrapper, SplitTime.effort_times, has no callers) — left untouched here; deleting it is a separate cleanup.

Behavior changes worth knowing

  • Events backfilled to flag-false (concealed groups at rollout) no longer self-pool: their own efforts produce "unknown" data statuses instead of stats-based ones. This matches the flag's semantics, and the event-form checkbox opts back in (as the Twisted Branch seed event does).
  • :focused (similar-effort) baselines are gated too — flag-false events feed no baseline of any kind.

Resolves#2169

Testing

  • New query specs: flag-false event excluded from the pool (unfocused and focused), negative segment pair excluded.
  • New simulate spec: created events all have the flag false. New duplicate spec: duplicated events keep it true.
  • New container specs: zero/negative typical time on a scaling type returns empty limits; in-aid zero typical still yields a usable band.
  • All six behavior-differentiating examples verified to fail against pre-change code.
  • Wider suites green: time predictor, segment time calculator, all interactors, projection, enrich/verify raw time row — 436 examples total, 0 failures. rubocop clean on touched files.

🤖 Generated with Claude Code

movesonand others added 3 commits August 22, 2026 12:32
The data-status statistics pool drew from every split time on a course
with no event scoping, so fabricated test times on a shared course
corrupted the pace-factor baseline for real events. Join the begin-side
subquery through efforts to events and require use_for_projections,
matching the predicate Projection.sql already uses. Also discard
negative segment pairs from the pool.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SimulateInProgressEventGroup now sets use_for_projections false on the
events it creates, so fabricated times cannot feed projections or the
data-status pool even on a shared course. DuplicateEventGroup is
deliberately unchanged: UI duplicates are next year's real races, whose
live times must feed the stream; a regression spec pins that.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A zero or negative pooled average previously produced an all-zero
limits band, against which every real time evaluated as bad. Return
empty limits for non-positive typical times on scaling limit types so
statuses degrade to unknown; zero_start and in_aid types keep their
intentional fixed bands.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@moveson
moveson merged commit 876d86a into masterAug 24, 2026
7 checks passed
@moveson
moveson deleted the oveson/claude/stats-use-for-projections branch August 24, 2026 14:43
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Simulate/duplicate test events share the production course and corrupt real events' statistics

1 participant

@moveson