Skip to content

TT-7621 fix: offer Record once the reference audio stops - #529

Open
nabalone wants to merge 4 commits into
developfrom
TT-7621_pbt-record-after-playback-stops
Open

TT-7621 fix: offer Record once the reference audio stops#529
nabalone wants to merge 4 commits into
developfrom
TT-7621_pbt-record-after-playback-stops

Conversation

@nabalone

Copy link
Copy Markdown
Collaborator

Fix 3 of the PBT series. Into #527.

The fault

Pausing the reference playback part way through left Record disabled with no way forward but replaying the whole clause.

allowRecord needs currentClausePlayed and phase 'recordReady', and handleRegionPlayEnd was the only thing that set them — so the step depended on a region-out that does not always come. A user pause has none by definition.

The fix

The step now treats the reference audio stopping as the signal that the clause has been heard — which is the thing the user actually did. A stop reported within 250ms of playback starting is the seek that started it rather than the audio, so those are ignored; auto-segmenting never produces a clause anywhere near that short.

Also fixes the waveform selection and the segment label disagreeing after a segment is selected, which came from the same stranded state.

Deliberately not fixed here

Record stays operable while a clicked segment plays is still red. I tried it on this branch and backed it out: the cause is a spurious park (wavesurfer emits the clicked clause's region-out during the seek, ~10ms in, so the step parks on a segment that is about to play). Suppressing that park does fix Record, but it then strands the click flow entirely — playback started by clicking a segment is not region-bounded and reports neither a region-out nor a stop, so nothing ever re-enables Record. Shipping that would trade a wrong-enabled button for a dead end.

The honest fix is at the player level: a segment click should start region-bounded playback that reports its end like playCurrentClause does. Worth its own ticket — it also means clicking a segment currently plays past it into the following audio.

Verification

  • defects spec: pause test now green
  • selection spec: 5 of 7 green (remaining: swallowed adjacent click — fixed in TT-7621 fix: act on a segment click instead of swallowing it #528 — and Record-during-playback, above)
  • behaviour specs: 13 + 16 green
  • jest PassageDetailCarefulSpeech: 24 green (this touches shared guided-record code)

🤖 Generated with Claude Code

@nabalone

Copy link
Copy Markdown
Collaborator Author

Claude opened this but I don't think we actually want this change in behavior

@nabalone nabalone closed this Aug 24, 2026
@nabalone

Copy link
Copy Markdown
Collaborator Author

Actually, asking the team

@nabalone nabalone reopened this Aug 24, 2026
@nabalone

Copy link
Copy Markdown
Collaborator Author

We decided that for now we do want to make this change and allow recording after a pause. And then when we raise it to the product owners, if they object we can back it back out

@nabalone
nabalone marked this pull request as ready for review August 24, 2026 21:05
@nabalone
nabalone force-pushed the TT-7621_pbt-record-after-playback-stops branch from 4751e03 to 3c433f6 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:39
Pausing the reference playback part way through left Record disabled with no way
forward but replaying the whole clause.

Record needs currentClausePlayed and phase 'recordReady', and handleRegionPlayEnd
was the only thing that set them - so the step depended on a region-out that does
not always come. A user pause has none by definition. The step now treats the
reference audio stopping as the signal that the clause has been heard, which is
the thing the user actually did.

A stop reported within 250ms of playback starting is the seek that started it
rather than the audio, so those are ignored; auto-segmenting never produces a
clause anywhere near that short.

Also fixes the waveform selection and the segment label disagreeing after a
segment is selected, which came from the same stranded state. Both tests are
renamed to what they now assert.

Not fixed here, and still red: Record stays operable while a clicked segment
plays. Suppressing the spurious park that causes it turns out to strand the
click flow instead, because playback started by clicking a segment is not
region-bounded and reports neither a region-out nor a stop - so the honest fix
is at the player level, and it is not this commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Devin flagged that clausePlaybackStartedAtRef was only set by playCurrentClause,
so playback started any other way - the user pressing Play, which goes through
handleBeforeSourcePlay - left the timestamp stale. The 250ms seek-suppression
window then compared against an old time, and a stop caused by that start would
fall outside the window and mark the clause played before it had been. Correct,
and exactly the failure the window exists to prevent.

The timestamp is now re-based wherever playback begins: in handleBeforeSourcePlay
for a user-initiated play, and on the play-status change for the real start
however it was triggered, as well as in playCurrentClause for the seek.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comments and one behaviour-preserving split, no logic change.

The seek-suppression window needed explaining rather than naming: starting a
clause seeks the playhead to its start, and that seek reports a stop of its own
before anything has been heard, so elapsed playback time is what separates it
from a real stop such as a user pause.

Split `if (playingNow || !recordingPassStartedRef.current) return;` into its two
unrelated halves - one is "this is a start, not a stop", the other is "the listen
pass has nothing to record" - and said why the recording/saving guard reads refs
rather than state.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This branch was cut before #527 gained the `@known-defect` tagging, so its
copy of the defects spec won the merge and took the tags with it. Every
still-broken repro then ran in CI and failed the check.

Restores develop's tags on the three defects this branch does not fix, and
keeps the pause repro untagged — that one is fixed here, so it should run.

Also tags `clicking back to segment 2 leaves the step on segment 3` in the
selection spec. It is a known defect (fixed in #536) that #527 missed, so it
was failing CI untagged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nabalone
nabalone marked this pull request as draft August 25, 2026 14:25
@nabalone
nabalone marked this pull request as ready for review August 25, 2026 15:00
@gtryus
gtryus requested a lite review from Copilot August 25, 2026 16:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts the Phrase Back Translation (PBT) guided recording flow so Record becomes available when reference playback stops (e.g., user pauses), eliminating a dead-end where the step previously depended on a region-out event that may never fire. This aligns the step’s state machine with actual user intent (“I stopped playback, so I’m done listening to this clause”) and updates Cypress specs accordingly.

Changes:

  • Treat “source audio stopped” as a clause-heard signal (with a short suppression window to ignore seek-induced stop events).
  • Update CT coverage: convert the “pause strands Record” repro from a known-defect test into a passing regression test.
  • Tag the still-known defect around out-of-order segment navigation in the selection spec so it can be filtered as a known defect.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/renderer/src/components/PassageDetail/PassageDetailPhraseBackTranslate.selection.cy.tsx Tags an existing defect repro as @known-defect to keep normal CT runs meaningful.
src/renderer/src/components/PassageDetail/PassageDetailPhraseBackTranslate.defects.cy.tsx Converts the “pause leaves Record disabled” case into a passing regression assertion.
src/renderer/src/components/PassageDetail/PassageDetailGuidedPhraseRecord.tsx Implements stop-based progression to recordReady and currentClausePlayed, with seek-stop suppression.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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.

2 participants