FAILURE MAP
← Case archive

FA-88761 / Mesh topology invariants / Open access

UV face lists of the wrong length are paired silently · case 01

A short UV list is wrapped around the face and invents seams.

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

ROOT CAUSE

The length check between face and UV face is missing.

VERIFIED REPAIR

Return ["uv-mismatch", i] when lengths differ.

Unsuccessful approach: Comparing only the number of faces misses per-face length mismatches.

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)):
        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]]], ['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]]]], []]], [['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]]], ['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]]], ['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]]], ['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]]], ['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]]], ['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]]]], []]], [['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]]], ['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]]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]]]
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
extra uv corner[]['uv-mismatch', 0]Failed
quad strip[][]Passed

SHA-256 / 82f7f7fa387b4758f9b395054c9a2f3649a9af0b3345938d2abf73fe41a45963

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={}
    if len(faces)!=len(uvf): return ['uv-mismatch',0]
    seams=set()
    for fi,(f,t) in enumerate(zip(faces,uvf)):
        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]]], ['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]]]], []]], [['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]]], ['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]]], ['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]]], ['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]]], ['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]]], ['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]]]], []]], [['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]]], ['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]]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]]]
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
extra uv corner[]['uv-mismatch', 0]Failed
quad strip[][]Passed

SHA-256 / 48a0ba895208d4ac432fe1c960f3f0dea968509c0c0a42fb0471972980f4e3c5

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]]], ['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]]]], []]], [['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]]], ['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]]], ['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]]], ['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]]], ['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]]], ['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]]]], []]], [['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]]], ['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]]], ['same uv sum collision', [[[[0, 3, 1], [1, 3, 2]], [[0, 3, 1], [1, 3, 2]]]], []]]]
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
extra uv corner['uv-mismatch', 0]['uv-mismatch', 0]Passed
quad strip[][]Passed

SHA-256 / 6c5c18306fddcb7b0183a97d23aee59e85ec5e503b59367f2049292f7a739f6c

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

Case digest / 051c421c92e61fb0554ce658048e775561f2a724321da9b1154f3cd7f3ecbde3