FAILURE MAP
← Case archive

FA-88371 / Mesh topology invariants / Open access

Consistent shared edges are flagged as inconsistent · case 01

Every properly oriented closed mesh is reported non-orientable.

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

ROOT CAUSE

The inconsistency test compares the first use with the reversed second use, which is the consistent case.

VERIFIED REPAIR

An interior edge is inconsistent when both uses have the same direction.

Unsuccessful approach: Comparing only one endpoint of each use matches the consistent pattern too.

Case contract

Input: polygon faces. Empty input returns "empty". Consecutive repeated indices form no edge (skip that pair only). Undirected edges used once are boundary, twice interior, more non-manifold; an interior edge whose two uses have the same direction is inconsistent. Verdict precedence: non-manifold, then "non-orientable-or-inconsistent", then "open-oriented" (boundary present), else "closed-oriented". Return [boundary, interior, nonmanifold, inconsistent, verdict].

Why this case matters

Mesh processing pipelines (remeshing, export, simulation, printing) trust these topological counts and adjacency answers; a wrong invariant silently accepts broken meshes or rejects valid ones.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    if not faces: return 'empty'
    uses={}
    for f in faces:
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            if a==b: continue
            uses.setdefault((min(a,b),max(a,b)),[]).append((a,b))
    bd=it=nm=inc=0
    for k in sorted(uses):
        u=uses[k]
        if len(u)==1: bd+=1
        elif len(u)==2:
            it+=1
            if u[0]==u[1][::-1]: inc+=1
        else: nm+=1
    if nm: v='non-manifold'
    elif inc: v='non-orientable-or-inconsistent'
    elif bd: v='open-oriented'
    else: v='closed-oriented'
    return [bd,it,nm,inc,v]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']]], [['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]]]
for label, args, expected in fixtures[N-1]:
    check(label, 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
tetrahedron[0, 6, 0, 6, 'non-orientable-or-inconsistent'][0, 6, 0, 0, 'closed-oriented']Failed
cube[0, 12, 0, 12, 'non-orientable-or-inconsistent'][0, 12, 0, 0, 'closed-oriented']Failed
disk[5, 5, 0, 5, 'non-orientable-or-inconsistent'][5, 5, 0, 0, 'open-oriented']Failed
mobius[6, 3, 0, 2, 'non-orientable-or-inconsistent'][6, 3, 0, 1, 'non-orientable-or-inconsistent']Failed
book[6, 0, 1, 0, 'non-manifold'][6, 0, 1, 0, 'non-manifold']Passed
flipped pair[4, 1, 0, 0, 'open-oriented'][4, 1, 0, 1, 'non-orientable-or-inconsistent']Failed
bowtie[6, 0, 0, 0, 'open-oriented'][6, 0, 0, 0, 'open-oriented']Passed

SHA-256 / 384e1ed4ce6208e4cca0b1c296e3c4f20f5888d2fc61ab460440ddf3b5abde7d

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    if not faces: return 'empty'
    uses={}
    for f in faces:
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            if a==b: continue
            uses.setdefault((min(a,b),max(a,b)),[]).append((a,b))
    bd=it=nm=inc=0
    for k in sorted(uses):
        u=uses[k]
        if len(u)==1: bd+=1
        elif len(u)==2:
            it+=1
            if u[0][0]==u[1][1]: inc+=1
        else: nm+=1
    if nm: v='non-manifold'
    elif inc: v='non-orientable-or-inconsistent'
    elif bd: v='open-oriented'
    else: v='closed-oriented'
    return [bd,it,nm,inc,v]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']]], [['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]]]
