Skip to content

Fixture: browser-vs-telephony parity on silence gaps (one scenario, two renders) #14

Description

@quantumCF

The failure class

The same agent that sounds clean on a browser test call can carry long
silence gaps on outbound telephony, so a test plan that stops at the browser
misses the defect entirely. Public evidence the class exists in the wild: a
provider community thread
(community thread 2475)
where browser test calls pass while outbound telephony calls carry gaps; the
thread reports multiple multi-second silence gaps on the outbound leg only. hotato should ship a fixture pair that turns
"passes in the browser, fails on the phone line" into a deterministic
parity assertion.

What exists to build on

  • The telephony-degraded class in corpus/classes/ already renders one
    scenario's exact reference_render timings a second time through
    corpus/classes/telephony_codec.py (G.711 mu-law companding plus a fixed
    packet-loss schedule), proving verdicts stay stable across codec
    degradation.
  • The candidate scan (hotato.scan.scan_recording, surfaced by
    hotato investigate --min-gap and hotato ingest --min-gap) reports
    long_response_gap candidates with their offsets and durations.
  • The capture paths for both legs are shipped (adapters/README.md):
    browser or web-call recordings and telephony recordings both arrive as
    two-channel WAVs through hotato capture, --stereo, or
    --caller/--agent.

The fixture

One scenario, two renders, one parity check:

  1. Clean render. A short conversation at 16 kHz with continuous
    turn-taking and no agent-side gap at or above the stated --min-gap
    threshold (use the default, 2.0 s).
  2. Telephony render with a gap schedule. The identical
    reference_render timings passed through telephony_codec.py, plus a
    fixed schedule that inserts two or three multi-second silence gaps into
    the agent channel at stated offsets. The label carries the schedule.

The test runs the same scan over both WAVs and asserts:

  • the clean render surfaces zero long_response_gap candidates at the
    stated threshold;
  • the telephony render surfaces exactly the inserted gaps, at their labeled
    offsets and durations, within a stated tolerance.

That is the parity claim in executable form: same scenario, same scan, the
divergence is the finding. Users then have a template for the live version
of the same check: capture the same scripted call over their web path and
their telephony path and run the identical scan on both.

Done looks like

  • The pair is built by corpus/classes/build_classes.py (or a sibling
    builder in the same deterministic pattern) and regenerates byte-identically
    with --check.
  • corpus/classes/manifest.json and corpus/classes/README.md list it.
  • One test asserts both scan results as above.
  • python -m pytest -q and python scripts/copy_lint.py both pass.

Size

One fixture pair plus one test. Good first issue: the codec path, the gap
scan, and the builder pattern all exist; the work is the gap schedule, the
labels, and the two scan assertions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions