feat(key): multi-profile key ensemble cross-check (accuracy PR-B3) - #206
Merged
Conversation
analyze_key now runs KeyExtractor for edma + temperley + krumhansl in
full mode and emits an additive, full-only keyEnsemble field:
{method:'profile_vote.v1', agreement, profiles[], alternates[]}.
SURFACING-ONLY: the shipped key/keyConfidence/keyProfile are unchanged —
still EDMA (golden diff confirms only keyEnsemble was added; the key value
is byte-identical). The vote is evidence until the GiantSteps Key gate
proves it beats EDMA-alone. Pre-registered decision rule (frozen before
the run) in incorporations/key-ensemble-decision-2026-07-04.md: adopt iff
mirexWeighted gain >= +0.02 AND no exact-rate regression beyond 0.01, on
>= 400 evaluable clips. agreement (0-3) is a ready confidence calibrator;
alternates hedge the relative-major/minor error that is EDMA's typical
miss.
Gated on full mode (like tuning*): fast mode is unchanged and pays no
extra KeyExtractor cost. Any/all profile failures degrade gracefully
(null ensemble; EDMA key still ships).
Contract mirrors (tripwire #4): analyze.py + server_phase1 forwarding,
JSON_SCHEMA.md inventory/full-only/field-row, test_audio_fixture full-mode
key set, types/measurement.ts KeyEnsemble, backendPhase1Client forwarding,
phase1FullPayload fixture, golden re-baselined (new key, structural).
Tests: test_key_ensemble (agreement/alternates, full-vs-fast, all-fail).
Backend 1302 OK, fundamentals gate green, frontend verify green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4wfz87k6kzJqkKLKZE7YL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase B of the accuracy program: cross-checks the single EDMA key read against two more profiles to expose (and later reduce) EDMA's typical miss — the relative-major/minor flip.
What
analyze_keynow runsKeyExtractorfor edma + temperley + krumhansl in full mode and emits an additive, full-onlykeyEnsemble:{method: "profile_vote.v1", agreement, profiles[], alternates[]}.Surfacing-only, deliberately
The shipped
key/keyConfidence/keyProfileare unchanged — still EDMA. The golden diff confirms it: onlykeyEnsemblewas added; the key value is byte-identical. The vote is evidence, not yet the label, until it earns promotion on real audio.Pre-registered gate (frozen before the run)
incorporations/key-ensemble-decision-2026-07-04.mdrecords the rule ahead of the deciding run so the outcome can't be rationalized after seeing numbers: adopt the vote as the shipped label iff MIREX-weighted gain ≥ +0.02 AND no exact-rate regression beyond 0.01, on ≥ 400 evaluable GiantSteps Key clips. The harness (scripts/evaluate_giantsteps.py --subset key) is already in place from Phase A — this just needs the operator's audio fetch. Until then,agreement(0–3) is a ready confidence calibrator andalternateshedge the display.Cost / safety
Gated on full mode like the tuning pass — fast mode is unchanged and pays no extra
KeyExtractorcost. Any/all profile failures degrade gracefully (null ensemble; the EDMA key still ships).Contract mirrors (tripwire #4)
analyze.py+server_phase1forwarding · JSON_SCHEMA.md inventory + full-only list + field row ·test_audio_fixturefull-mode key set ·types/measurement.tsKeyEnsemble·backendPhase1Clientforwarding ·phase1FullPayloadfixture · golden re-baselined (new key, structural).Tests
test_key_ensemble(agreement + alternates, full-vs-fast gating, all-profiles-fail). Backend 1302 OK, fundamentals gate green, frontend verify green.🤖 Generated with Claude Code
https://claude.ai/code/session_01T4wfz87k6kzJqkKLKZE7YL
Generated by Claude Code