FAILURE MAP
← Case archive

FA-88796 / Mesh topology invariants / Open access

Split children are appended after the untouched faces · case 01

Face indices shift, breaking per-face attribute arrays.

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

ROOT CAUSE

Children are collected separately and appended at the end.

VERIFIED REPAIR

Place both children at the original face position.

Unsuccessful approach: Appending only the second child at the end still moves it.

Case contract

Input [faces, a, b] for a triangle mesh (any non-triangle returns "non-triangle"). Insert vertex m = max index + 1 on edge {a,b}: each triangle (u,w,c) with {u,w}={a,b} along its boundary becomes [u,m,c] then [m,w,c] at its original position. No such triangle returns "no-edge". Return [m, faces, number of split triangles].

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,a,b=x
    m=1+max(v for f in faces for v in f)
    out=[]
    extra=[]
    hit=0
    for f in faces:
        n=len(f)
        if n!=3: return 'non-triangle'
        done=False
        for j in range(3):
            u,w=f[j],f[(j+1)%3]
            if {u,w}=={a,b}:
                c=f[(j+2)%3]
                extra.append([u,m,c])
                extra.append([m,w,c])
                hit+=1
                done=True
                break
        if not done: out.append(list(f))
    if hit==0: return 'no-edge'
    return [m,out+extra,hit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]]], [['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]], ['reversed request', [[[[0, 1, 2], [2, 1, 3]], 2, 1]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle']], [['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle'], ['book spine', [[[[0, 1, 2], [1, 0, 3], [0, 1, 4]], 0, 1]], [5, [[0, 5, 2], [5, 1, 2], [1, 5, 3], [5, 0, 3], [0, 5, 4], [5, 1, 4]], 3]]], [['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]]], [['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]], ['reversed request', [[[[0, 1, 2], [2, 1, 3]], 2, 1]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle']]]
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
shared diagonal[4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2][4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]Passed
rim edge[4, [[2, 1, 3], [0, 4, 2], [4, 1, 2]], 1][4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]Failed
missing edgeno-edgeno-edgePassed
gapped indices[8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2][8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]Passed
tetrahedron edge[4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2][4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]Passed
quad inputnon-trianglenon-trianglePassed
disk spoke[6, [[0, 1, 2], [0, 4, 5], [0, 5, 1], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4]], 2][6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]Failed

SHA-256 / 38d087dc62c54b8e8c802e587c6ce96cdcdd7e49a86d065d056251cd51766f0b

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,a,b=x
    m=1+max(v for f in faces for v in f)
    out=[]
    extra=[]
    hit=0
    for f in faces:
        n=len(f)
        if n!=3: return 'non-triangle'
        done=False
        for j in range(3):
            u,w=f[j],f[(j+1)%3]
            if {u,w}=={a,b}:
                c=f[(j+2)%3]
                out.append([u,m,c])
                extra.append([m,w,c])
                hit+=1
                done=True
                break
        if not done: out.append(list(f))
    if hit==0: return 'no-edge'
    return [m,out+extra,hit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]]], [['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]], ['reversed request', [[[[0, 1, 2], [2, 1, 3]], 2, 1]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle']], [['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle'], ['book spine', [[[[0, 1, 2], [1, 0, 3], [0, 1, 4]], 0, 1]], [5, [[0, 5, 2], [5, 1, 2], [1, 5, 3], [5, 0, 3], [0, 5, 4], [5, 1, 4]], 3]]], [['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]]], [['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]], ['reversed request', [[[[0, 1, 2], [2, 1, 3]], 2, 1]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle']]]
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
shared diagonal[4, [[1, 4, 0], [2, 4, 3], [4, 2, 0], [4, 1, 3]], 2][4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]Failed
rim edge[4, [[0, 4, 2], [2, 1, 3], [4, 1, 2]], 1][4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]Failed
missing edgeno-edgeno-edgePassed
gapped indices[8, [[1, 8, 0], [5, 8, 7], [8, 5, 0], [8, 1, 7]], 2][8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]Failed
tetrahedron edge[4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [3, 4, 0], [4, 3, 1], [4, 2, 0]], 2][4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]Failed
quad inputnon-trianglenon-trianglePassed
disk spoke[6, [[0, 1, 2], [3, 6, 2], [0, 6, 4], [0, 4, 5], [0, 5, 1], [6, 0, 2], [6, 3, 4]], 2][6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]Failed

SHA-256 / 04d4d002d8aa9b3b43f779f9511c68e57cf08dfe390479031f3bd8cdfef0a0b0

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,a,b=x
    m=1+max(v for f in faces for v in f)
    out=[]
    hit=0
    for f in faces:
        n=len(f)
        if n!=3: return 'non-triangle'
        done=False
        for j in range(3):
            u,w=f[j],f[(j+1)%3]
            if {u,w}=={a,b}:
                c=f[(j+2)%3]
                out.append([u,m,c])
                out.append([m,w,c])
                hit+=1
                done=True
                break
        if not done: out.append(list(f))
    if hit==0: return 'no-edge'
    return [m,out,hit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]]], [['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]], ['reversed request', [[[[0, 1, 2], [2, 1, 3]], 2, 1]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle']], [['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle'], ['book spine', [[[[0, 1, 2], [1, 0, 3], [0, 1, 4]], 0, 1]], [5, [[0, 5, 2], [5, 1, 2], [1, 5, 3], [5, 0, 3], [0, 5, 4], [5, 1, 4]], 3]]], [['shared diagonal', [[[[0, 1, 2], [2, 1, 3]], 1, 2]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['gapped indices', [[[[0, 1, 5], [1, 7, 5]], 1, 5]], [8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]]], [['rim edge', [[[[0, 1, 2], [2, 1, 3]], 0, 1]], [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]], ['tetrahedron edge', [[[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]], 2, 3]], [4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]], ['quad input', [[[[0, 1, 2, 3]], 0, 1]], 'non-triangle'], ['disk spoke', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], 0, 3]], [6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]], ['reversed request', [[[[0, 1, 2], [2, 1, 3]], 2, 1]], [4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]], ['fan rim', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4]], 3, 4]], [5, [[0, 1, 2], [0, 2, 3], [3, 5, 0], [5, 4, 0]], 1]], ['triangle then quad', [[[[0, 1, 2], [2, 1, 3, 4]], 0, 1]], 'non-triangle']]]
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
shared diagonal[4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2][4, [[1, 4, 0], [4, 2, 0], [2, 4, 3], [4, 1, 3]], 2]Passed
rim edge[4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1][4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1]Passed
missing edgeno-edgeno-edgePassed
gapped indices[8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2][8, [[1, 8, 0], [8, 5, 0], [5, 8, 7], [8, 1, 7]], 2]Passed
tetrahedron edge[4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2][4, [[0, 2, 1], [0, 1, 3], [2, 4, 1], [4, 3, 1], [3, 4, 0], [4, 2, 0]], 2]Passed
quad inputnon-trianglenon-trianglePassed
disk spoke[6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2][6, [[0, 1, 2], [3, 6, 2], [6, 0, 2], [0, 6, 4], [6, 3, 4], [0, 4, 5], [0, 5, 1]], 2]Passed

SHA-256 / c8900d7872312811e130559b6f0ac08070193341144da1dc59f76258180a899d

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

Case digest / 00f821a1ca46a335726482d2d07d23993c8b988b6e37e1ce8cbde470e5f21a86