fix: one click should mark your child for the game, and the ball should be findable - #46
Merged
Merged
Conversation
Production has an athlete bound to 2 tracks out of 1125, and one suggested moment, in a game they played all of. Three separate causes, all measured against that project's own data. Stitching a pick into the fragments either side of it has existed since the appearance matcher landed, but the only route to it was the candidate grid, which offers proposals to tick. The scrubber — where people actually identify, because pointing at your own child needs no explanation — bound the one track under the cursor and stopped. It now asks the server to follow them, and the server accepts the same proposals the grid pre-ticks. Best-effort: a failure to widen must never lose the pick, which is the part the user made. The ball, second. Only a confident detection may open a track; a faint one can extend a track that already exists. So per-class floors were half a fix — a 0.2 ball landed in the low pile, where it could only attach to a ball track lucky enough to have started at 0.4, and there usually was none. That is exactly the shape the floor sweep showed: positions up 69%, track count flat. Track birth now honours each class's own floor, and nothing else moves: a weak *player* detection still cannot start a track. Third, geometry. Overlap is the wrong question to ask about a thrown ball. It is a small box that clears several of its own widths between sampled frames, and boxes that do not touch have an IoU of exactly zero however close they are — so association fails, the track dies, and a new one is born further along the same flight. Both boxes are now grown before overlap is measured, per class, which leaves everyone with a buffer of 0 associating on identical geometry. Exposed as --class-buffer for the same reason the floors are: the value that belongs there is a measurement, not an opinion. Identity is collected where the user is already looking at the child, so the colour field is reachable from the surface they use — production has a kid recorded as team "Triton (white)" because the only form offering a colour was one they never reached. And the empty state no longer says "run analysis" while analysis is running, which was the page telling you to act when the only right move was to wait. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The live-region refresh re-mounted the review scrubber after swapping data-live="moments". The scrubber is not in that region — it is not on that page — while the island that *is*, the interactive Keep/Reject list, was never re-mounted at all. Both halves fail silently. The moment list came back as the server rendered it, looking exactly right, with nothing behind its buttons; and it came back that way at the worst possible moment, since that region is swapped precisely when a job finishes and new suggestions appear. Meanwhile a page holding both would have attached a second canvas and a second set of controls over the same video. The list moves into its own module so the entry point and the refresh can share one mount, the map points at it, and mountReview refuses to attach twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces the reasoning that motivated the buffer with the sweep that chose it.
1.5 is kept over 3.0 because the extra joining buys ~1% more coverage while
roughly doubling the radius in which a stray blob can be taken for the ball,
and a track that teleports is worse than two that stop.
Measured against the deployed worker on identical footage and flags:
ball hoop player referee time
deployed today 21 / 382 7 / 387 297 / 8604 39 / 803 89s
+ birth at floor 71 / 831 15 / 425 297 / 8604 39 / 803 93s
+ buffered IoU 66 / 891 15 / 425 297 / 8604 39 / 803 88s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Four fixes, each measured against the production project rather than argued.
Your athlete was on 2 tracks out of 1125
Stitching a pick into the fragments either side of it has existed since the appearance matcher landed — but the only route to it was the candidate grid, which offers proposals to tick. The scrubber, where people actually identify because pointing at your own child needs no explanation, bound the one track under the cursor and stopped.
Measured on the live project, for the athlete who is actually in it:
One click now covers 54.6s instead of 10.6s. The proposals accepted are the same ones the grid pre-ticks, so this is that surface's existing judgement, reached from the surface people use. It is best-effort: a failure to widen never loses the pick, which is the part the user made and the part scoring cannot do without.
The ball, twice
Only a confident detection may open a track; a faint one can extend a track that already exists. Per-class floors were therefore half a fix — a 0.2 ball landed in the low pile, where it could only attach to a ball track lucky enough to have started at 0.4, and usually there was none. That is exactly the shape the floor sweep showed: positions up 69%, track count flat.
Second, geometry. Overlap is the wrong question to ask about a thrown ball: a small box that clears several of its own widths has an IoU of exactly zero, so association fails, the track dies, and a new one is born further along the same flight.
A/B against the deployed worker, same 20s of real game, same flags:
Ball positions +133% for no measurable runtime. The rim doubled too — its 0.15 floor was under the same 0.4 birth bar. Player and referee counts are identical to the digit, which is the invariant: loosening the ball must never loosen anybody.
The buffer was swept, not guessed — 3.0 joins more but buys ~1% more coverage while roughly doubling the radius in which a stray blob can be taken for the ball, and a track that teleports is worse than two that stop.
--class-bufferis exposed for the same reason the floors are: the value belongs to a measurement, not an opinion.A silent bug in #41
The live refresh re-mounted the review scrubber after swapping
data-live="moments". The scrubber is not in that region — it is not on that page — while the island that is, the interactive Keep/Reject list, was never re-mounted at all.Both halves fail invisibly. The moment list came back looking exactly right with nothing behind its buttons, and it came back that way at the worst moment, since that region is swapped precisely when a job finishes and new suggestions appear. A page holding both would have grown a second canvas and a second set of controls.
Knowing whether to wait
Identity — name, number, shirt colour, team — is collected in the scrubber, where the user is already looking at the child. Production has a kid recorded as team
Triton (white)because the only form offering a colour was one they never reached. A spinner marks the one click that genuinely waits, and the empty state no longer says "run analysis" while analysis is running.606 tests pass, lint and build clean.