feat(alerts): require an HnR rise to persist before notifying - #7
Merged
Conversation
TorrentLeech publishes a LIVE "not currently satisfying" counter rather than a permanent strike record. Stale tracker-side leech records age out through it, so the count blips 0 -> 1 -> 0 with nothing actually wrong. checkHnrIncrease fires on every blip, and every one of them is a false alarm. Measured on 11 days of hourly TL polls: four separate blips, runs of 5, 4, 2 and 4 polls, all self-cleared. checkHnrSustained requires an increase to hold for N consecutive polls (default 6 - the smallest value that suppresses all four) and fires exactly once, on the poll where the run completes. A genuine hit-and-run is a recorded penalty that never clears, so the only cost is a few hours of notice on something already irreversible. - N is configurable per target via thresholds.hnrSustainedPolls, clamped to HNR_SUSTAINED_POLLS_MAX so an over-large value cannot silently never fire. - The scheduler now loads HNR_HISTORY_POLLS snapshots instead of one; only the HnR check reads the extra rows. - Callers that supply no history keep the original single-step behaviour.
Knip Code AnalysisFound 9 total issues
View details
Use |
|
🚫 Security audit failed Critical Failures
Warnings
Passed (36/38)
Summary: 36/38 checks passed See |
Trivy flagged CVE-2026-67213 (HIGH) against nanoid 3.3.16, reached transitively through postcss, which is itself pulled in by next, @tailwindcss/postcss and vite. The image build gates on the scan, so this blocked release. Pinned to ^3.3.17 rather than the >=3.3.17 that a naive read of the advisory suggests: the open range resolves to nanoid 6.x, which is a major version away from the ^3.3.11 postcss actually asks for. Staying inside 3.x takes the fix without swapping a scanner finding for a runtime break. Unrelated to the HnR work on this branch; it surfaced because this is the first build since the advisory landed.
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.
Problem
TorrentLeech's hit-and-run figure is a live "not currently satisfying" counter, not a permanent strike record. Stale tracker-side leech records age out through it, so the count blips
0 -> 1 -> 0over a few hours with nothing wrong.checkHnrIncreasefires on every one.Measured on 11 days of hourly TL polls from
tracker_snapshots:Four alerts, four false alarms.
Fix
checkHnrSustainedrequires an increase to hold for N consecutive polls before it notifies, and fires exactly once — on the poll where the run reaches N. A later poll shifts the rise past the checked offset, so an elevated-but-flat counter stays quiet.Default N = 6: the smallest value that suppresses all four observed episodes. A genuine hit-and-run is a recorded penalty that never clears, so the only cost is a few hours of notice on something already irreversible.
Notes
thresholds.hnrSustainedPolls, clamped toHNR_SUSTAINED_POLLS_MAX— an over-large value would otherwise exceed the fetched history and silently never fire, which looks identical to "no HnRs".HNR_HISTORY_POLLSsnapshots instead of 1. Only the HnR check reads the extra rows; every other comparison still usespreviousSnapshot.recentHnrskeep the original single-step behaviour.Tests
18 new cases, including a replay of all four real TL episodes asserting zero alerts, and a non-clearing strike asserting exactly one.
pnpm tscclean. The one failing suite (chart-transforms) is the known UTC-brittle test — fails in Mountain, passes in CI, untouched here.