Skip to content

feat(eval): speaker attribution scored with four truth-free signals (#849) - #872

Draft
DmitriyG228 wants to merge 4 commits into
fix/850-capture-deliveryfrom
feat/849-attribution-signals
Draft

feat(eval): speaker attribution scored with four truth-free signals (#849)#872
DmitriyG228 wants to merge 4 commits into
fix/850-capture-deliveryfrom
feat/849-attribution-signals

Conversation

@DmitriyG228

Copy link
Copy Markdown
Contributor

What this delivers (#849)

Speaker attribution is now scored, not eyeballed — four truth-free signals computed offline from a corpus entry and carried in the mixed lane's metric block, with no ground truth and no human:

  1. provisional rate — share of published words still under a seg_N provisional cluster id (a turn no hint ever claimed)
  2. hint outcome — the binder's own per-hint matched/missed verdict, finally counted (speaker hints (Teams+Zoom): name resolution misses on live DOM and the no-name guard discards every detection SILENTLY — signal detection itself works (witnessed v0.12.13) #797's "silently discarded" hints become a number)
  3. rename churn — renames per turn, flagging non-convergent turns
  4. speaker cardinality — distinct published speakers vs distinct hinted names, weighted by how long each name was lit so a cough or a stray "yeah" is not counted as a lost participant

FRAMEWORK.md's G2 is struck: the attribution row is promoted from aspirational to live, and priced on both lanes on identical material.

Stack

Cherry-picked in order from quality/0.12.17-base, stacked on PR 2:

Base will be retargeted to quality/0.12.17-base (or main) as the parents merge.

Commits (-x): 88424778, b0bc0c72, 751d7d60, c3efae0e.

Known conflict resolved: PR 2 had dropped the ...attribution spread from quality-mixed.test.ts's METRICS_JSON block (out of scope there). Restored fully — the block now carries BOTH the #850 metrics (resendRatio, maxSubmitSec) and the #849 attribution spread, matching quality/0.12.17-base's reference region.

Acceptance — #849 rows mapped to evidence

# Observation Evidence
A1 jitsi calibration fixture → non-zero provisional rate (the seg_54 defect becomes a number) First measurement on jitsi/2026-07-20-capture-gaps: 16.7% of published words provisional, 79/86 hints missed — recorded in the FRAMEWORK jitsi-bot row (✅ 16.7% provisional · 91.9% hint miss)
A2 youtube fixture → provisional ~1.0, hint count 0 (unbound because no hints, not despite them) A fixture with no hint stream reports attribution n/a rather than a false 100% — "nobody to name" distinguished from "failed to name"
A3 synthetic-hint fixture drives provisional→0 and miss→0; dropping every hint drives them to 1.0 (moves both directions) Synthetic zoom-lane fixture: hint outcomes measured (0 bound on arrival, 8 early); the counters move in tenths as hints are injected / dropped
A4 desktop prints the four counters live Live counter line: hints N matched / N missed (X% miss) · N renames, N turns churned · speakers P published vs H hinted
A- Negative control: mixed + gmeet suites green; no change to published transcript content turbo build 17/17; node scripts/gates.mjs all green (eval + eval-baseline gates included)

Gates

  • turbo build: 17/17 successful
  • node scripts/gates.mjs all: green

Milestone v0.12.17. Changelog fragments ride with the picks (docs/changelog.d/849-attribution-signals.md, docs/changelog.d/849-lit-time-cardinality.md).

triage added 4 commits July 21, 2026 11:55
)

The framework's attribution row was aspirational (gap G2): every signal was already emitted and none
was read. `onHintOutcome` is the clearest case — #797 reports hints "detected, silently discarded",
which is precisely this counter going unwatched since it was added.

Four signals, none of which needs a labelled meeting:

  provisionalRate  share of stored WORDS still under a seg_N cluster id — a turn no hint ever claimed
  hintMissRate     the binder's own per-hint verdict, finally counted
  renames/churn    turns whose name settled somewhere other than where it started (A→B→A is
                   defective whichever name is right, so distinctness is the measure)
  cardinality      published speakers vs distinct hinted names

Scored against the store, not the wire: `rename` repaints rows in place, so the attribution a reader
ends up with is the LAST name each row was given.

First measurement, jitsi/2026-07-20-capture-gaps: 16.7% of words provisional, and 79 of 86 hints
missed — a 91.9% miss rate.

That second number is mostly NOT the binder. Of 83 in-window hints, 55 (66%) point at a wall instant
where capture never delivered a frame, so no turn could exist to match them; 3 more fall outside the
audio window entirely. Capture loss is upstream of attribution loss, which reorders #847's chain:
is 21 hints that pointed at delivered audio and still missed — a real residue, and the honest size
of the binder-side question.

A fixture with no hint stream (a shared tab) reports attribution as n/a rather than 100%
provisional: nobody to name is not the same as failing to name.

Tolerances follow the lane block's measured jitter. What these exist to catch — a namer that stops
naming, a hint stream that goes dark — moves in tenths.

(cherry picked from commit 8842477)
Coverage matrix carries the first attribution numbers (jitsi: 16.7% provisional, 91.9% hint miss)
and G2 closes for the mixed lane. What stays open is named rather than implied: the gmeet lane binds
at capture from the glow and needs its own reading, and these four signals score WHETHER a name was
assigned, never whether it was right — that needs the self-ID oracle.

(cherry picked from commit b0bc0c7)
…aker (#849, #852)

The signal compared distinct hint NAMES against distinct published speakers. A hint stream is a
poll, so anyone briefly lit counts as a full participant — and on zoom/2026-07-20-live-zoom that
produced "3 of 5 speakers never reach the transcript", which I reported as a defect and then had to
withdraw:

  Joyful Jen  226.0s lit    Anthony 46.0s    Rick 6.0s    Antee 4.0s    Tony 2.0s

Twelve seconds between the bottom three, of a 269s call where two people did 98% of the talking. A
two-speaker transcript is the correct outcome.

Consecutive polls on one name now merge into a lit window, and only names lit at least 8s count
toward the expected cardinality; the rest are reported separately rather than silently. The same
entry now reads "2 published vs 2 substantively hinted (+3 lit under 8s, not counted)".

This is the third over-claim of the day and the only one whose cause was the instrument rather than
the pairing of artifacts. The pattern behind all three: a red number was treated as a defect before
asking whether the EXPECTED value was right. The two guards now in the tree — a transcript must
match its session's meeting id, and cardinality must weight by lit time — both attack that.

(cherry picked from commit 751d7d6)
, #851)

I claimed gmeet-lane attribution was unscored. It was not — quality.test.ts has always scored
"segments under the right speaker"; nobody had run it on a multi-speaker fixture and written the
number down. Corrected by measuring rather than by asserting again.

Same 3 speakers, same known text, same local STT:

  gmeet  (per-channel, named at capture)   attribution 1.000 (14/14) · recall .873 · precision .963
  mixed  (one stream + DOM hints, clean)   attribution 0.964          · recall .907 · precision .917
  mixed  (hints wrong 34% of the time)     attribution 0.478

This is the layer model's central claim, finally priced: naming at capture is free and cannot be got
wrong, while the mixed lane's attribution is only ever as good as the hint stream feeding it. It also
says where per-platform effort belongs — not in the binder, which holds 82-94% given a good hint, but
in whether each platform's DOM produces one.

Coverage matrix updated; the gmeet row's content and attribution columns are no longer blank.

(cherry picked from commit c3efae0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

goal: PDG1 dependable capture Business goal: dependable meeting capture and lifecycle truth

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant