Skip to content

HPB live feed + gap-fill poll + auto-enable captions - #4

Merged
ikusteu merged 4 commits into
mainfrom
feat/d-830-live-ui-hpb-feed
Oct 30, 2026
Merged

ikusteu merged 4 commits into
mainfrom
feat/d-830-live-ui-hpb-feed

Conversation

@ikusteu

@ikusteu ikusteu commented Oct 27, 2026

Copy link
Copy Markdown
Member

Stacked on #3 (base is feat/d-830-live-ui, not main) — review after it.

What

A followup that changes how the transcript panel gets the live feed, and makes it self-activating:

  • Auto-enable captions on activation. Clicking the bookmarklet now turns Talk's live captions on for your session (the same thing the CC button does), so you are on the HPB feed immediately — no manual step.
  • HPB stream for liveness, poll for gaps. The panel no longer polls for the live feed. It takes finals from Talk's signalling in near-real-time and polls /history only to fill gaps, deliver joins, and catch up. Both sources share one seq space, so the merge is exact — no duplicates, no drops, no content-matching.

How the two streams share a seq

The worry was correlating a live stream and a polled stream without a shared id. Talk's filtered SimpleWebRTC.on('transcript') event hardcodes four fields and drops a seq, but the raw connection.on('message') event (what Talk's own SimpleWebRTC listens to) carries the full payload. So cassini-live stamps each HPB final with its buffer seq, the browser reads it off the raw message event, and the live feed and the poll key into the same timeline. No WebSocket monkey-patching, no fuzzy matching.

  • Server (send_transcript): each HPB final carries its buffer seq. Version unchanged (0.10.0).
  • tap.js: subscribe to connection.on('message'); emit finals (with seq) + partials; re-attach on rejoin.
  • store.js: a reorder buffer over the shared seq — render at applied+1, hold out-of-order live finals until the gap fills, dedup by seq, step over server-evicted entries. Append-only.
  • session.js: poll demoted to gap-fill/joins, since=<contiguous seq>, ~3s; enables captions on call start.
  • captions.js: POSTs Talk's live-transcription endpoint (idempotent, best-effort).

Validation

  • Backend: 12/12 history tests (incl. seq-on-HPB-final), lint + manifest green.
  • Frontend: 10/10 unit (reorder buffer, gap-hold, dedup, eviction-skip); 13/13 Playwright (live feed, gap-hold + poll-fill, dedup, auto-enable, catch-up, joins, partials, scoping, teardown, loader).
  • Real harness e2e: the viewer clicks only the bookmarklet (no CC button) and sees the full conversation — two speakers, own speech, join markers. Screenshot in docs/transcript-panel-harness.png.

Note

The live feed reads a Talk-internal connection.on('message') event — stable (Talk routes its own messages through it), with window.signalingSocket as a raw fallback if a future Talk version changes signalling internals.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WEKiygi6s6G31srWmN5rnz

@ikusteu
ikusteu added this pull request to stack #5 October 27, 2026 09:58
Base automatically changed from feat/d-830-live-ui to main October 29, 2026 09:22
@ikusteu
ikusteu force-pushed the feat/d-830-live-ui-hpb-feed branch 3 times, most recently from f10db6f to e8ddfae Compare October 30, 2026 21:40
ikusteu and others added 4 commits October 30, 2026 22:52
The panel no longer polls for the live feed. It takes finals from Talk's
signalling in near-real-time and polls /history only to fill gaps, deliver
joins and catch up — both sources sharing ONE seq space, so the merge is
exact (no content-matching, no duplicates, no drops).

- Server (0.10.0, no bump): send_transcript stamps each HPB final with its
  buffer seq. Talk's filtered 'transcript' event drops extra fields, but the
  raw signalling 'message' event keeps them — so the browser gets the seq.
- tap.js: subscribe to connection.on('message') (what Talk's own SimpleWebRTC
  uses) for the raw payload incl. seq; emit finals (seq) and partials; still
  sees own lines; re-attaches on rejoin.
- store.js: a reorder buffer over the shared seq — render at applied+1, hold
  out-of-order live finals until the gap fills, dedup by seq, and step over
  entries the server has evicted. Append-only rendering.
- session.js: poll is demoted to gap-fill/joins, asking since=<contiguous seq>
  every ~3s; on a call start it enables captions for this session.
- captions.js: POST Talk's live-transcription endpoint on activation, so every
  viewer is on the HPB feed (idempotent, best-effort).

Feasibility note (Ivan asked to flag blockers): the seq cannot ride the
filtered 'transcript' event, but it does ride the raw 'message' event — so the
design is clean, with no WebSocket monkey-patching and no fuzzy correlation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WEKiygi6s6G31srWmN5rnz
@ikusteu
ikusteu force-pushed the feat/d-830-live-ui-hpb-feed branch from e8ddfae to e6114aa Compare October 30, 2026 21:53
@ikusteu
ikusteu merged commit e790ff4 into main Oct 30, 2026
8 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