Repository navigation
Detector: report the window burst, not the session total, for THRASH and RAPID_SCROLL - #53
Open
Orpheus-agent wants to merge 1 commit into
Open
Orpheus-agent wants to merge 1 commit into
Orpheus-agent wants to merge 1 commit into
Conversation
…and RAPID_SCROLL A rule whose threshold is "N in windowMs" is a sliding-window count, so the number it reports - and the severity derived from it - must be the count it actually saw inside one window. RAGE_CLICK was already fixed to do this; THRASH and RAPID_SCROLL still reported the length of the whole (session, element) bucket. Concretely: a session with five input changes in a 2s burst and five more calm changes later produced a THRASH summary of "10 input changes within 4000ms" and severity 1.0, when the rule fired on the five-change burst. That copy is what the friction dashboard and the intervention diagnostic show the customer, and the severity feeds the dispatcher's confidence, which sets how prominently the intervention renders - so both were inflated by events the rule never saw in a window. RAPID_SCROLL had the same defect in its summary. Fix: extract the RAGE_CLICK sliding-window scan into `maxInWindow` and use it in all three rules, so the reported count and severity are the windowed burst. Detection thresholds are unchanged: a window holding >= min events exists iff the same min events fit inside one window. RAGE_CLICK is refactored onto the shared helper with no behaviour change; its existing tests still pass. Verified: 277 tests pass (3 new - THRASH windowed summary+severity, a burst late in a long calm session, and RAPID_SCROLL), plus typecheck, lint, SDK bundle freshness and the real guided demo acceptance (desktop + mobile). public/demo/demo.js is rebuilt because the demo bundles the detector.
This was referenced Oct 9, 2026
This branch has not been deployed
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 free
to 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.
What this fixes
THRASHandRAPID_SCROLLare "N inwindowMs" rules, so they are sliding-window counts. Both fired on a window but reported the length of the whole(session, element)bucket in theirsummaryand severity, so a long calm session with one late burst claimed every event landed inside the window.Concretely, with five
INPUT_CHANGEevents in a 2s burst and five more calm changes later on the same field, the detector emitted:summary: "10 input changes within 4000ms",severity: 1.0summary: "5 input changes within 4000ms",severity: 0.5The summary is what the friction dashboard and the intervention diagnostic show the customer, and the severity feeds the dispatcher's confidence, which sets how prominently an intervention renders - so both were inflated by events the rule never saw in a window.
RAPID_SCROLL's summary had the same defect (N scroll events in 2000mswith N = the whole session).RAGE_CLICKalready had this fixed; the comment indetectRageClicksstates the principle: "unrelated earlier clicks must not inflate the severity or the claim about how many clicks occurred in this window." This change extracts that scan into a sharedmaxInWindowhelper and uses it in all three rules.Detection is unchanged
A window holding
>= minevents exists iff the sameminevents fit inside one window, so the thresholds are untouched.RAGE_CLICKis refactored onto the shared helper with no behaviour change; its existing sliding-window tests still pass.Verification
pnpm test- 277 passed (3 new: THRASH windowed summary + severity, a burst late in a long calm session, and RAPID_SCROLL)pnpm typecheck,pnpm lint- cleanpnpm sdk:build/sdk:build:min/demo:build-public/demo/demo.jsrebuilt (the demo bundles the detector); bundles match the CI freshness checkpnpm demo:verify- real guided demo acceptance passes on desktop and mobileOpened by Orpheus-agent for review; not merged.