Skip to content

fix(speaker): cross-condition negative-exemplar veto via condition transport#1497

Merged
r3dbars merged 1 commit into
mainfrom
claude/negative-veto-cross-condition
Jul 7, 2026
Merged

fix(speaker): cross-condition negative-exemplar veto via condition transport#1497
r3dbars merged 1 commit into
mainfrom
claude/negative-veto-cross-condition

Conversation

@r3dbars

@r3dbars r3dbars commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What

Strengthens the negative-exemplar veto (#1487) so it fires cross-condition, implementing recommendation #3 of the PR #1493 eval (docs/speaker-eval-exemplar-delta-2026-07.md): "give a profile's negative exemplars the same multi-condition treatment as its positive ones."

Why

PR #1493 measured the veto as "sound but regime-limited": after a correction it removes 46% of repeat wrong-matches in-room (AMI) but only 12% cross-condition (VoxCeleb). A rejected in-room sample and a later telephone/VoIP sample of the same rejected impostor sit too far apart in embedding space for the raw cosine to clear the 0.80 veto floor — so a correction made in one audio condition failed to protect the owner in another. The positive side already closed this exact gap with multi-exemplar voiceprints (#1488); the negative side (a single rejected embedding) had no analog.

How

SpeakerNegativeExemplarPolicy gains a condition-transported negative similarity. Beyond raw cosine to each stored rejected sample, the candidate is compared against each rejected sample transported along the profile's own observed condition shiftsunit(exemplar) − average, reusing the positive multi-exemplar voiceprints. Channel/condition shifts (clean → compressed remote → telephone) are largely speaker-independent, so a rejected sample shifted by a condition the profile has actually seen approximates the same rejected voice returning in that condition.

Owner-safe by construction (the #1493 guardrail is the priority):

  • Transport only along +(exemplar − average) — real, forward, profile-observed conditions. Bidirectional/synthetic directions were measured to leak owner-collateral and are not used.
  • A profile with no positive exemplars derives nothing → reduces exactly to the raw maxNegativeSimilarity → single-condition profiles (and any store with no negatives) are byte-for-byte unchanged.
  • The 0.80 floor and the ≥ positiveSimilarity owner gate are untouched. Transport only widens which impostor returns are caught; it never lowers the floor, so a genuine owner — closer to its own fingerprint than to a transported impostor sample — is still protected.

Results — real qmatrix corpus (SpeakerExemplarDeltaEvalTests)

Same harness/corpus/operating point as #1493. RAW = single stored rejected sample (pre-fix); TX = condition-transported (this PR); both use the unchanged 0.80/≥pos gate.

AMI (in-room, 147 profiles, 535 cross-condition wrong re-matches, 5773 owner checks)

metric RAW TX Δ
cross-condition vetoed-among-re-match 0.350 0.374 +7.0% rel
aggregate vetoed-among-re-match 0.460 0.483 +0.023
owner-collateral 2.17% 2.32% +0.16pp (+9 of 5773)

VoxCeleb (single-utterance, 30 profiles)byte-identical (0.123→0.123; owner-collateral 1.56%→1.56%): no condition structure to transport along, and no regression.

On VoxCeleb's 12%

It doesn't move — and that is correct, not a miss. VoxCeleb is single-short-utterance-per-meeting, so a "cross-condition" replay differs from the rejected sample in content/session as much as in channel; a channel transport can't (and shouldn't) bridge that. Real returning Transcripted users are AMI-like (repeated appearances across conditions → multi-exemplar structure), which is the regime this improves. Pushing VoxCeleb's 12% harder was investigated across floor-lowering, ramped owner-margins, global channel subspaces, and orthogonal-complement distance — every mechanism trades owner-collateral for veto coverage at a ≈1:1-or-worse absolute rate (best case removed +39 wrong re-matches while adding +56 owner false-vetoes), which is net-negative in production and violates the #1493 guardrail. Condition transport is the one lever that gains cross-condition coverage without a net owner cost.

Full write-up: docs/speaker-eval-negative-veto-cross-condition-2026-07.md.

Tests

  • SpeakerNegativeExemplarPolicyTests 12/12 — new fixtures: same-impostor-different-condition (veto now fires), owner-different-condition (no false veto), no-exemplars-equals-raw (byte-identical fallback).
  • SpeakerNegativeExemplarTests 7/7, SpeakerNamingSimulationRunnerTests 7/7, full Core suite 714 passed / 0 failed (13 corpus-gated skips), SpeakerExemplarDeltaEvalTests passes on the real corpus.

Coordination

Orthogonal to #1496 (average-based auto-accept margin): that PR changes the auto-accept margin computation; this changes the negative-veto representation. They touch SpeakerMatchingService.swift and SpeakerExemplarDeltaEvalTests.swift in different regions. #1496 should land first; I'll rebase this onto it, keeping both changes.

Refs #1493, #1487, #1488.

🤖 Generated with Claude Code

…ansport

The negative-exemplar veto (#1487) was "sound but regime-limited" (eval in
#1493): after a correction it removed 46% of repeat wrong-matches in-room
(AMI) but only 12% cross-condition (VoxCeleb). Root cause: a single rejected
in-room sample and a later telephone/VoIP sample of the same rejected impostor
sit too far apart in embedding space for the raw cosine to clear the 0.80 veto
floor. The positive side already closed this gap with multi-exemplar
voiceprints (#1488); the negative side — one rejected embedding — had no analog.

Give the negative side the same multi-condition treatment (eval rec #3):
compare the candidate against each rejected sample AND against that sample
transported along the profile's own observed condition shifts (unit(exemplar) −
average). Channel/condition shifts are largely speaker-independent, so a
rejected sample shifted by a condition the profile has actually seen
approximates the same rejected voice returning in that other condition.

Owner-safe by construction:
- transport only along +(exemplar − average) — real, forward, profile-observed
  conditions; bidirectional/synthetic directions were measured to leak
  owner-collateral and are not used.
- a profile with no positive exemplars derives nothing → reduces exactly to the
  raw maxNegativeSimilarity → single-condition profiles unchanged.
- the 0.80 floor and the ≥positiveSimilarity owner gate are untouched; transport
  only widens which impostor returns are caught, never lowers the floor.

Real qmatrix eval (SpeakerExemplarDeltaEvalTests): AMI cross-condition
vetoed-among-re-match 0.350 → 0.374 (+7.0% rel) with owner-collateral flat
(2.17% → 2.32%, +9 of 5773 checks). VoxCeleb (single-utterance corpus, no
condition structure) byte-identical, incl. owner-collateral — no regression.
Pushing VoxCeleb's 12% further was investigated and rejected: every mechanism
that moves it trades owner-collateral ~1:1, violating the #1493 guardrail.

See docs/speaker-eval-negative-veto-cross-condition-2026-07.md. Refs #1493.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@r3dbars r3dbars force-pushed the claude/negative-veto-cross-condition branch from 509a9c7 to c790cfe Compare July 7, 2026 21:21
@r3dbars r3dbars merged commit 776096e into main Jul 7, 2026
6 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