{"abstract":"Landscape selfies are saved upside down.","category":"Image orientation metadata","checks":8,"contract":"Input [gx, gy, previous_rotation, camera] with gravity in milli-g in the portrait device frame (x right, y down). Device rotation: keep the previous bucket when the in-plane magnitude is below 300 mg or |gx| == |gy| (hysteresis); otherwise gy dominates -> 0 (gy > 0) or 180, gx dominates -> 90 (gx > 0) or 270. The back sensor is mounted at 90 degrees and needs (90 + r) mod 360 clockwise; the mirrored front sensor is mounted at 270 and needs (270 - r) mod 360 with the mirror bit. The tag comes from (quarter turns, mirror) via 1:(0,0) 2:(0,1) 3:(2,0) 4:(2,1) 5:(3,1) 6:(1,0) 7:(1,1) 8:(3,0). Return [tag, r].","evaluation_group":"w2-image-orientation-metadata-capture-accelerometer","failed_approach":"Using the back-camera mount angle with the subtraction is off by a half turn.","family":"w2-image-orientation-metadata-capture-accelerometer-front-mount","id":"FA-79096","implementations":{"attempt":{"sha256":"4fcf2ffc49cf67304761bbeeea5e1e52a26020b59b0dd59b9b6a49e1f5849643","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    gx, gy, prev_r, camera = x\n    if gx * gx + gy * gy < 300 * 300 or abs(gx) == abs(gy):\n        r = prev_r\n    elif abs(gy) > abs(gx):\n        r = 0 if gy > 0 else 180\n    else:\n        r = 90 if gx > 0 else 270\n    from_km = {(0, 0): 1, (0, 1): 2, (2, 0): 3, (2, 1): 4, (3, 1): 5, (1, 0): 6, (1, 1): 7, (3, 0): 8}\n    if camera == 'front':\n        total = (90 - r) % 360\n        return [from_km[(total // 90, 1)], r]\n    total = (90 + r) % 360\n    return [from_km[(total // 90, 0)], r]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[439, -411, 180, 'front'], [4, 90]], [[298, 553, 180, 'front'], [5, 0]], [[925, 721, 90, 'front'], [4, 90]], [[-382, -382, 180, 'back'], [8, 180]], [[50, -890, 180, 'back'], [8, 180]], [[53, -848, 270, 'back'], [8, 180]], [[247, -67, 270, 'back'], [1, 270]], [[686, -373, 90, 'front'], [4, 90]]], [[[-835, 686, 0, 'front'], [2, 270]], [[648, -194, 90, 'front'], [4, 90]], [[-926, 466, 0, 'back'], [1, 270]], [[110, -610, 0, 'back'], [8, 180]], [[-900, 900, 270, 'back'], [1, 270]], [[-869, 635, 270, 'back'], [1, 270]], [[-239, -597, 180, 'back'], [8, 180]], [[-993, 66, 0, 'front'], [2, 270]]], [[[-994, 954, 180, 'front'], [2, 270]], [[-176, 109, 270, 'front'], [2, 270]], [[-552, 552, 270, 'front'], [2, 270]], [[486, 992, 270, 'back'], [6, 0]], [[54, 63, 0, 'back'], [6, 0]], [[-86, -105, 270, 'back'], [1, 270]], [[-134, -182, 180, 'back'], [8, 180]], [[717, 36, 90, 'front'], [4, 90]]], [[[-522, 369, 0, 'front'], [2, 270]], [[213, 206, 270, 'front'], [2, 270]], [[-996, 271, 270, 'front'], [2, 270]], [[137, 86, 180, 'back'], [8, 180]], [[116, 53, 90, 'back'], [3, 90]], [[-183, 181, 180, 'back'], [8, 180]], [[-651, 121, 180, 'back'], [1, 270]], [[-899, 899, 90, 'front'], [4, 90]]], [[[-1000, -619, 90, 'front'], [2, 270]], [[-869, -869, 0, 'front'], [5, 0]], [[634, -189, 90, 'front'], [4, 90]], [[816, 260, 0, 'back'], [3, 90]], [[-188, 149, 180, 'back'], [8, 180]], [[-532, 686, 180, 'back'], [6, 0]], [[-67, 67, 270, 'back'], [1, 270]], [[-52, -248, 270, 'front'], [2, 270]]]]\nlabels = [\"regression: front sensor rotation direction\", \"repair trap\", \"combined fault\", \"control\", \"control\", \"boundary\", \"boundary\", \"control\"]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"%s %d\" % (labels[i % len(labels)], i), 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":"92713c64e9382ddbc8001dfa5651d98c84874f5a17f9db8c8ee8ffee10f64bca","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    gx, gy, prev_r, camera = x\n    if gx * gx + gy * gy < 300 * 300 or abs(gx) == abs(gy):\n        r = prev_r\n    elif abs(gy) > abs(gx):\n        r = 0 if gy > 0 else 180\n    else:\n        r = 90 if gx > 0 else 270\n    from_km = {(0, 0): 1, (0, 1): 2, (2, 0): 3, (2, 1): 4, (3, 1): 5, (1, 0): 6, (1, 1): 7, (3, 0): 8}\n    if camera == 'front':\n        total = (270 + r) % 360\n        return [from_km[(total // 90, 1)], r]\n    total = (90 + r) % 360\n    return [from_km[(total // 90, 0)], r]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[439, -411, 180, 'front'], [4, 90]], [[298, 553, 180, 'front'], [5, 0]], [[925, 721, 90, 'front'], [4, 90]], [[-382, -382, 180, 'back'], [8, 180]], [[50, -890, 180, 'back'], [8, 180]], [[53, -848, 270, 'back'], [8, 180]], [[247, -67, 270, 'back'], [1, 270]], [[686, -373, 90, 'front'], [4, 90]]], [[[-835, 686, 0, 'front'], [2, 270]], [[648, -194, 90, 'front'], [4, 90]], [[-926, 466, 0, 'back'], [1, 270]], [[110, -610, 0, 'back'], [8, 180]], [[-900, 900, 270, 'back'], [1, 270]], [[-869, 635, 270, 'back'], [1, 270]], [[-239, -597, 180, 'back'], [8, 180]], [[-993, 66, 0, 'front'], [2, 270]]], [[[-994, 954, 180, 'front'], [2, 270]], [[-176, 109, 270, 'front'], [2, 270]], [[-552, 552, 270, 'front'], [2, 270]], [[486, 992, 270, 'back'], [6, 0]], [[54, 63, 0, 'back'], [6, 0]], [[-86, -105, 270, 'back'], [1, 270]], [[-134, -182, 180, 'back'], [8, 180]], [[717, 36, 90, 'front'], [4, 90]]], [[[-522, 369, 0, 'front'], [2, 270]], [[213, 206, 270, 'front'], [2, 270]], [[-996, 271, 270, 'front'], [2, 270]], [[137, 86, 180, 'back'], [8, 180]], [[116, 53, 90, 'back'], [3, 90]], [[-183, 181, 180, 'back'], [8, 180]], [[-651, 121, 180, 'back'], [1, 270]], [[-899, 899, 90, 'front'], [4, 90]]], [[[-1000, -619, 90, 'front'], [2, 270]], [[-869, -869, 0, 'front'], [5, 0]], [[634, -189, 90, 'front'], [4, 90]], [[816, 260, 0, 'back'], [3, 90]], [[-188, 149, 180, 'back'], [8, 180]], [[-532, 686, 180, 'back'], [6, 0]], [[-67, 67, 270, 'back'], [1, 270]], [[-52, -248, 270, 'front'], [2, 270]]]]\nlabels = [\"regression: front sensor rotation direction\", \"repair trap\", \"combined fault\", \"control\", \"control\", \"boundary\", \"boundary\", \"control\"]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"%s %d\" % (labels[i % len(labels)], i), 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"},"fixed":{"sha256":"c73e206cdf9f232f74b4cb3c0da1f405eac814e40902415076b385c8771ea430","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    gx, gy, prev_r, camera = x\n    if gx * gx + gy * gy < 300 * 300 or abs(gx) == abs(gy):\n        r = prev_r\n    elif abs(gy) > abs(gx):\n        r = 0 if gy > 0 else 180\n    else:\n        r = 90 if gx > 0 else 270\n    from_km = {(0, 0): 1, (0, 1): 2, (2, 0): 3, (2, 1): 4, (3, 1): 5, (1, 0): 6, (1, 1): 7, (3, 0): 8}\n    if camera == 'front':\n        total = (270 - r) % 360\n        return [from_km[(total // 90, 1)], r]\n    total = (90 + r) % 360\n    return [from_km[(total // 90, 0)], r]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[439, -411, 180, 'front'], [4, 90]], [[298, 553, 180, 'front'], [5, 0]], [[925, 721, 90, 'front'], [4, 90]], [[-382, -382, 180, 'back'], [8, 180]], [[50, -890, 180, 'back'], [8, 180]], [[53, -848, 270, 'back'], [8, 180]], [[247, -67, 270, 'back'], [1, 270]], [[686, -373, 90, 'front'], [4, 90]]], [[[-835, 686, 0, 'front'], [2, 270]], [[648, -194, 90, 'front'], [4, 90]], [[-926, 466, 0, 'back'], [1, 270]], [[110, -610, 0, 'back'], [8, 180]], [[-900, 900, 270, 'back'], [1, 270]], [[-869, 635, 270, 'back'], [1, 270]], [[-239, -597, 180, 'back'], [8, 180]], [[-993, 66, 0, 'front'], [2, 270]]], [[[-994, 954, 180, 'front'], [2, 270]], [[-176, 109, 270, 'front'], [2, 270]], [[-552, 552, 270, 'front'], [2, 270]], [[486, 992, 270, 'back'], [6, 0]], [[54, 63, 0, 'back'], [6, 0]], [[-86, -105, 270, 'back'], [1, 270]], [[-134, -182, 180, 'back'], [8, 180]], [[717, 36, 90, 'front'], [4, 90]]], [[[-522, 369, 0, 'front'], [2, 270]], [[213, 206, 270, 'front'], [2, 270]], [[-996, 271, 270, 'front'], [2, 270]], [[137, 86, 180, 'back'], [8, 180]], [[116, 53, 90, 'back'], [3, 90]], [[-183, 181, 180, 'back'], [8, 180]], [[-651, 121, 180, 'back'], [1, 270]], [[-899, 899, 90, 'front'], [4, 90]]], [[[-1000, -619, 90, 'front'], [2, 270]], [[-869, -869, 0, 'front'], [5, 0]], [[634, -189, 90, 'front'], [4, 90]], [[816, 260, 0, 'back'], [3, 90]], [[-188, 149, 180, 'back'], [8, 180]], [[-532, 686, 180, 'back'], [6, 0]], [[-67, 67, 270, 'back'], [1, 270]], [[-52, -248, 270, 'front'], [2, 270]]]]\nlabels = [\"regression: front sensor rotation direction\", \"repair trap\", \"combined fault\", \"control\", \"control\", \"boundary\", \"boundary\", \"control\"]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"%s %d\" % (labels[i % len(labels)], i), 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":"A deterministic bounded teaching model with a stipulated contract; it makes no claim of conformance to any published specification. 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-image-orientation-metadata-capture-accelerometer-front-mount","generated_at":"2026-09-29T14:49:41.204104+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Camera, phone and scanner images carry an orientation hint separately from the stored pixels; galleries, thumbnailers, editors and upload pipelines must interpret it consistently or photos appear sideways, mirrored or doubly rotated.","repair":"For the mirrored sensor subtract the device rotation from its 270 degree mount.","root_cause":"The mirrored front sensor composes the device rotation in the same direction as the back sensor.","sha256":"6654bbb3df1fa78cd291b056e58df0c619348d31b1ab7111360b20b3b4610ae1","title":"Front camera rotation adds the device turn like the back camera · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":42.733,"exit_code":1,"observations":[{"actual":[2,90],"check":"regression: front sensor rotation direction 0","expected":[4,90],"passed":false},{"actual":[7,0],"check":"repair trap 1","expected":[5,0],"passed":false},{"actual":[2,90],"check":"combined fault 2","expected":[4,90],"passed":false},{"actual":[8,180],"check":"control 3","expected":[8,180],"passed":true},{"actual":[8,180],"check":"control 4","expected":[8,180],"passed":true},{"actual":[8,180],"check":"boundary 5","expected":[8,180],"passed":true},{"actual":[1,270],"check":"boundary 6","expected":[1,270],"passed":true},{"actual":[2,90],"check":"control 7","expected":[4,90],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: front sensor rotation direction 0\", \"actual\": [2, 90], \"expected\": [4, 90], \"passed\": false}, {\"check\": \"repair trap 1\", \"actual\": [7, 0], \"expected\": [5, 0], \"passed\": false}, {\"check\": \"combined fault 2\", \"actual\": [2, 90], \"expected\": [4, 90], \"passed\": false}, {\"check\": \"control 3\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"control 4\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": [1, 270], \"expected\": [1, 270], \"passed\": true}, {\"check\": \"control 7\", \"actual\": [2, 90], \"expected\": [4, 90], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":37.775,"exit_code":1,"observations":[{"actual":[2,90],"check":"regression: front sensor rotation direction 0","expected":[4,90],"passed":false},{"actual":[5,0],"check":"repair trap 1","expected":[5,0],"passed":true},{"actual":[2,90],"check":"combined fault 2","expected":[4,90],"passed":false},{"actual":[8,180],"check":"control 3","expected":[8,180],"passed":true},{"actual":[8,180],"check":"control 4","expected":[8,180],"passed":true},{"actual":[8,180],"check":"boundary 5","expected":[8,180],"passed":true},{"actual":[1,270],"check":"boundary 6","expected":[1,270],"passed":true},{"actual":[2,90],"check":"control 7","expected":[4,90],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: front sensor rotation direction 0\", \"actual\": [2, 90], \"expected\": [4, 90], \"passed\": false}, {\"check\": \"repair trap 1\", \"actual\": [5, 0], \"expected\": [5, 0], \"passed\": true}, {\"check\": \"combined fault 2\", \"actual\": [2, 90], \"expected\": [4, 90], \"passed\": false}, {\"check\": \"control 3\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"control 4\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": [1, 270], \"expected\": [1, 270], \"passed\": true}, {\"check\": \"control 7\", \"actual\": [2, 90], \"expected\": [4, 90], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":42.331,"exit_code":0,"observations":[{"actual":[4,90],"check":"regression: front sensor rotation direction 0","expected":[4,90],"passed":true},{"actual":[5,0],"check":"repair trap 1","expected":[5,0],"passed":true},{"actual":[4,90],"check":"combined fault 2","expected":[4,90],"passed":true},{"actual":[8,180],"check":"control 3","expected":[8,180],"passed":true},{"actual":[8,180],"check":"control 4","expected":[8,180],"passed":true},{"actual":[8,180],"check":"boundary 5","expected":[8,180],"passed":true},{"actual":[1,270],"check":"boundary 6","expected":[1,270],"passed":true},{"actual":[4,90],"check":"control 7","expected":[4,90],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: front sensor rotation direction 0\", \"actual\": [4, 90], \"expected\": [4, 90], \"passed\": true}, {\"check\": \"repair trap 1\", \"actual\": [5, 0], \"expected\": [5, 0], \"passed\": true}, {\"check\": \"combined fault 2\", \"actual\": [4, 90], \"expected\": [4, 90], \"passed\": true}, {\"check\": \"control 3\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"control 4\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": [8, 180], \"expected\": [8, 180], \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": [1, 270], \"expected\": [1, 270], \"passed\": true}, {\"check\": \"control 7\", \"actual\": [4, 90], \"expected\": [4, 90], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}