FAILURE MAP
← Case archive

FA-80971 / Music interval and transposition theory / Open access

Key signature size for a named tonic: flat side range not enforced · case 01

Fb major and Db minor are reported as eight flats instead of being rejected.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The range guard checks only the sharp limit.

VERIFIED REPAIR

Restore the signature range step so that it reads `fifths < -7 or fifths > 7`.

Unsuccessful approach: Checking only the flat limit lets B# major and G# major (eight or more sharps) through.

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 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:
        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), (['Fb', 'major'], None), (['B#', 'major'], None), (['Db', 'minor'], None)], [(['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['Cb', 'major'], -7), (['Db', 'major'], -5), (['Fb', 'major'], None), (['E#', 'major'], None), (['Gb', 'minor'], None)], [(['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['A', 'minor'], 0), (['E', 'minor'], 1), (['Gb', 'minor'], None), (['Db', 'minor'], None), (['G#', 'major'], None)], [(['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Fb', 'major'], None), (['B#', 'major'], None), (['Db', 'minor'], None)], [(['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['G#', 'minor'], 5), (['D#', 'minor'], 6), (['Fb', 'major'], None), (['E#', 'major'], None), (['Gb', 'minor'], 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 fixtureActualExpectedOutcome
oracle 000Passed
oracle 111Passed
oracle 2-1-1Passed
oracle 366Passed
oracle 4-6-6Passed
oracle 5-8NoneFailed
oracle 6NoneNonePassed
oracle 7-8NoneFailed

SHA-256 / 63e8eb2f0fad91fe40de8fc93d11b7f66ce4bd776cdcb0810082f08ab381f1f9

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 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:
        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), (['Fb', 'major'], None), (['B#', 'major'], None), (['Db', 'minor'], None)], [(['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['Cb', 'major'], -7), (['Db', 'major'], -5), (['Fb', 'major'], None), (['E#', 'major'], None), (['Gb', 'minor'], None)], [(['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['A', 'minor'], 0), (['E', 'minor'], 1), (['Gb', 'minor'], None), (['Db', 'minor'], None), (['G#', 'major'], None)], [(['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Fb', 'major'], None), (['B#', 'major'], None), (['Db', 'minor'], None)], [(['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['G#', 'minor'], 5), (['D#', 'minor'], 6), (['Fb', 'major'], None), (['E#', 'major'], None), (['Gb', 'minor'], 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 fixtureActualExpectedOutcome
oracle 000Passed
oracle 111Passed
oracle 2-1-1Passed
oracle 366Passed
oracle 4-6-6Passed
oracle 5NoneNonePassed
oracle 612NoneFailed
oracle 7NoneNonePassed

SHA-256 / 4ba2c8eaf85ef152e53f275428d863df7ecd6e2b2d67425469ac927ab2b51cf1

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), (['Fb', 'major'], None), (['B#', 'major'], None), (['Db', 'minor'], None)], [(['F#', 'major'], 6), (['Gb', 'major'], -6), (['C#', 'major'], 7), (['Cb', 'major'], -7), (['Db', 'major'], -5), (['Fb', 'major'], None), (['E#', 'major'], None), (['Gb', 'minor'], None)], [(['Cb', 'major'], -7), (['Db', 'major'], -5), (['B', 'major'], 5), (['A', 'minor'], 0), (['E', 'minor'], 1), (['Gb', 'minor'], None), (['Db', 'minor'], None), (['G#', 'major'], None)], [(['A', 'minor'], 0), (['E', 'minor'], 1), (['D', 'minor'], -1), (['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Fb', 'major'], None), (['B#', 'major'], None), (['Db', 'minor'], None)], [(['C#', 'minor'], 4), (['Eb', 'minor'], -6), (['Ab', 'minor'], -7), (['G#', 'minor'], 5), (['D#', 'minor'], 6), (['Fb', 'major'], None), (['E#', 'major'], None), (['Gb', 'minor'], 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 fixtureActualExpectedOutcome
oracle 000Passed
oracle 111Passed
oracle 2-1-1Passed
oracle 366Passed
oracle 4-6-6Passed
oracle 5NoneNonePassed
oracle 6NoneNonePassed
oracle 7NoneNonePassed

SHA-256 / 701856407cc9bc08d71ccdd869b72b764b504dccdbaa225319cace093b70c4d0

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.669153+00:00.

Case digest / 163587b08464872a243aa245f7c8ef984d3a28734262abb3efa905c5aeaec19e