for label, args, expected in fixtures[N-1]:
    check(label, 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
tetrahedron[0, 6, 0, 6, 'non-orientable-or-inconsistent'][0, 6, 0, 0, 'closed-oriented']Failed
cube[0, 12, 0, 12, 'non-orientable-or-inconsistent'][0, 12, 0, 0, 'closed-oriented']Failed
disk[5, 5, 0, 5, 'non-orientable-or-inconsistent'][5, 5, 0, 0, 'open-oriented']Failed
mobius[6, 3, 0, 2, 'non-orientable-or-inconsistent'][6, 3, 0, 1, 'non-orientable-or-inconsistent']Failed
book[6, 0, 1, 0, 'non-manifold'][6, 0, 1, 0, 'non-manifold']Passed
flipped pair[4, 1, 0, 0, 'open-oriented'][4, 1, 0, 1, 'non-orientable-or-inconsistent']Failed
bowtie[6, 0, 0, 0, 'open-oriented'][6, 0, 0, 0, 'open-oriented']Passed

SHA-256 / fd10378959d945e11f3bd7ff90c90bde2e2947457df743ccfb0f2a05c0421e01

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    faces=x
    if not faces: return 'empty'
    uses={}
    for f in faces:
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            if a==b: continue
            uses.setdefault((min(a,b),max(a,b)),[]).append((a,b))
    bd=it=nm=inc=0
    for k in sorted(uses):
        u=uses[k]
        if len(u)==1: bd+=1
        elif len(u)==2:
            it+=1
            if u[0]==u[1]: inc+=1
        else: nm+=1
    if nm: v='non-manifold'
    elif inc: v='non-orientable-or-inconsistent'
    elif bd: v='open-oriented'
    else: v='closed-oriented'
    return [bd,it,nm,inc,v]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']]], [['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], [6, 0, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['empty', [[]], 'empty'], ['repeated corner', [[[0, 1, 1, 2], [2, 1, 3]]], [4, 1, 0, 0, 'open-oriented']], ['book and flipped pair', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [5, 6, 7], [5, 6, 8]]], [10, 1, 1, 1, 'non-manifold']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['four sheets', [[[0, 1, 2], [1, 0, 3], [0, 1, 4], [1, 0, 5]]], [8, 0, 1, 0, 'non-manifold']], ['torus', [[[0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [2, 3, 0], [3, 6, 7], [3, 7, 4], [4, 7, 8], [4, 8, 5], [5, 8, 6], [5, 6, 3], [6, 0, 1], [6, 1, 7], [7, 1, 2], [7, 2, 8], [8, 2, 0], [8, 0, 6]]], [0, 27, 0, 0, 'closed-oriented']], ['projective plane', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 2, 4], [2, 3, 5], [3, 4, 1], [4, 5, 2], [5, 1, 3]]], [0, 15, 0, 10, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]], [['tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']], ['cube', [[[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [0, 12, 0, 0, 'closed-oriented']], ['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [5, 5, 0, 0, 'open-oriented']], ['mobius', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 0, 3]]], [6, 3, 0, 1, 'non-orientable-or-inconsistent']], ['book', [[[0, 1, 2], [1, 0, 3], [0, 1, 4]]], [6, 0, 1, 0, 'non-manifold']], ['flipped pair', [[[0, 1, 2], [0, 1, 3]]], [4, 1, 0, 1, 'non-orientable-or-inconsistent']], ['repeated corner closed', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 3, 2]]], [0, 6, 0, 0, 'closed-oriented']]]]
for label, args, expected in fixtures[N-1]:
    check(label, 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
tetrahedron[0, 6, 0, 0, 'closed-oriented'][0, 6, 0, 0, 'closed-oriented']Passed
cube[0, 12, 0, 0, 'closed-oriented'][0, 12, 0, 0, 'closed-oriented']Passed
disk[5, 5, 0, 0, 'open-oriented'][5, 5, 0, 0, 'open-oriented']Passed
mobius[6, 3, 0, 1, 'non-orientable-or-inconsistent'][6, 3, 0, 1, 'non-orientable-or-inconsistent']Passed
book[6, 0, 1, 0, 'non-manifold'][6, 0, 1, 0, 'non-manifold']Passed
flipped pair[4, 1, 0, 1, 'non-orientable-or-inconsistent'][4, 1, 0, 1, 'non-orientable-or-inconsistent']Passed
bowtie[6, 0, 0, 0, 'open-oriented'][6, 0, 0, 0, 'open-oriented']Passed

SHA-256 / 53f7be111962bec63c4c7babcfa7c64771bd46ad7c14c283b16fa70d59414ff5

Verification & scope

Pure combinatorial teaching model over integer face lists with a stipulated contract; no geometry kernel or file format is implied. 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:51:07.522086+00:00.

Case digest / 81c336091fbacdcc9e0a8c62153beffae880af9805131c0b84fa83ca55b5ffa0