FA-88791 / Mesh topology invariants / Open access
Edge split reports success when the edge is absent · case 01
Requests for a non-existent edge return the unchanged mesh with a new vertex id.
ROOT CAUSE
The no-edge check is missing.
VERIFIED REPAIR
Return "no-edge" when no triangle was split.
Unsuccessful approach: Requiring two split faces refuses valid boundary edge splits.
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=[]
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))
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]]], [['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['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'], ['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]]], [['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'], ['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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 edge | [4, [[0, 1, 2], [2, 1, 3]], 0] | no-edge | Failed |
| 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 input | non-triangle | non-triangle | Passed |
| 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 / a3b02313b4ce180c1e2f83d2cb6bf20ed9533e813d4b36e2c77b6f9434cbab64
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=[]
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<2: 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]]], [['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['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'], ['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]]], [['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'], ['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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 | no-edge | [4, [[0, 4, 2], [4, 1, 2], [2, 1, 3]], 1] | Failed |
| missing edge | no-edge | no-edge | Passed |
| 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 input | non-triangle | non-triangle | Passed |
| 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 / 78bc07c43bb30ad8ab9b152d612e98f2d9c25536a0d74ede97626baf6744c003
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]]], [['missing edge', [[[[0, 1, 2], [2, 1, 3]], 0, 3]], 'no-edge'], ['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'], ['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]]], [['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'], ['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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 edge | no-edge | no-edge | Passed |
| 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 input | non-triangle | non-triangle | Passed |
| 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 / 570cc0928bcf7a3fb3f99a25984d39ad0fd071411ee5849c8c2466e3432bff7a
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.422484+00:00.
Case digest / cd654ef2161ef237dc7d1e6d7889d065b454d8c7b072ba81298e4909402ebf4e