{"abstract":"Mirroring a portrait photo in the editor leaves it lying on its side.","category":"Image orientation metadata","checks":8,"contract":"A photo editor rotates and flips losslessly by rewriting only the orientation tag. An orientation is modelled as (k, m): mirror horizontally m times, then rotate k quarter turns clockwise (tag table 1:(0,0) 2:(0,1) 3:(2,0) 4:(2,1) 5:(3,1) 6:(1,0) 7:(1,1) 8:(3,0)). Editor operations act on the displayed image: cw, ccw, r180, flip_h (mirror left-right) and flip_v (mirror top-bottom). Invalid starting tags count as 1; an unknown operation returns {\"error\": \"unknown-op\", \"op\": op}. Return the final tag.","evaluation_group":"w2-image-orientation-metadata-editor-metadata-rotate","failed_approach":"Adding a half turn is only right when the current rotation is a quarter turn.","family":"w2-image-orientation-metadata-editor-metadata-rotate-flip-h-conjugation","id":"FA-78946","implementations":{"attempt":{"sha256":"a9d8f0c4d857fda8590cd34c99866e1fb0ac6e1c2f3b74997fd101d1169eed2c","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(tag, ops):\n    to_km = {1: (0, 0), 2: (0, 1), 3: (2, 0), 4: (2, 1), 5: (3, 1), 6: (1, 0), 7: (1, 1), 8: (3, 0)}\n    from_km = {v: t for t, v in to_km.items()}\n    if tag not in to_km:\n        tag = 1\n    k, m = to_km[tag]\n    for op in ops:\n        if op == 'cw':\n            k = (k + 1) % 4\n        elif op == 'ccw':\n            k = (k + 3) % 4\n        elif op == 'r180':\n            k = (k + 2) % 4\n        elif op == 'flip_h':\n            k, m = (k + 2) % 4, 1 - m\n        elif op == 'flip_v':\n            k, m = (2 - k) % 4, 1 - m\n        else:\n            return {'error': 'unknown-op', 'op': op}\n    return from_km[(k, m)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[(4, ['cw', 'cw', 'ccw', 'flip_h']), 6], [(8, ['ccw', 'flip_h', 'ccw']), 7], [(0, ['flip_h', 'ccw', 'flip_h', 'flip_v']), 7], [(7, ['flip_v', 'ccw', 'r180']), 3], [(8, ['ccw', 'cw']), 8], [(3, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(1, ['cw', 'ccw', 'r180', 'cw']), 8], [(2, ['ccw', 'flip_h', 'r180', 'ccw']), 3]], [[(11, ['flip_v', 'ccw', 'flip_h', 'flip_v']), 5], [(7, ['cw', 'r180', 'flip_h']), 1], [(8, ['ccw', 'flip_h', 'ccw', 'flip_h']), 8], [(0, []), 1], [(8, ['ccw', 'r180']), 1], [(4, ['mirror', 'flip_v', 'cw', 'r180']), {'error': 'unknown-op', 'op': 'mirror'}], [(2, ['flip_v', 'ccw', 'cw']), 3], [(7, ['flip_h', 'flip_v']), 5]], [[(5, ['flip_h']), 6], [(11, ['flip_h']), 2], [(4, ['flip_h', 'ccw', 'flip_h']), 5], [(1, ['ccw', 'ccw', 'r180']), 1], [(11, ['r180', 'cw', 'flip_v', 'cw']), 2], [(2, ['flip_v', 'cw', 'cw']), 1], [(6, ['r180', 'flip_v', 'ccw']), 4], [(11, ['cw', 'flip_v', 'flip_h']), 8]], [[(5, ['flip_h', 'flip_v', 'r180']), 5], [(8, ['ccw', 'flip_h']), 4], [(1, ['flip_h', 'ccw', 'r180', 'flip_h']), 8], [(4, ['ccw']), 7], [(8, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(4, ['ccw', 'ccw', 'flip_v', 'ccw']), 6], [(11, ['r180']), 3], [(2, ['ccw', 'r180', 'flip_h', 'flip_v']), 5]], [[(4, ['cw', 'flip_h']), 6], [(0, ['flip_h', 'r180', 'flip_v']), 1], [(3, ['r180', 'flip_h', 'ccw', 'flip_h']), 6], [(1, []), 1], [(11, ['cw', 'cw', 'ccw']), 6], [(5, ['r180']), 7], [(6, ['ccw']), 1], [(7, ['flip_h']), 8]]]\nlabels = [\"regression: horizontal flip of a rotated view\", \"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":"2d4f57000ce366ab66a2f841d0d4ea42a67f8d1028119061d7f559bd6a5a37a4","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(tag, ops):\n    to_km = {1: (0, 0), 2: (0, 1), 3: (2, 0), 4: (2, 1), 5: (3, 1), 6: (1, 0), 7: (1, 1), 8: (3, 0)}\n    from_km = {v: t for t, v in to_km.items()}\n    if tag not in to_km:\n        tag = 1\n    k, m = to_km[tag]\n    for op in ops:\n        if op == 'cw':\n            k = (k + 1) % 4\n        elif op == 'ccw':\n            k = (k + 3) % 4\n        elif op == 'r180':\n            k = (k + 2) % 4\n        elif op == 'flip_h':\n            k, m = k, 1 - m\n        elif op == 'flip_v':\n            k, m = (2 - k) % 4, 1 - m\n        else:\n            return {'error': 'unknown-op', 'op': op}\n    return from_km[(k, m)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[(4, ['cw', 'cw', 'ccw', 'flip_h']), 6], [(8, ['ccw', 'flip_h', 'ccw']), 7], [(0, ['flip_h', 'ccw', 'flip_h', 'flip_v']), 7], [(7, ['flip_v', 'ccw', 'r180']), 3], [(8, ['ccw', 'cw']), 8], [(3, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(1, ['cw', 'ccw', 'r180', 'cw']), 8], [(2, ['ccw', 'flip_h', 'r180', 'ccw']), 3]], [[(11, ['flip_v', 'ccw', 'flip_h', 'flip_v']), 5], [(7, ['cw', 'r180', 'flip_h']), 1], [(8, ['ccw', 'flip_h', 'ccw', 'flip_h']), 8], [(0, []), 1], [(8, ['ccw', 'r180']), 1], [(4, ['mirror', 'flip_v', 'cw', 'r180']), {'error': 'unknown-op', 'op': 'mirror'}], [(2, ['flip_v', 'ccw', 'cw']), 3], [(7, ['flip_h', 'flip_v']), 5]], [[(5, ['flip_h']), 6], [(11, ['flip_h']), 2], [(4, ['flip_h', 'ccw', 'flip_h']), 5], [(1, ['ccw', 'ccw', 'r180']), 1], [(11, ['r180', 'cw', 'flip_v', 'cw']), 2], [(2, ['flip_v', 'cw', 'cw']), 1], [(6, ['r180', 'flip_v', 'ccw']), 4], [(11, ['cw', 'flip_v', 'flip_h']), 8]], [[(5, ['flip_h', 'flip_v', 'r180']), 5], [(8, ['ccw', 'flip_h']), 4], [(1, ['flip_h', 'ccw', 'r180', 'flip_h']), 8], [(4, ['ccw']), 7], [(8, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(4, ['ccw', 'ccw', 'flip_v', 'ccw']), 6], [(11, ['r180']), 3], [(2, ['ccw', 'r180', 'flip_h', 'flip_v']), 5]], [[(4, ['cw', 'flip_h']), 6], [(0, ['flip_h', 'r180', 'flip_v']), 1], [(3, ['r180', 'flip_h', 'ccw', 'flip_h']), 6], [(1, []), 1], [(11, ['cw', 'cw', 'ccw']), 6], [(5, ['r180']), 7], [(6, ['ccw']), 1], [(7, ['flip_h']), 8]]]\nlabels = [\"regression: horizontal flip of a rotated view\", \"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":"bf141fda52073ffe1d7443b23d08a4d31ee9aebdd55bae03c80597396ead28b5","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(tag, ops):\n    to_km = {1: (0, 0), 2: (0, 1), 3: (2, 0), 4: (2, 1), 5: (3, 1), 6: (1, 0), 7: (1, 1), 8: (3, 0)}\n    from_km = {v: t for t, v in to_km.items()}\n    if tag not in to_km:\n        tag = 1\n    k, m = to_km[tag]\n    for op in ops:\n        if op == 'cw':\n            k = (k + 1) % 4\n        elif op == 'ccw':\n            k = (k + 3) % 4\n        elif op == 'r180':\n            k = (k + 2) % 4\n        elif op == 'flip_h':\n            k, m = (-k) % 4, 1 - m\n        elif op == 'flip_v':\n            k, m = (2 - k) % 4, 1 - m\n        else:\n            return {'error': 'unknown-op', 'op': op}\n    return from_km[(k, m)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[(4, ['cw', 'cw', 'ccw', 'flip_h']), 6], [(8, ['ccw', 'flip_h', 'ccw']), 7], [(0, ['flip_h', 'ccw', 'flip_h', 'flip_v']), 7], [(7, ['flip_v', 'ccw', 'r180']), 3], [(8, ['ccw', 'cw']), 8], [(3, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(1, ['cw', 'ccw', 'r180', 'cw']), 8], [(2, ['ccw', 'flip_h', 'r180', 'ccw']), 3]], [[(11, ['flip_v', 'ccw', 'flip_h', 'flip_v']), 5], [(7, ['cw', 'r180', 'flip_h']), 1], [(8, ['ccw', 'flip_h', 'ccw', 'flip_h']), 8], [(0, []), 1], [(8, ['ccw', 'r180']), 1], [(4, ['mirror', 'flip_v', 'cw', 'r180']), {'error': 'unknown-op', 'op': 'mirror'}], [(2, ['flip_v', 'ccw', 'cw']), 3], [(7, ['flip_h', 'flip_v']), 5]], [[(5, ['flip_h']), 6], [(11, ['flip_h']), 2], [(4, ['flip_h', 'ccw', 'flip_h']), 5], [(1, ['ccw', 'ccw', 'r180']), 1], [(11, ['r180', 'cw', 'flip_v', 'cw']), 2], [(2, ['flip_v', 'cw', 'cw']), 1], [(6, ['r180', 'flip_v', 'ccw']), 4], [(11, ['cw', 'flip_v', 'flip_h']), 8]], [[(5, ['flip_h', 'flip_v', 'r180']), 5], [(8, ['ccw', 'flip_h']), 4], [(1, ['flip_h', 'ccw', 'r180', 'flip_h']), 8], [(4, ['ccw']), 7], [(8, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(4, ['ccw', 'ccw', 'flip_v', 'ccw']), 6], [(11, ['r180']), 3], [(2, ['ccw', 'r180', 'flip_h', 'flip_v']), 5]], [[(4, ['cw', 'flip_h']), 6], [(0, ['flip_h', 'r180', 'flip_v']), 1], [(3, ['r180', 'flip_h', 'ccw', 'flip_h']), 6], [(1, []), 1], [(11, ['cw', 'cw', 'ccw']), 6], [(5, ['r180']), 7], [(6, ['ccw']), 1], [(7, ['flip_h']), 8]]]\nlabels = [\"regression: horizontal flip of a rotated view\", \"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-editor-metadata-rotate-flip-h-conjugation","generated_at":"2026-09-29T14:49:39.881078+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":"Negate the quarter-turn count modulo 4 when toggling the mirror bit for flip_h.","root_cause":"A display-space mirror applied after a rotation reverses the rotation direction, but the code keeps k unchanged.","sha256":"4bc5860aa236c9c7c8b65983b15a432cc6c1b79f660ab0974a321dff5c0717b8","title":"Flipping a rotated photo keeps its rotation count · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":37.461,"exit_code":1,"observations":[{"actual":6,"check":"regression: horizontal flip of a rotated view 0","expected":6,"passed":true},{"actual":5,"check":"repair trap 1","expected":7,"passed":false},{"actual":5,"check":"combined fault 2","expected":7,"passed":false},{"actual":3,"check":"control 3","expected":3,"passed":true},{"actual":8,"check":"control 4","expected":8,"passed":true},{"actual":{"error":"unknown-op","op":"rotate"},"check":"boundary 5","expected":{"error":"unknown-op","op":"rotate"},"passed":true},{"actual":8,"check":"boundary 6","expected":8,"passed":true},{"actual":3,"check":"control 7","expected":3,"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: horizontal flip of a rotated view 0\", \"actual\": 6, \"expected\": 6, \"passed\": true}, {\"check\": \"repair trap 1\", \"actual\": 5, \"expected\": 7, \"passed\": false}, {\"check\": \"combined fault 2\", \"actual\": 5, \"expected\": 7, \"passed\": false}, {\"check\": \"control 3\", \"actual\": 3, \"expected\": 3, \"passed\": true}, {\"check\": \"control 4\", \"actual\": 8, \"expected\": 8, \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"expected\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": 8, \"expected\": 8, \"passed\": true}, {\"check\": \"control 7\", \"actual\": 3, \"expected\": 3, \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":37.396,"exit_code":1,"observations":[{"actual":8,"check":"regression: horizontal flip of a rotated view 0","expected":6,"passed":false},{"actual":7,"check":"repair trap 1","expected":7,"passed":true},{"actual":5,"check":"combined fault 2","expected":7,"passed":false},{"actual":3,"check":"control 3","expected":3,"passed":true},{"actual":8,"check":"control 4","expected":8,"passed":true},{"actual":{"error":"unknown-op","op":"rotate"},"check":"boundary 5","expected":{"error":"unknown-op","op":"rotate"},"passed":true},{"actual":8,"check":"boundary 6","expected":8,"passed":true},{"actual":1,"check":"control 7","expected":3,"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: horizontal flip of a rotated view 0\", \"actual\": 8, \"expected\": 6, \"passed\": false}, {\"check\": \"repair trap 1\", \"actual\": 7, \"expected\": 7, \"passed\": true}, {\"check\": \"combined fault 2\", \"actual\": 5, \"expected\": 7, \"passed\": false}, {\"check\": \"control 3\", \"actual\": 3, \"expected\": 3, \"passed\": true}, {\"check\": \"control 4\", \"actual\": 8, \"expected\": 8, \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"expected\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": 8, \"expected\": 8, \"passed\": true}, {\"check\": \"control 7\", \"actual\": 1, \"expected\": 3, \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.467,"exit_code":0,"observations":[{"actual":6,"check":"regression: horizontal flip of a rotated view 0","expected":6,"passed":true},{"actual":7,"check":"repair trap 1","expected":7,"passed":true},{"actual":7,"check":"combined fault 2","expected":7,"passed":true},{"actual":3,"check":"control 3","expected":3,"passed":true},{"actual":8,"check":"control 4","expected":8,"passed":true},{"actual":{"error":"unknown-op","op":"rotate"},"check":"boundary 5","expected":{"error":"unknown-op","op":"rotate"},"passed":true},{"actual":8,"check":"boundary 6","expected":8,"passed":true},{"actual":3,"check":"control 7","expected":3,"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: horizontal flip of a rotated view 0\", \"actual\": 6, \"expected\": 6, \"passed\": true}, {\"check\": \"repair trap 1\", \"actual\": 7, \"expected\": 7, \"passed\": true}, {\"check\": \"combined fault 2\", \"actual\": 7, \"expected\": 7, \"passed\": true}, {\"check\": \"control 3\", \"actual\": 3, \"expected\": 3, \"passed\": true}, {\"check\": \"control 4\", \"actual\": 8, \"expected\": 8, \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"expected\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": 8, \"expected\": 8, \"passed\": true}, {\"check\": \"control 7\", \"actual\": 3, \"expected\": 3, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}