FA-81176 / Music interval and transposition theory / Open access
Chord symbol to pitch classes: chord tones above B not wrapped · case 01
An A major triad returns [9,13,16] instead of [9,1,4].
ROOT CAUSE
Chord tones are formed by adding intervals to the root without reducing modulo twelve.
VERIFIED REPAIR
Restore the pitch class reduction step so that it reads `(r + i) % 12`.
Unsuccessful approach: Subtracting twelve only above twelve leaves a tone of exactly 12 unreduced.
Case contract
Input a chord symbol: root letter with optional # or b, a quality from "", m, dim, aug, 7, maj7, m7, m7b5, dim7, sus4, mMaj7, 6, and optionally "/" plus a bass note (letter with optional # or b and nothing else). Return pitch classes root-first in template order; for a slash chord the bass moves to the front (removed from its old position if it is a chord tone, otherwise added). Unknown or malformed symbols return None.
Why this case matters
Lead-sheet, accompaniment and guitar-chart tools expand chord symbols into voicings.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
shapes = {'': [0, 4, 7], 'm': [0, 3, 7], 'dim': [0, 3, 6], 'aug': [0, 4, 8], '7': [0, 4, 7, 10], 'maj7': [0, 4, 7, 11], 'm7': [0, 3, 7, 10], 'm7b5': [0, 3, 6, 10], 'dim7': [0, 3, 6, 9], 'sus4': [0, 5, 7], 'mMaj7': [0, 3, 7, 11], '6': [0, 4, 7, 9]}
def root(s):
if not s or s[0] not in base:
return None, s
if s[1:2] in ('#', 'b'):
return (base[s[0]] + (1 if s[1] == '#' else -1)) % 12, s[2:]
return base[s[0]], s[1:]
if not isinstance(x, str):
return None
head, slash, tail = x.partition('/')
r, quality = root(head)
if r is None or quality not in shapes:
return None
tones = [r + i for i in shapes[quality]]
if slash:
b, rest = root(tail)
if b is None or rest:
return None
if b in tones:
tones.remove(b)
tones.insert(0, b)
return tones
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('C', [0, 4, 7]), ('Cm', [0, 3, 7]), ('Bb', [10, 2, 5]), ('Bb7', [10, 2, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('Dsus4', [2, 7, 9]), ('C/E', [4, 0, 7]), ('E#', [5, 9, 0])], [('Bbm7', [10, 1, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('C/E', [4, 0, 7]), ('C/G', [7, 0, 4]), ('C/Bb', [10, 0, 4, 7]), ('Am/G', [7, 9, 0, 4]), ('Cmaj7/B', [11, 0, 4, 7]), ('AmMaj7', [9, 0, 4, 8])], [('Bb7', [10, 2, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('Ebmaj7', [3, 7, 10, 2]), ('F/A', [9, 5, 0]), ('Cmaj7/B', [11, 0, 4, 7]), ('C/E/G', None), ('C/Ebm', None), ('C/H', None)], [('F#m7b5', [6, 9, 0, 4]), ('Gdim7', [7, 10, 1, 4]), ('Am/G', [7, 9, 0, 4]), ('E#', [5, 9, 0]), ('C/H', None), ('H7', None), ('Cmin', None), ('D/F#', [6, 2, 9])], [('Ebmaj7', [3, 7, 10, 2]), ('Aaug', [9, 1, 5]), ('F/A', [9, 5, 0]), ('AmMaj7', [9, 0, 4, 8]), ('D/F#', [6, 2, 9]), ('Ebm/Gb', [6, 3, 10]), ('C/', None), ('Am/', 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, 4, 7] | [0, 4, 7] | Passed |
| oracle 1 | [0, 3, 7] | [0, 3, 7] | Passed |
| oracle 2 | [10, 14, 17] | [10, 2, 5] | Failed |
| oracle 3 | [10, 14, 17, 20] | [10, 2, 5, 8] | Failed |
| oracle 4 | [6, 9, 12, 16] | [6, 9, 0, 4] | Failed |
| oracle 5 | [2, 7, 9] | [2, 7, 9] | Passed |
| oracle 6 | [4, 0, 7] | [4, 0, 7] | Passed |
| oracle 7 | [5, 9, 12] | [5, 9, 0] | Failed |
SHA-256 / 6626886892dd2f9b90d17292615038db6ce9fa58a4b7848d2c8e4f219d824d33
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
shapes = {'': [0, 4, 7], 'm': [0, 3, 7], 'dim': [0, 3, 6], 'aug': [0, 4, 8], '7': [0, 4, 7, 10], 'maj7': [0, 4, 7, 11], 'm7': [0, 3, 7, 10], 'm7b5': [0, 3, 6, 10], 'dim7': [0, 3, 6, 9], 'sus4': [0, 5, 7], 'mMaj7': [0, 3, 7, 11], '6': [0, 4, 7, 9]}
def root(s):
if not s or s[0] not in base:
return None, s
if s[1:2] in ('#', 'b'):
return (base[s[0]] + (1 if s[1] == '#' else -1)) % 12, s[2:]
return base[s[0]], s[1:]
if not isinstance(x, str):
return None
head, slash, tail = x.partition('/')
r, quality = root(head)
if r is None or quality not in shapes:
return None
tones = [(r + i) - 12 if r + i > 12 else r + i for i in shapes[quality]]
if slash:
b, rest = root(tail)
if b is None or rest:
return None
if b in tones:
tones.remove(b)
tones.insert(0, b)
return tones
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('C', [0, 4, 7]), ('Cm', [0, 3, 7]), ('Bb', [10, 2, 5]), ('Bb7', [10, 2, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('Dsus4', [2, 7, 9]), ('C/E', [4, 0, 7]), ('E#', [5, 9, 0])], [('Bbm7', [10, 1, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('C/E', [4, 0, 7]), ('C/G', [7, 0, 4]), ('C/Bb', [10, 0, 4, 7]), ('Am/G', [7, 9, 0, 4]), ('Cmaj7/B', [11, 0, 4, 7]), ('AmMaj7', [9, 0, 4, 8])], [('Bb7', [10, 2, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('Ebmaj7', [3, 7, 10, 2]), ('F/A', [9, 5, 0]), ('Cmaj7/B', [11, 0, 4, 7]), ('C/E/G', None), ('C/Ebm', None), ('C/H', None)], [('F#m7b5', [6, 9, 0, 4]), ('Gdim7', [7, 10, 1, 4]), ('Am/G', [7, 9, 0, 4]), ('E#', [5, 9, 0]), ('C/H', None), ('H7', None), ('Cmin', None), ('D/F#', [6, 2, 9])], [('Ebmaj7', [3, 7, 10, 2]), ('Aaug', [9, 1, 5]), ('F/A', [9, 5, 0]), ('AmMaj7', [9, 0, 4, 8]), ('D/F#', [6, 2, 9]), ('Ebm/Gb', [6, 3, 10]), ('C/', None), ('Am/', 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, 4, 7] | [0, 4, 7] | Passed |
| oracle 1 | [0, 3, 7] | [0, 3, 7] | Passed |
| oracle 2 | [10, 2, 5] | [10, 2, 5] | Passed |
| oracle 3 | [10, 2, 5, 8] | [10, 2, 5, 8] | Passed |
| oracle 4 | [6, 9, 12, 4] | [6, 9, 0, 4] | Failed |
| oracle 5 | [2, 7, 9] | [2, 7, 9] | Passed |
| oracle 6 | [4, 0, 7] | [4, 0, 7] | Passed |
| oracle 7 | [5, 9, 12] | [5, 9, 0] | Failed |
SHA-256 / 8ef53d5298f31b8a21b6de321fc1fae5687adf8feb48bf4b2aad4c664c785ed4
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
shapes = {'': [0, 4, 7], 'm': [0, 3, 7], 'dim': [0, 3, 6], 'aug': [0, 4, 8], '7': [0, 4, 7, 10], 'maj7': [0, 4, 7, 11], 'm7': [0, 3, 7, 10], 'm7b5': [0, 3, 6, 10], 'dim7': [0, 3, 6, 9], 'sus4': [0, 5, 7], 'mMaj7': [0, 3, 7, 11], '6': [0, 4, 7, 9]}
def root(s):
if not s or s[0] not in base:
return None, s
if s[1:2] in ('#', 'b'):
return (base[s[0]] + (1 if s[1] == '#' else -1)) % 12, s[2:]
return base[s[0]], s[1:]
if not isinstance(x, str):
return None
head, slash, tail = x.partition('/')
r, quality = root(head)
if r is None or quality not in shapes:
return None
tones = [(r + i) % 12 for i in shapes[quality]]
if slash:
b, rest = root(tail)
if b is None or rest:
return None
if b in tones:
tones.remove(b)
tones.insert(0, b)
return tones
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('C', [0, 4, 7]), ('Cm', [0, 3, 7]), ('Bb', [10, 2, 5]), ('Bb7', [10, 2, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('Dsus4', [2, 7, 9]), ('C/E', [4, 0, 7]), ('E#', [5, 9, 0])], [('Bbm7', [10, 1, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('C/E', [4, 0, 7]), ('C/G', [7, 0, 4]), ('C/Bb', [10, 0, 4, 7]), ('Am/G', [7, 9, 0, 4]), ('Cmaj7/B', [11, 0, 4, 7]), ('AmMaj7', [9, 0, 4, 8])], [('Bb7', [10, 2, 5, 8]), ('F#m7b5', [6, 9, 0, 4]), ('Ebmaj7', [3, 7, 10, 2]), ('F/A', [9, 5, 0]), ('Cmaj7/B', [11, 0, 4, 7]), ('C/E/G', None), ('C/Ebm', None), ('C/H', None)], [('F#m7b5', [6, 9, 0, 4]), ('Gdim7', [7, 10, 1, 4]), ('Am/G', [7, 9, 0, 4]), ('E#', [5, 9, 0]), ('C/H', None), ('H7', None), ('Cmin', None), ('D/F#', [6, 2, 9])], [('Ebmaj7', [3, 7, 10, 2]), ('Aaug', [9, 1, 5]), ('F/A', [9, 5, 0]), ('AmMaj7', [9, 0, 4, 8]), ('D/F#', [6, 2, 9]), ('Ebm/Gb', [6, 3, 10]), ('C/', None), ('Am/', 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, 4, 7] | [0, 4, 7] | Passed |
| oracle 1 | [0, 3, 7] | [0, 3, 7] | Passed |
| oracle 2 | [10, 2, 5] | [10, 2, 5] | Passed |
| oracle 3 | [10, 2, 5, 8] | [10, 2, 5, 8] | Passed |
| oracle 4 | [6, 9, 0, 4] | [6, 9, 0, 4] | Passed |
| oracle 5 | [2, 7, 9] | [2, 7, 9] | Passed |
| oracle 6 | [4, 0, 7] | [4, 0, 7] | Passed |
| oracle 7 | [5, 9, 0] | [5, 9, 0] | Passed |
SHA-256 / 5e164b446710421eebb4aa98357cb724236cf022bbcff4c5a964a8f4c3ed2666
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:50:00.596672+00:00.
Case digest / db00cb3d8bcae4cfbb2f790996123c2a5f2804b9d7048a3c88a649f51e9cda80