FAILURE MAP
← Case archive

FA-88766 / Mesh topology invariants / Open access

UV seams are keyed by directed geometric edges · case 01

The two faces on an edge never meet in the table, so no seam is ever reported.

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

ROOT CAUSE

The edge key keeps traversal direction, and neighbouring faces traverse shared edges oppositely.

VERIFIED REPAIR

Key edges by the undirected vertex pair (min, max).

Unsuccessful approach: Keying by the UV index pair compares texture edges instead of geometric edges.

Case contract

Input [faces, uvfaces]: each face has a parallel list of UV indices. A face whose UV list length differs returns ["uv-mismatch", face index]. A geometric edge is a seam when a later face assigns a different UV index to either endpoint than the first face did. Return sorted seam edges [min,max].

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,uvf=x
    seen={}
    seams=set()
    for fi,(f,t) in enumerate(zip(faces,uvf)):
        if len(f)!=len(t): return ['uv-mismatch',fi]
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            ua,ub=t[i],t[(i+1)%n]
            k=(a,b)
            m={a:ua,b:ub}
            if k in seen:
                if seen[k]!=m: seams.add(k)
            else: seen[k]=m
    return sorted([list(k) for k in seams])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['one endpoint split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [4, 1, 3]]]], [[1, 2]]], ['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]]], [['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]], ['quad strip', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [1, 2, 5, 4]]]], []], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]]], [['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]], ['mismatch after seams', [[[[0, 1, 2], [2, 1, 3], [3, 1, 4]], [[0, 1, 2], [5, 1, 3], [3, 1]]]], ['uv-mismatch', 2]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]], [['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['one endpoint split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [4, 1, 3]]]], [[1, 2]]], ['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]], [['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]]]]
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 uv no seam[][]Passed
one endpoint split[][[1, 2]]Failed
both endpoints split[][[1, 2]]Failed
swapped uv indices[][[1, 2]]Failed
cube with seams[][[4, 5], [4, 7], [5, 6], [6, 7]]Failed
length mismatch['uv-mismatch', 1]['uv-mismatch', 1]Passed
extra uv corner['uv-mismatch', 0]['uv-mismatch', 0]Passed

SHA-256 / 2f581103d91661512767ddc8d06fd3418073abcad913fbd98833046a6cdfa3b3

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,uvf=x
    seen={}
    seams=set()
    for fi,(f,t) in enumerate(zip(faces,uvf)):
        if len(f)!=len(t): return ['uv-mismatch',fi]
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            ua,ub=t[i],t[(i+1)%n]
            k=(min(ua,ub),max(ua,ub))
            m={a:ua,b:ub}
            if k in seen:
                if seen[k]!=m: seams.add(k)
            else: seen[k]=m
    return sorted([list(k) for k in seams])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['one endpoint split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [4, 1, 3]]]], [[1, 2]]], ['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]]], [['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]], ['quad strip', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [1, 2, 5, 4]]]], []], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]]], [['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]], ['mismatch after seams', [[[[0, 1, 2], [2, 1, 3], [3, 1, 4]], [[0, 1, 2], [5, 1, 3], [3, 1]]]], ['uv-mismatch', 2]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]], [['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['one endpoint split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [4, 1, 3]]]], [[1, 2]]], ['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]], [['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]]]]
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 uv no seam[][]Passed
one endpoint split[][[1, 2]]Failed
both endpoints split[][[1, 2]]Failed
swapped uv indices[[1, 2]][[1, 2]]Passed
cube with seams[][[4, 5], [4, 7], [5, 6], [6, 7]]Failed
length mismatch['uv-mismatch', 1]['uv-mismatch', 1]Passed
extra uv corner['uv-mismatch', 0]['uv-mismatch', 0]Passed

SHA-256 / 576e9251b3837a2d95f735de1d68e9f28e06651494dbfbb5ab99aa95b86cf259

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,uvf=x
    seen={}
    seams=set()
    for fi,(f,t) in enumerate(zip(faces,uvf)):
        if len(f)!=len(t): return ['uv-mismatch',fi]
        n=len(f)
        for i in range(n):
            a,b=f[i],f[(i+1)%n]
            ua,ub=t[i],t[(i+1)%n]
            k=(min(a,b),max(a,b))
            m={a:ua,b:ub}
            if k in seen:
                if seen[k]!=m: seams.add(k)
            else: seen[k]=m
    return sorted([list(k) for k in seams])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['one endpoint split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [4, 1, 3]]]], [[1, 2]]], ['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]]], [['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]], ['quad strip', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [1, 2, 5, 4]]]], []], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]]], [['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]], ['mismatch after seams', [[[[0, 1, 2], [2, 1, 3], [3, 1, 4]], [[0, 1, 2], [5, 1, 3], [3, 1]]]], ['uv-mismatch', 2]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]], [['shared uv no seam', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1, 3]]]], []], ['one endpoint split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [4, 1, 3]]]], [[1, 2]]], ['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]], [['both endpoints split', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [5, 4, 3]]]], [[1, 2]]], ['swapped uv indices', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [1, 2, 3]]]], [[1, 2]]], ['cube with seams', [[[[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, 3, 2, 1], [4, 5, 6, 7], [0, 1, 9, 8], [1, 2, 10, 9], [2, 3, 11, 10], [3, 0, 8, 11]]]], [[4, 5], [4, 7], [5, 6], [6, 7]]], ['length mismatch', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2], [2, 1]]]], ['uv-mismatch', 1]], ['extra uv corner', [[[[0, 1, 2], [2, 1, 3]], [[0, 1, 2, 7], [2, 1, 3]]]], ['uv-mismatch', 0]], ['quad strip split', [[[[0, 1, 4, 3], [1, 2, 5, 4]], [[0, 1, 4, 3], [6, 2, 5, 7]]]], [[1, 4]]], ['disk atlas', [[[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]], [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [6, 5, 1]]]], [[0, 1], [0, 5]]]]]
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 uv no seam[][]Passed
one endpoint split[[1, 2]][[1, 2]]Passed
both endpoints split[[1, 2]][[1, 2]]Passed
swapped uv indices[[1, 2]][[1, 2]]Passed
cube with seams[[4, 5], [4, 7], [5, 6], [6, 7]][[4, 5], [4, 7], [5, 6], [6, 7]]Passed
length mismatch['uv-mismatch', 1]['uv-mismatch', 1]Passed
extra uv corner['uv-mismatch', 0]['uv-mismatch', 0]Passed

SHA-256 / e0ad31bc6edb078c1845b0e9f503422dc1f4281fdd486b4b6d08458fff8fba14

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

Case digest / 89da4ca36595112be274ca2ecb6bfb3b18d273e553c3c39763c2e13f6d2a7a57