feat(suggestions): skip live suggestions for backchannel interviewer turns - #101
Conversation
…turns Every ASR final on the interviewer channel fired a full live-suggestion request - profile, context, up to 60 transcripts - even for "mhm" or "yeah, got it", and the only sign a turn didn't need an answer was the backend's NO_SUGGESTION_NEEDED sentinel arriving after a card had already been rendered and had to be retracted. An ASR final is also an acoustic endpoint, not a finished thought, so a question split by a pause fired twice and the second aborted the first mid-render. classifyInterviewerTurn() runs in-process on the merged turn and returns Skip (drop outright, no request, no card), Answer (a completed question or directive - generate now), or Uncertain (park on an INTERVIEWER_TURN_SETTLE_MS timer any further final re-arms, so a split question is judged whole). Skip only fires when a backchannel lexicon consumes the entire turn from the front; anything it can't fully consume falls through, since a missed question is far more costly than one wasted request. Answer/Uncertain also ride the request as turn_verdict, for the backend's own speculative gate (companion PR on backend). The client no longer appends a Pending card on request start either - it holds for LIVE_SUGGESTION_RENDER_DELAY_MS so a turn the backend gate suppresses in that window produces no card at all instead of one that flashes and disappears. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ust its last block A pause longer than TRANSCRIPT_INTER_TRANSCRIPT_GAP_MS keeps two Other blocks separate even with no candidate turn between them. Classifying only the last block read a real question as backchannel whenever it was followed by a standalone acknowledgement, dropping it silently - no request, no card, no error. Extracted as selectTrailingOtherTurn so the concatenation is unit-testable without driving real wall-clock gaps through ingest(). Also fixes a doc link in CLAUDE.md pointing turn_verdict readers at the renderer types instead of main. Addresses gitar-bot review findings on PR #101.
Code Review ✅ Approved 2 resolved / 2 findingsAdds deterministic classification to skip live suggestions for backchannel interviewer turns and delays pending card creation to prevent UI flashing. Addresses findings regarding block inspection scope and documentation links. ✅ 2 resolved✅ Edge Case: Skip verdict only inspects the last merged interviewer block
✅ Quality: CLAUDE.md links turn_verdict types to the wrong file
OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
Summary
classifyInterviewerTurn()(src/main/utils/interviewer-turn.ts), an in-process, deterministic first stage that runs on the merged interviewer turn and returnsSkip(pure backchannel - drop outright, no request, no card),Answer(a completed question or directive - generate immediately), orUncertain(park on anINTERVIEWER_TURN_SETTLE_MStimer that any further interviewer final re-arms, so a question an ASR final split mid-sentence is judged whole).Skiponly fires when a backchannel lexicon consumes the entire turn from the front - deliberately asymmetric, since a missed question is silent and unrecoverable mid-interview while a wasted request just costs one ignored card.transcript.service.tsnow schedules the suggestion through this classifier instead of firing unconditionally on every interviewer final.Answer/Uncertainride the request asturn_verdictfor the backend's own speculative gate (PowerInterviewAI/backend#49).suggestion-live.service.tsno longer appends aPendingcard the moment a request starts - it holds forLIVE_SUGGESTION_RENDER_DELAY_MS, so a turn the backend gate suppresses in that window produces no card at all instead of one that flashes and is retracted.Fixes #100.
Test plan
pnpm lint- cleanpnpm exec tsc -p tsconfig.electron.json --noEmit/tsconfig.app.json- cleanpnpm test:main- all checks passedtest/interviewer-turn.test.mjs(Skip/Answer/Uncertain classification, both directions of the asymmetry, fragment-waits-for-continuation)