FA-80976 / Music interval and transposition theory / Open access
Key signature size for a named tonic: unknown mode treated as major · case 01
A dorian or capitalised Major request returns a major signature instead of None.
ROOT CAUSE
The mode guard only rejects empty values, so any unknown mode falls through to the major branch.
VERIFIED REPAIR
Restore the mode validation step so that it reads `if mode not in ('major', 'minor'):`.
Unsuccessful approach: Checking that the mode is a string still accepts arbitrary unknown mode names.
Case contract
Input [tonic, mode] with tonic a letter optionally followed by one # or b, and mode major or minor. The signature is the letter position on the line of fifths (F -1, C 0, G 1, D 2, A 3, E 4, B 5) plus 7 per sharp and minus 7 per flat; minor keys use the relative major, three fifths flatward. Return the count (positive sharps, negative flats) or None if it lies outside -7..7 or the input is invalid.
Why this case matters
Pitch spelling and interval arithmetic decide the notes that notation, transposition and analysis tools display or play.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'F': -1, 'C': 0, 'G': 1, 'D': 2, 'A': 3, 'E': 4, 'B': 5}
if not isinstance(x, list) or len(x) != 2:
return None
tonic, mode = x
if not mode:
return None
if not isinstance(tonic, str) or not tonic or tonic[0] not in base:
return None
rest = tonic[1:]
if rest not in ('', '#', 'b'):
return None
acc = {'': 0, '#': 1, 'b': -1}[rest]
fifths = base[tonic[0]] + 7 * acc
if mode == 'minor':
fifths -= 3
if fifths < -7 or fifths > 7:
return None
return fifths
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(['C', 'major'], 0), (['G', 'major'], 1), (['F', 'major'], -1), (['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['G#', 'minor'], 5), (['D#', 'minor'], 6), (['A#', 'minor'], 7), (['C', 'dorian'], None), (['C', 'Major'], None)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("oracle %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | 0 | 0 | Passed |
| oracle 1 | 1 | 1 | Passed |
| oracle 2 | -1 | -1 | Passed |
| oracle 3 | 6 | 6 | Passed |
| oracle 4 | -6 | -6 | Passed |
| oracle 5 | 7 | 7 | Passed |
| oracle 6 | 0 | None | Failed |
| oracle 7 | 0 | None | Failed |
SHA-256 / f54cc6a73b42b776387ebb565c076cb592a25569939957603bc3ac19ae2d3f95
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'F': -1, 'C': 0, 'G': 1, 'D': 2, 'A': 3, 'E': 4, 'B': 5}
if not isinstance(x, list) or len(x) != 2:
return None
tonic, mode = x
if not isinstance(mode, str):
return None
if not isinstance(tonic, str) or not tonic or tonic[0] not in base:
return None
rest = tonic[1:]
if rest not in ('', '#', 'b'):
return None
acc = {'': 0, '#': 1, 'b': -1}[rest]
fifths = base[tonic[0]] + 7 * acc
if mode == 'minor':
fifths -= 3
if fifths < -7 or fifths > 7:
return None
return fifths
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(['C', 'major'], 0), (['G', 'major'], 1), (['F', 'major'], -1), (['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['G#', 'minor'], 5), (['D#', 'minor'], 6), (['A#', 'minor'], 7), (['C', 'dorian'], None), (['C', 'Major'], None)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("oracle %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | 0 | 0 | Passed |
| oracle 1 | 1 | 1 | Passed |
| oracle 2 | -1 | -1 | Passed |
| oracle 3 | 6 | 6 | Passed |
| oracle 4 | -6 | -6 | Passed |
| oracle 5 | 7 | 7 | Passed |
| oracle 6 | 0 | None | Failed |
| oracle 7 | 0 | None | Failed |
SHA-256 / 0965d1ca8f5399200748d8c1c45820a4a2154559921fe988c96e54c60ed15ef3
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'F': -1, 'C': 0, 'G': 1, 'D': 2, 'A': 3, 'E': 4, 'B': 5}
if not isinstance(x, list) or len(x) != 2:
return None
tonic, mode = x
if mode not in ('major', 'minor'):
return None
if not isinstance(tonic, str) or not tonic or tonic[0] not in base:
return None
rest = tonic[1:]
if rest not in ('', '#', 'b'):
return None
acc = {'': 0, '#': 1, 'b': -1}[rest]
fifths = base[tonic[0]] + 7 * acc
if mode == 'minor':
fifths -= 3
if fifths < -7 or fifths > 7:
return None
return fifths
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(['C', 'major'], 0), (['G', 'major'], 1), (['F', 'major'], -1), (['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['C', 'dorian'], None), (['C', 'Major'], None)], [(['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['G#', 'minor'], 5), (['D#', 'minor'], 6), (['A#', 'minor'], 7), (['C', 'dorian'], None), (['C', 'Major'], None)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("oracle %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | 0 | 0 | Passed |
| oracle 1 | 1 | 1 | Passed |
| oracle 2 | -1 | -1 | Passed |
| oracle 3 | 6 | 6 | Passed |
| oracle 4 | -6 | -6 | Passed |
| oracle 5 | 7 | 7 | Passed |
| oracle 6 | None | None | Passed |
| oracle 7 | None | None | Passed |
SHA-256 / 45825ee6afbafba40ae8311109ca9dfcbd0e08816ebb65ca3d9b27333bd1ff48
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; it is not a complete music notation or theory engine. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:49:58.695026+00:00.
Case digest / 02956d842d15ab6164ba0e169bed500ab3ab5c2564a0d7299d22634e0b03ccd5