Systems and subsystems

The runner and its routing rules

One script takes a directory of audio and produces the TSV, one explanation JSON per file, timings and a resumable cache. Inside it, a short list of fixed rules over measured facts decides what each detector's result may do. That list is the orchestrator.

In plain words

Orchestration here is not a learned router and not a language model. Every detector runs on every file (the whole test set is about 95 minutes of audio, so compute was never the constraint). What the rules decide is what each result is allowed to do to the score, and every decision is written to the file's routing log so it can be checked afterwards. The rules are on the How it decides page as a diagram; this page is the reference.

What goes in and comes out

In: a directory of audio files and, optionally, the sponsor's template TSV that fixes the row order. Out, under the output directory: the TSV (never overwritten; a clash gets a timestamp suffix), a results/ folder with one JSON per file, a resumable results.jsonl, timings.csv, a sidecar CSV of the per-detector values, run_meta.json, and the preflight outputs.

Where it lives

src/hearsay/pipeline.py: the constants, the Models loader, analyze_clip, routing_log, fusion_line, final_score and refuse. scripts/run_pipeline.py: the command line, the template reader, the cache, the preflight, the TSV writer and the exit codes.

The rules and where each is set

Command line

--in, --out, --template, --team (the default is not our team name; the deliverable passes CrossExam), --fusion (default: the shipped constants file since the 12:35 switch), --rule, --policy, --flip (writes the pre-flipped twin through the same map), --detectors (cannot narrow the set the constants file needs), --m5, --threads (capped at 6source: src/hearsay/pipeline.py line 102 (GitHub; assumes main is public)), --require-offline, --no-truncate, --fresh, --compare-tsv, --preflight. Environment variables mirror the main flags (run_pipeline.py, lines 98–144).

Preflight and cache

Before scoring, four seconds of silence and a three-note chord are scored twice through the whole pipeline: both probabilities must be finite and agree, every scorer must be ok, neither clip may pass the gate, and both must land below the block (run_pipeline.py, lines 318–354). The cache header records the models, the constants file's hash and the scorer set; a mismatch moves the old cache aside; rule, policy and polarity are not part of the identity, so cached logits are re-fused in a fraction of a second (run_pipeline.py, lines 247–303).

Status

Built; the default constants file is the shipped rule since the 12:35 switch on Saturday. Live from audio on all 1,671source: README.md, section score-a-directory-on-the-mac files it reproduces the submitted TSV with Spearman 1.000000source: README.md, section score-a-directory-on-the-mac and a maximum difference of 9.3e-4source: README.md, section score-a-directory-on-the-mac.

Numbers

Speed with M5 loaded: 1.34 ssource: README.md, section score-a-directory-on-the-mac per file; peak memory 4.0 GBsource: README.md, section score-a-directory-on-the-mac. The router-on versus router-off ablation is on How it decides.

Known limits

The verdict field compares the pre-map fused probability with 0.5source: src/hearsay/pipeline.py line 652 (GitHub; assumes main is public) and ignores --flip; it is a label for the report, not the ranking the metric scores. A comment in the runner and the Docker build script still name the previous default; the code's default is the shipped file.

Tests that pin it

tests/test_pipeline.py: response shape, the map applied exactly once, the routing log reads the detector features (order and wording), lossy/seams/hum/drift wording, the default answer applied when there is no speech, a gate error does not gate, a failed fused detector is imputed and logged, a decode failure sits below the block, re-fusing switches rule, policy and polarity without models, scorers come from the constants file, the cache identity gates the resume and tolerates a torn line, the template is read in order and missing files are flagged, exit code 4 when a weighted scorer fails, the preflight refuses a failing scorer, --require-offline refuses without the environment.

Sources

README, "Orchestration"; the runner report; the worked examples; the M5-scorer run spec.