Skip to content

Give scoring something to anchor on: focal athlete, per-sport target class, thread cap - #14

Merged
ralyodio merged 1 commit into
masterfrom
scoring-anchors
Aug 9, 2026
Merged

Give scoring something to anchor on: focal athlete, per-sport target class, thread cap#14
ralyodio merged 1 commit into
masterfrom
scoring-anchors

Conversation

@ralyodio

@ralyodio ralyodio commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Three findings from your basketball run — 1,287 tracks, 34,089 detections, zero suggested moments.

1. Without an athlete to follow, a moment is arithmetically impossible

Three of the seven scoring signals need a focal track, and together they carry 0.6 of the 1.15 total weight. With no focal track the only signal that can fire is high_motion at 0.1.

scenario best possible score threshold
no athlete marked 0.087 0.35
with a focal athlete 0.609 0.35

Not "unlikely" — impossible. The app said "Nothing suggested yet — run analysis", ran analysis for a minute, and completed with nothing, never mentioning it could not have succeeded. It now says so before the work starts.

2. Scoring looked for goal whatever the sport

Basketball tracks a hoop, hockey a net, football an end_zone. For those sports both target signals were permanently dark even with a model that saw the thing perfectly. Soccer worked by luck of naming.

Sports now declare their target class, derived from the noun where the two agree and stated explicitly where they don't:

baseball    base        football    end_zone
basketball  hoop        hockey      net
soccer      goal        volleyball  net

A sport with no trackable target resolves to null rather than a name nothing will ever match.

3. The thread cap was tuned on the wrong machine

worker: threads: using 4 (cgroup-aware 24, visible cores 48)

Those two numbers disagreeing is exactly what #10 existed to reveal, and pinning the pool was right — onnxruntime would have sized from 48 on a 24-core allowance. But 4 is now the limit rather than the protection. The cap moves to 8, which is where a model this small stops benefiting rather than the size of the laptop it was measured on.

REELEEL_CV_THREADS overrides it without a deploy, so the real ceiling can be found on the box that has 24 cores instead of guessed on one with 4.

Verification

393 tests pass (7 new), eslint and typecheck clean. The ceiling arithmetic above was computed by running the real plugin weights through the real scoring code, not derived by hand — after a first attempt that got it wrong by counting user_marker, which has a weight but no implementation and so never reaches the denominator.

What to expect

Mark an athlete, re-run on fast. Detection already works; this gives scoring the anchor it needs. If it still finds nothing, the log will now say whether tracks existed and the threshold is simply too high for this footage — which is a tuning conversation, not a bug hunt.

… nothing

Three findings from a real basketball run that produced 1287 tracks and zero
suggested moments.

Without an athlete to follow, a moment is arithmetically impossible. Three
of the seven scoring signals need a focal track and together carry 0.6 of
the 1.15 total weight. With no focal track the only signal that can fire is
high_motion at 0.1, so the best any window can score is 0.087 against a
threshold of 0.35. The app said "Nothing suggested yet — run analysis", ran
analysis for a minute, and completed with nothing — never mentioning that it
could not have succeeded. It now says so before the work starts, not after.

Scoring looked for a track named `goal` whatever the sport. Basketball
tracks a `hoop`, hockey a `net`, football an `end_zone`, so for those sports
both target signals were permanently dark even with a model that saw the
thing perfectly. Soccer worked by luck of naming. Sports now declare the
class that is their scoring target, derived from the noun where the two
agree and stated explicitly where they do not. A sport with no trackable
target resolves to null rather than to a name nothing will match.

The thread cap from #10 was tuned on a four-core laptop and production
turned out to have twenty-four:

  worker: threads: using 4 (cgroup-aware 24, visible cores 48)

Those two numbers disagreeing is what #10 existed to reveal, and it was
right to pin the pool — onnxruntime would have sized from 48. But four is
now the limit rather than the protection, so the cap moves to eight, which
is where a model this small stops benefiting rather than the size of the
machine it was measured on. REELEEL_CV_THREADS overrides it without a
deploy, so the ceiling can be found without another release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit bbc16fe into master Aug 9, 2026
4 checks passed
@ralyodio
ralyodio deleted the scoring-anchors branch August 9, 2026 23:46
ralyodio added a commit that referenced this pull request Aug 10, 2026
"we should use team color and names not just names — that would help with
detection (ie: #14 in white team not #14 on black team)."

Correct, and the column was already there: `jersey_color` has been on the
athlete row since the first migration, and nothing has ever written it or shown
it. So the picker offered a name — the one attribute a detector cannot help you
match against — while the two things a parent actually points with, the number
and the shirt, went unrecorded. Both teams have a 14 and on a school court they
are regularly on screen together.

Identity is now collected where the user is already looking at the child, in the
picker itself, rather than in a separate "Add an athlete" form they would have to
find first: name, number, shirt colour, team, all optional. Quick-identify no
longer produces "My athlete" when the user told us who it was. Everywhere an
athlete is named now reads "Fred #14 in white (Triton)", colour before team
because colour is the part visible in the footage.

The appearance matcher already separates the teams — a shirt signature is how it
refuses the black team's 14 — so this makes the thing it keys on visible to the
person judging its suggestions, rather than adding a second mechanism.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to 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.

1 participant