Skip to content

TT-7621 WIP: undo a take whose upload lands after it was discarded - #531

Draft
nabalone wants to merge 3 commits into
developfrom
TT-7621_pbt-discard-take-mid-upload
Draft

TT-7621 WIP: undo a take whose upload lands after it was discarded#531
nabalone wants to merge 3 commits into
developfrom
TT-7621_pbt-discard-take-mid-upload

Conversation

@nabalone

@nabalone nabalone commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

WIP — do not merge. The repro test is still red. Pushed so the analysis is not lost.

The fault

Clearing a take while its upload is in flight brings the take back: the upload finishes, the mediafile reaches rowData, and the step shows a take the user deleted — Record disabled, segment counted as recorded, audio they rejected stored.

Worth taking regardless of the rest: a harness timing bug

With putDelayMs, the fake server added the mediafile when the PUT started rather than when it completed, so the take appeared in rowData while the upload was still in flight. A test about what happens during an upload was really testing what happens after one — and it is what made my first attempt at this fix look like it wasn't firing at all. Storage is now timed from the PUT completing.

Also here: the step's state machine is now observable

data-phase, data-allow-record, data-unit-index on the step container (plus a temporary data-discard-pending). The listen/record state machine drives most of this step's behaviour and was invisible from outside. Two investigations tonight collapsed from repeated guessing to one run each once it could be read — including the one that stopped me shipping a bad fix in #529.

The fix attempt

  • uploadInFlightRef, so "is an upload still in flight" can be answered. savingRecording cannot: by the time the delete icon is clickable it is already false.
  • afterUploadCb returns early for a discarded take instead of forcing phase 'recorded' and marking the segment optimistically complete.
  • An effect that removes the mediafile once it appears in rowData, since at afterUploadCb time there is nothing to address yet.

Where it stands

With the timing corrected, the discard flag now survives to afterUploadCb as intended — confirmed by sampling data-discard-pending. But the step still ends in phase 'recorded' with the take shown, so the cleanup effect's removeRecord is not taking effect: either it loses a race with the navigation effect's completed branch (which sets 'recorded' as soon as completedIndices contains the index), or the removal itself is not landing.

Next step is to log around the removal rather than infer.

🤖 Generated with Claude Code

@nabalone
nabalone force-pushed the TT-7621_pbt-segment-selection-and-recorder-state branch from 5bef41e to 3f3ee57 Compare August 24, 2026 21:56
@nabalone
nabalone force-pushed the TT-7621_pbt-discard-take-mid-upload branch from 0d56f45 to 59682ff Compare August 24, 2026 21:57
Base automatically changed from TT-7621_pbt-segment-selection-and-recorder-state to develop August 24, 2026 22:33
nabalone and others added 3 commits August 25, 2026 08:40
INCOMPLETE - the repro test is still red. Committed so the analysis is not lost.

Clearing a take while its upload is in flight brings the take back: the upload
finishes, the mediafile reaches rowData, and the step shows a take the user
deleted with Record disabled and the segment counted as recorded.

What is here:
- uploadInFlightRef, so "is an upload still in flight" can actually be answered.
  savingRecording cannot answer it: by the time the delete icon is clickable it
  is already false, which is why an earlier attempt at this never triggered.
- afterUploadCb returns early for a discarded take instead of forcing phase
  'recorded' and marking the segment optimistically complete.
- an effect that removes the mediafile once it appears in rowData, since at
  afterUploadCb time there is nothing to address yet.

Why it is still red: the delete icon is still present at the end of the test,
so something puts the step back into phase 'recorded'. The most likely candidate
is the recording-pass navigation effect's completed branch - once the take is in
rowData, completedIndices contains the current index and that branch sets
'recorded' - racing the cleanup effect above. Confirming it needs the step's
phase to be observable; adding data-phase to the container made short work of
the equivalent question on the Record-during-playback investigation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two things, both from chasing the discard-mid-upload defect.

Harness: with putDelayMs the fake server added the mediafile when the PUT
started, not when it completed, so the take appeared in rowData while the upload
was still in flight. A test about what happens *during* an upload was really
testing what happens after one - and it is what made the first attempt at this
fix look like it was not firing. Storage is now timed from the PUT completing.
Worth taking regardless of the rest of this branch.

Step: data-phase, data-allow-record, data-unit-index and (temporarily)
data-discard-pending on the container. The listen/record state machine drives
most of this step's behaviour and was invisible from outside, which made a wrong
Record state guesswork to diagnose; two investigations tonight collapsed to one
run each once it could be read.

Still red. With the timing corrected the discard flag now survives to
afterUploadCb as intended, but the step still ends in phase 'recorded' with the
take shown, so the cleanup effect's removeRecord is not taking effect - either it
is losing a race with the navigation effect's completed branch, or the removal
itself is not landing. Next step is to log around the removal rather than infer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Still red. Third and last attempt tonight; recorded so tomorrow starts from
what is known rather than from scratch.

The marker is now the unit index that was discarded rather than a boolean, and
neither afterUploadCb nor the cleanup effect clears it on the other's behalf:
whichever of them runs first, the other still has to act. That was the flaw in
the previous attempt - sampling showed the cleanup effect deleting the arriving
mediafile and consuming the flag, and afterUploadCb then running with nothing
set and taking the ordinary success path, so the segment ended up 'recorded'
with the take shown and optimistically complete. It also clears the marker when
a new take starts, so a later recording on the same segment is not mistaken for
the discarded one.

What sampling established, for whoever picks this up:
- the discard marker is set (uploadInFlightRef answers correctly)
- the mediafile does arrive and the cleanup effect does delete it - rowData
  never grows, the row appears and goes between two 50ms samples
- the step still ends in phase 'recorded' with the delete icon showing

So what remains is not the deletion but the phase: something re-asserts
'recorded' after the cleanup. The navigation effect's completed branch is the
prime suspect (it sets 'recorded' whenever completedIndices contains the current
index) together with the optimistic-completion set, which afterUploadCb populates
and which is not rowData-backed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nabalone
nabalone force-pushed the TT-7621_pbt-discard-take-mid-upload branch from 59682ff to 743eded Compare August 25, 2026 12:40
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