Uh oh!
There was an error while loading. Please reload this page.
Guard the TimePredictor pace factor against non-positive baselines - #2239
Merged
Conversation
Reproduces the #2169 incident shape (clean subject-segment pool, poisoned completed-segment pool) plus the latent FloatDomainError when the completed-segment average is exactly zero. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
measurable_pace? now requires positive actual and typical completed times: a typical completed time of exactly 0.0 was truthy, so float division produced Infinity and limits raised FloatDomainError. The imputed pace is also clamped to [0.1, 10] so a corrupt pooled baseline can shrink or stretch the limits band at most tenfold instead of collapsing it to zero width; real pace factors (roughly 0.3..3) are never clamped. Resolves#2238 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per review: without an observability channel, the clamp converts a rare loud failure (mass bad flags, which is how a poisoned baseline announces itself) into a rare silent one. The guard remains: it fixes the FloatDomainError crash on a zero typical completed time and stops a negative actual completed time from producing a nonsense negative limits band. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the surviving piece of #2238 after design review (the clamp was considered and deliberately dropped — see below). Written TDD-style: the failing specs were committed first, then the fix.
measurable_pace?checked truthiness only, and0.0is truthy, so:Infinityvia float division, andlimits'(limit * pace_factor).to_iraisedFloatDomainError— an unrescued exception inSetEffortStatus, which runs in the live-entry submission path. Reproduced verbatim in the first commit's spec run.measurable_pace?now requires positive actual and typical completed times, falling back to the existing unmeasurable-pace convention of1, so per-segment checks flag the genuinely broken times instead.Why no clamp
A
[0.1, 10]pace-factor clamp was implemented and then removed during review. Rationale: with #2237's pool gating in place, a corrupt flag-true baseline is rare — and when it happens, the un-clamped failure mode (mass bad flags) is loud and self-announcing, which is exactly how the #2169 incident was discovered. Clamping without an observability channel would convert that rare loud failure into a rare silent one, asserting "good" precisely when the evidence is least trustworthy. Scout capture on clamp engagement was also considered and rejected as alert-fatigue noise.Resolves#2238
Testing
#data_status with a degenerate stats baselinespecs (stubbed per-segment pool averages): zero completed-segment average → no raise, evaluates against the unscaled band (pre-fix:FloatDomainError: Infinity); negative average → same (pre-fix: everything "bad" via a negative band).🤖 Generated with Claude Code