{"abstract":"The outer boundary is no longer listed first when a hole has a smaller vertex id.","category":"Mesh topology invariants","checks":7,"contract":"Input: consistently oriented polygon faces. A half-edge (a,b) is boundary when (b,a) is not a half-edge. If any vertex starts two boundary half-edges return \"ambiguous\". Otherwise walk loops along the half-edge direction, each starting at its smallest vertex, and return them sorted by descending length then first vertex.","contract_signature":"x","evaluation_group":"w2-mesh_topology_invariants-boundary-loops","failed_approach":"Sorting by ascending length lists the smallest hole first.","family":"w2-mesh_topology_invariants-boundary-loops-loop-ordering","id":"FA-88406","implementations":{"attempt":{"sha256":"1cfb103baba997f88e8ff9991ebcb4c551251bf5b71d7ebf21985ec4fd95739a","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    faces=x\n    he=[]\n    for f in faces:\n        n=len(f)\n        for i in range(n):\n            he.append((f[i],f[(i+1)%n]))\n    hs=set(he)\n    nxt={}\n    for a,b in he:\n        if (b,a) not in hs:\n            if a in nxt: return 'ambiguous'\n            nxt[a]=b\n    loops=[]\n    seen=set()\n    for s in sorted(nxt):\n        if s in seen: continue\n        loop=[]\n        v=s\n        while v not in seen:\n            seen.add(v)\n            loop.append(v)\n            v=nxt[v]\n        loops.append(loop)\n    return sorted(loops,key=lambda l:(len(l),l[0]))\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [[1, 2, 3, 4, 5]]], ['fan', [[[0, 1, 2], [0, 2, 3], [0, 3, 4]]], [[0, 1, 2, 3, 4]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [[0, 2, 1], [3, 4, 5]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [[0, 1, 2, 5, 8, 7, 6, 3]]], ['square with hole', [[[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['closed tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], []], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [[0, 1, 2, 5, 8, 7, 6, 3]]], ['square with hole', [[[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['closed tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], []], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], 'ambiguous'], ['two disks', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 12, 13], [10, 13, 14]]], [[1, 2, 3, 4, 5], [10, 11, 12, 13, 14]]], ['open cylinder', [[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['bowtie', [[[0, 1, 2], [0, 3, 4]]], 'ambiguous'], ['two disks', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 12, 13], [10, 13, 14]]], [[1, 2, 3, 4, 5], [10, 11, 12, 13, 14]]], ['open cylinder', [[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['single triangle', [[[4, 2, 7]]], [[2, 7, 4]]], ['single quad', [[[3, 1, 0, 2]]], [[0, 2, 3, 1]]], ['triangle grid', [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]]], [[0, 1, 2, 5, 4, 3]]], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [[1, 2, 3, 4, 5]]], ['fan', [[[0, 1, 2], [0, 2, 3], [0, 3, 4]]], [[0, 1, 2, 3, 4]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [[0, 2, 1], [3, 4, 5]]], ['single triangle', [[[4, 2, 7]]], [[2, 7, 4]]], ['single quad', [[[3, 1, 0, 2]]], [[0, 2, 3, 1]]], ['triangle grid', [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]]], [[0, 1, 2, 5, 4, 3]]], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [[1, 2, 3, 4, 5]]], ['fan', [[[0, 1, 2], [0, 2, 3], [0, 3, 4]]], [[0, 1, 2, 3, 4]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [[0, 2, 1], [3, 4, 5]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [[0, 1, 2, 5, 8, 7, 6, 3]]], ['square with hole', [[[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['closed tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], []], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"e4f8fe5e9033825252b8917efb0de28343e6ed8e062457ef520109edf483cb62","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    faces=x\n    he=[]\n    for f in faces:\n        n=len(f)\n        for i in range(n):\n            he.append((f[i],f[(i+1)%n]))\n    hs=set(he)\n    nxt={}\n    for a,b in he:\n        if (b,a) not in hs:\n            if a in nxt: return 'ambiguous'\n            nxt[a]=b\n    loops=[]\n    seen=set()\n    for s in sorted(nxt):\n        if s in seen: continue\n        loop=[]\n        v=s\n        while v not in seen:\n            seen.add(v)\n            loop.append(v)\n            v=nxt[v]\n        loops.append(loop)\n    return sorted(loops,key=lambda l:l[0])\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [[1, 2, 3, 4, 5]]], ['fan', [[[0, 1, 2], [0, 2, 3], [0, 3, 4]]], [[0, 1, 2, 3, 4]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [[0, 2, 1], [3, 4, 5]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [[0, 1, 2, 5, 8, 7, 6, 3]]], ['square with hole', [[[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['closed tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], []], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [[0, 1, 2, 5, 8, 7, 6, 3]]], ['square with hole', [[[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['closed tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], []], ['bowtie', [[[0, 1, 2], [0, 3, 4]]], 'ambiguous'], ['two disks', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 12, 13], [10, 13, 14]]], [[1, 2, 3, 4, 5], [10, 11, 12, 13, 14]]], ['open cylinder', [[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['bowtie', [[[0, 1, 2], [0, 3, 4]]], 'ambiguous'], ['two disks', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [10, 11, 12], [10, 12, 13], [10, 13, 14]]], [[1, 2, 3, 4, 5], [10, 11, 12, 13, 14]]], ['open cylinder', [[[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['single triangle', [[[4, 2, 7]]], [[2, 7, 4]]], ['single quad', [[[3, 1, 0, 2]]], [[0, 2, 3, 1]]], ['triangle grid', [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]]], [[0, 1, 2, 5, 4, 3]]], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [[1, 2, 3, 4, 5]]], ['fan', [[[0, 1, 2], [0, 2, 3], [0, 3, 4]]], [[0, 1, 2, 3, 4]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [[0, 2, 1], [3, 4, 5]]], ['single triangle', [[[4, 2, 7]]], [[2, 7, 4]]], ['single quad', [[[3, 1, 0, 2]]], [[0, 2, 3, 1]]], ['triangle grid', [[[0, 1, 4], [0, 4, 3], [1, 2, 5], [1, 5, 4]]], [[0, 1, 2, 5, 4, 3]]], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]], [['disk', [[[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1]]], [[1, 2, 3, 4, 5]]], ['fan', [[[0, 1, 2], [0, 2, 3], [0, 3, 4]]], [[0, 1, 2, 3, 4]]], ['annulus', [[[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0]]], [[0, 2, 1], [3, 4, 5]]], ['quad grid', [[[0, 1, 4, 3], [1, 2, 5, 4], [3, 4, 7, 6], [4, 5, 8, 7]]], [[0, 1, 2, 5, 8, 7, 6, 3]]], ['square with hole', [[[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]]], [[0, 1, 2, 3], [4, 7, 6, 5]]], ['closed tetrahedron', [[[0, 2, 1], [0, 1, 3], [1, 2, 3], [0, 3, 2]]], []], ['disk with small far island', [[[5, 6, 7], [5, 7, 8], [5, 8, 9], [5, 9, 10], [5, 10, 6], [0, 1, 2]]], [[6, 7, 8, 9, 10], [0, 1, 2]]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-mesh_topology_invariants-boundary-loops-loop-ordering","generated_at":"2026-09-29T14:51:07.775039+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"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.","root_cause":"The sort key ignores loop length.","sha256":"898e11426831b136a0bb47d4ef5b198d6c5fd70e4ba7f14ad30c89a9fe016d02","title":"Boundary loops are ordered by first vertex only · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":41.084,"exit_code":1,"observations":[{"actual":[[1,2,3,4,5]],"check":"disk","expected":[[1,2,3,4,5]],"passed":true},{"actual":[[0,1,2,3,4]],"check":"fan","expected":[[0,1,2,3,4]],"passed":true},{"actual":[[0,2,1],[3,4,5]],"check":"annulus","expected":[[0,2,1],[3,4,5]],"passed":true},{"actual":[[0,1,2,5,8,7,6,3]],"check":"quad grid","expected":[[0,1,2,5,8,7,6,3]],"passed":true},{"actual":[[0,1,2,3],[4,7,6,5]],"check":"square with hole","expected":[[0,1,2,3],[4,7,6,5]],"passed":true},{"actual":[],"check":"closed tetrahedron","expected":[],"passed":true},{"actual":[[0,1,2],[6,7,8,9,10]],"check":"disk with small far island","expected":[[6,7,8,9,10],[0,1,2]],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"disk\", \"actual\": [[1, 2, 3, 4, 5]], \"expected\": [[1, 2, 3, 4, 5]], \"passed\": true}, {\"check\": \"fan\", \"actual\": [[0, 1, 2, 3, 4]], \"expected\": [[0, 1, 2, 3, 4]], \"passed\": true}, {\"check\": \"annulus\", \"actual\": [[0, 2, 1], [3, 4, 5]], \"expected\": [[0, 2, 1], [3, 4, 5]], \"passed\": true}, {\"check\": \"quad grid\", \"actual\": [[0, 1, 2, 5, 8, 7, 6, 3]], \"expected\": [[0, 1, 2, 5, 8, 7, 6, 3]], \"passed\": true}, {\"check\": \"square with hole\", \"actual\": [[0, 1, 2, 3], [4, 7, 6, 5]], \"expected\": [[0, 1, 2, 3], [4, 7, 6, 5]], \"passed\": true}, {\"check\": \"closed tetrahedron\", \"actual\": [], \"expected\": [], \"passed\": true}, {\"check\": \"disk with small far island\", \"actual\": [[0, 1, 2], [6, 7, 8, 9, 10]], \"expected\": [[6, 7, 8, 9, 10], [0, 1, 2]], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.675,"exit_code":1,"observations":[{"actual":[[1,2,3,4,5]],"check":"disk","expected":[[1,2,3,4,5]],"passed":true},{"actual":[[0,1,2,3,4]],"check":"fan","expected":[[0,1,2,3,4]],"passed":true},{"actual":[[0,2,1],[3,4,5]],"check":"annulus","expected":[[0,2,1],[3,4,5]],"passed":true},{"actual":[[0,1,2,5,8,7,6,3]],"check":"quad grid","expected":[[0,1,2,5,8,7,6,3]],"passed":true},{"actual":[[0,1,2,3],[4,7,6,5]],"check":"square with hole","expected":[[0,1,2,3],[4,7,6,5]],"passed":true},{"actual":[],"check":"closed tetrahedron","expected":[],"passed":true},{"actual":[[0,1,2],[6,7,8,9,10]],"check":"disk with small far island","expected":[[6,7,8,9,10],[0,1,2]],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"disk\", \"actual\": [[1, 2, 3, 4, 5]], \"expected\": [[1, 2, 3, 4, 5]], \"passed\": true}, {\"check\": \"fan\", \"actual\": [[0, 1, 2, 3, 4]], \"expected\": [[0, 1, 2, 3, 4]], \"passed\": true}, {\"check\": \"annulus\", \"actual\": [[0, 2, 1], [3, 4, 5]], \"expected\": [[0, 2, 1], [3, 4, 5]], \"passed\": true}, {\"check\": \"quad grid\", \"actual\": [[0, 1, 2, 5, 8, 7, 6, 3]], \"expected\": [[0, 1, 2, 5, 8, 7, 6, 3]], \"passed\": true}, {\"check\": \"square with hole\", \"actual\": [[0, 1, 2, 3], [4, 7, 6, 5]], \"expected\": [[0, 1, 2, 3], [4, 7, 6, 5]], \"passed\": true}, {\"check\": \"closed tetrahedron\", \"actual\": [], \"expected\": [], \"passed\": true}, {\"check\": \"disk with small far island\", \"actual\": [[0, 1, 2], [6, 7, 8, 9, 10]], \"expected\": [[6, 7, 8, 9, 10], [0, 1, 2]], \"passed\": false}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}