FA-81336 / Music interval and transposition theory / Open access
Triad and seventh inversion figures: fully diminished seventh unrecognised · case 01
Diminished seventh chords such as B D F Ab return None instead of a root and figure.
ROOT CAUSE
The template list stops after the half-diminished seventh and omits the fully diminished shape.
VERIFIED REPAIR
Restore the diminished seventh template step so that it reads `[0, 3, 6, 10], [0, 3, 6, 9]`.
Unsuccessful approach: Adding a 0-3-6-8 shape instead lets some dominant sevenths (such as G#7) match first with their third taken as the root.
Case contract
Input 3 or 4 MIDI integers in any order. The pitch-class set must match a template relative to some root (triads 047 037 036 048; sevenths 047t 037t 047e 036t 0369, t=10 e=11); roots are tried in ascending pitch-class order. The bass is the lowest MIDI note. Return [root_pc, figure] with figures "", "6", "64" for triads and "7", "65", "43", "42" for sevenths by the bass position in the template; otherwise None.
Why this case matters
Figured-bass realisation and harmonic analysis depend on identifying chord root and inversion.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or not 3 <= len(x) <= 4 or not all(isinstance(v, int) for v in x):
return None
bass = min(x)
pcs = sorted(set(v % 12 for v in x))
for r in pcs:
rel = sorted((p - r) % 12 for p in pcs)
if rel in ([0, 4, 7], [0, 3, 7], [0, 3, 6], [0, 4, 8], [0, 4, 7, 10], [0, 3, 7, 10], [0, 4, 7, 11], [0, 3, 6, 10]):
pos = rel.index((bass - r) % 12)
figs = ['', '6', '64'] if len(rel) == 3 else ['7', '65', '43', '42']
return [r, figs[pos]]
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([60, 64, 67], [0, '']), ([64, 67, 72], [0, '6']), ([67, 72, 76], [0, '64']), ([72, 64, 67], [0, '6']), ([76, 60, 67], [0, '']), ([55, 59, 62, 65], [7, '7']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7'])], [([72, 64, 67], [0, '6']), ([76, 60, 67], [0, '']), ([55, 59, 62, 65], [7, '7']), ([59, 62, 65, 67], [7, '65']), ([62, 65, 67, 71], [7, '43']), ([65, 67, 71, 74], [7, '42']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7'])], [([59, 62, 65, 67], [7, '65']), ([62, 65, 67, 71], [7, '43']), ([65, 67, 71, 74], [7, '42']), ([60, 64, 67, 72], [0, '']), ([48, 64, 67, 72], [0, '']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([59, 62, 65, 69], [11, '7'])], [([60, 64, 67, 72], [0, '']), ([48, 64, 67, 72], [0, '']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([59, 62, 65, 69], [11, '7']), ([57, 60, 64], [9, '']), ([60, 62, 67], None), ([60, 64, 68], [0, ''])], [([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([57, 60, 64], [9, '']), ([60, 62, 67], None), ([60, 64, 68], [0, '']), ([64, 60, 67], [0, '']), ([71, 62, 65], [11, '6']), ([60, 61, 62], 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 | [0, '6'] | [0, '6'] | Passed |
| oracle 2 | [0, '64'] | [0, '64'] | Passed |
| oracle 3 | [0, '6'] | [0, '6'] | Passed |
| oracle 4 | [0, ''] | [0, ''] | Passed |
| oracle 5 | [7, '7'] | [7, '7'] | Passed |
| oracle 6 | None | [0, '7'] | Failed |
| oracle 7 | None | [2, '7'] | Failed |
SHA-256 / fccb0eeede9b9f59b73f0845745fb3aeaef189c4f903fb84e48d7bc9c9f8d03e
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or not 3 <= len(x) <= 4 or not all(isinstance(v, int) for v in x):
return None
bass = min(x)
pcs = sorted(set(v % 12 for v in x))
for r in pcs:
rel = sorted((p - r) % 12 for p in pcs)
if rel in ([0, 4, 7], [0, 3, 7], [0, 3, 6], [0, 4, 8], [0, 4, 7, 10], [0, 3, 7, 10], [0, 4, 7, 11], [0, 3, 6, 10], [0, 3, 6, 8]):
pos = rel.index((bass - r) % 12)
figs = ['', '6', '64'] if len(rel) == 3 else ['7', '65', '43', '42']
return [r, figs[pos]]
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([60, 64, 67], [0, '']), ([64, 67, 72], [0, '6']), ([67, 72, 76], [0, '64']), ([72, 64, 67], [0, '6']), ([76, 60, 67], [0, '']), ([55, 59, 62, 65], [7, '7']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7'])], [([72, 64, 67], [0, '6']), ([76, 60, 67], [0, '']), ([55, 59, 62, 65], [7, '7']), ([59, 62, 65, 67], [7, '65']), ([62, 65, 67, 71], [7, '43']), ([65, 67, 71, 74], [7, '42']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7'])], [([59, 62, 65, 67], [7, '65']), ([62, 65, 67, 71], [7, '43']), ([65, 67, 71, 74], [7, '42']), ([60, 64, 67, 72], [0, '']), ([48, 64, 67, 72], [0, '']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([59, 62, 65, 69], [11, '7'])], [([60, 64, 67, 72], [0, '']), ([48, 64, 67, 72], [0, '']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([59, 62, 65, 69], [11, '7']), ([57, 60, 64], [9, '']), ([60, 62, 67], None), ([60, 64, 68], [0, ''])], [([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([57, 60, 64], [9, '']), ([60, 62, 67], None), ([60, 64, 68], [0, '']), ([64, 60, 67], [0, '']), ([71, 62, 65], [11, '6']), ([60, 61, 62], 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 | [0, '6'] | [0, '6'] | Passed |
| oracle 2 | [0, '64'] | [0, '64'] | Passed |
| oracle 3 | [0, '6'] | [0, '6'] | Passed |
| oracle 4 | [0, ''] | [0, ''] | Passed |
| oracle 5 | [7, '7'] | [7, '7'] | Passed |
| oracle 6 | None | [0, '7'] | Failed |
| oracle 7 | None | [2, '7'] | Failed |
SHA-256 / 08a87d13efe3c7529331d69bfe9869b90871901abf71a74da1a441cc533b3cb4
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or not 3 <= len(x) <= 4 or not all(isinstance(v, int) for v in x):
return None
bass = min(x)
pcs = sorted(set(v % 12 for v in x))
for r in pcs:
rel = sorted((p - r) % 12 for p in pcs)
if rel in ([0, 4, 7], [0, 3, 7], [0, 3, 6], [0, 4, 8], [0, 4, 7, 10], [0, 3, 7, 10], [0, 4, 7, 11], [0, 3, 6, 10], [0, 3, 6, 9]):
pos = rel.index((bass - r) % 12)
figs = ['', '6', '64'] if len(rel) == 3 else ['7', '65', '43', '42']
return [r, figs[pos]]
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([60, 64, 67], [0, '']), ([64, 67, 72], [0, '6']), ([67, 72, 76], [0, '64']), ([72, 64, 67], [0, '6']), ([76, 60, 67], [0, '']), ([55, 59, 62, 65], [7, '7']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7'])], [([72, 64, 67], [0, '6']), ([76, 60, 67], [0, '']), ([55, 59, 62, 65], [7, '7']), ([59, 62, 65, 67], [7, '65']), ([62, 65, 67, 71], [7, '43']), ([65, 67, 71, 74], [7, '42']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7'])], [([59, 62, 65, 67], [7, '65']), ([62, 65, 67, 71], [7, '43']), ([65, 67, 71, 74], [7, '42']), ([60, 64, 67, 72], [0, '']), ([48, 64, 67, 72], [0, '']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([59, 62, 65, 69], [11, '7'])], [([60, 64, 67, 72], [0, '']), ([48, 64, 67, 72], [0, '']), ([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([59, 62, 65, 69], [11, '7']), ([57, 60, 64], [9, '']), ([60, 62, 67], None), ([60, 64, 68], [0, ''])], [([60, 63, 66, 69], [0, '7']), ([62, 65, 68, 71], [2, '7']), ([57, 60, 64], [9, '']), ([60, 62, 67], None), ([60, 64, 68], [0, '']), ([64, 60, 67], [0, '']), ([71, 62, 65], [11, '6']), ([60, 61, 62], 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 | [0, '6'] | [0, '6'] | Passed |
| oracle 2 | [0, '64'] | [0, '64'] | Passed |
| oracle 3 | [0, '6'] | [0, '6'] | Passed |
| oracle 4 | [0, ''] | [0, ''] | Passed |
| oracle 5 | [7, '7'] | [7, '7'] | Passed |
| oracle 6 | [0, '7'] | [0, '7'] | Passed |
| oracle 7 | [2, '7'] | [2, '7'] | Passed |
SHA-256 / 8b7bcc9db418e30626d2b2a335bae95a755656ccec1c47463821991bc08dbbad
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:01.906956+00:00.
Case digest / ce10d7ee5abb158b4d08d5b78bb50df496a4473ac3fd6767906fb7eb42677aef