Skip to content

fix: marking the same child twice should leave you with one child - #40

Merged
ralyodio merged 1 commit into
masterfrom
fix/one-athlete-not-seven
Aug 10, 2026
Merged

fix: marking the same child twice should leave you with one child#40
ralyodio merged 1 commit into
masterfrom
fix/one-athlete-not-seven

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Reported from real use: "it created each focal selection into a duplicate player and in the end it just uses one selection not all of them."

Exactly right. The live project had 8 athletes, 7 of them "My athlete", created inside three minutes, one fragment each:

ath_751aef7a 'My athlete'  focal=True   14:14:57
ath_599b1f9a 'Fred' #14 Triton (white)  14:10:09
ath_79c5eda0 'My athlete'               14:12:35
ath_52123626 'My athlete'               14:12:51
ath_f4d669e6 'My athlete'               14:13:21
ath_deb93569 'My athlete'               14:13:58
ath_c5321e91 'My athlete'               14:14:19
ath_1b035ae5 'My athlete'               14:14:46

Why

new in the identify route means "I have not told you who this is", and it was calling addAthlete unconditionally. The client sends new whenever its own athlete list hasn't loaded — which is every click made faster than a page reload. So the faster you worked, the more duplicates you got, and each new athlete was made focal in turn. Scoring reads the focal flag, so all that careful selecting collapsed to the last click.

The fix

Two halves:

  1. new prefers the athlete already being followed and only creates one when there genuinely is none. Identifying is still the one step that can't be skipped, so first-run behaviour is unchanged.

  2. A new call adds; a named call replaces. A caller that said new didn't know who this was and can't have sent the fragments already bound, so replacing silently discarded every earlier pick. The picker holds the whole selection and names the athlete, so it still replaces — that's what makes unticking a crop work.

Test

apps/web/src/identifytwice.test.ts drives the real route through registerActions, simulating clicks with no loaded client state.

  • before: 3 clicks → 3 athletes (expected […] to have a length of 1 but got 3)
  • after: 1 athlete holding all 3 fragments, focal

574 tests pass, 8 skipped. Lint and build clean.

Not in this PR

Also raised in the same report, and worth separate changes: jersey/team shown in the picker so "#14 white" is distinguishable from "#14 black"; ball detection recall; and replacing the full-page reloads with live updates and progress so it's clear when to wait and when to act.

🤖 Generated with Claude Code

A user marking their kid on the footage — play, pause, click, play, pause,
click — ended up with eight athletes, seven of them named "My athlete", created
inside three minutes, each bound to exactly one fragment. Scoring reads the
focal flag, so a dozen careful selections collapsed to whichever click happened
last. Their words: "it created each focal selection into a duplicate player and
in the end it just uses one selection not all of them".

`new` in the identify route means "I have not told you who this is", and it was
creating an athlete unconditionally. The client sends `new` whenever its own
athlete list has not loaded yet, which is every click made faster than a page
reload — so the faster you worked, the more duplicates you got. It now prefers
the athlete already being followed, and only creates one when there genuinely
is none.

The second half is which fragments survive. A caller that said `new` did not
know who this was and cannot have sent the fragments already bound, so replacing
the set silently discarded every earlier pick; those calls now add. The picker,
which holds the whole selection and names the athlete, still replaces — that is
what makes unticking a crop work.

apps/web/src/identifytwice.test.ts drives the real route: three clicks with no
loaded state give three athletes before this change and one athlete with three
fragments after it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 597fbc4 into master Aug 10, 2026
4 checks passed
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