{"abstract":"Both rotate buttons turn the photo the same way.","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":"abs(k - 1) maps 0 to 1 instead of wrapping to 3.","family":"w2-image-orientation-metadata-editor-metadata-rotate-ccw-direction","id":"FA-78956","implementations":{"attempt":{"sha256":"353d2d29219ebd68110338cb2f4b346d13f0f70a019798987e7224600e88452c","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 = abs(k - 1) % 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 = [[[(7, ['flip_v', 'ccw', 'r180']), 3], [(4, ['cw', 'cw', 'ccw', 'flip_h']), 6], [(0, ['ccw', 'flip_v', 'r180', 'cw']), 4], [(8, ['ccw', 'flip_h', 'ccw']), 7], [(3, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(6, []), 6], [(0, ['flip_v']), 4], [(8, ['ccw', 'cw']), 8]], [[(2, ['flip_v', 'ccw', 'cw']), 3], [(1, ['ccw', 'flip_v']), 5], [(11, ['ccw', 'flip_h']), 7], [(8, ['CW']), {'error': 'unknown-op', 'op': 'CW'}], [(0, []), 1], [(4, ['mirror', 'flip_v', 'cw', 'r180']), {'error': 'unknown-op', 'op': 'mirror'}], [(5, ['ccw', 'mirror']), {'error': 'unknown-op', 'op': 'mirror'}], [(7, ['r180', 'ccw', 'flip_v', 'cw']), 6]], [[(6, ['flip_h', 'flip_h', 'ccw', 'r180']), 3], [(9, ['ccw', 'ccw', 'cw', 'r180']), 6], [(9, ['r180', 'r180', 'ccw', 'flip_v']), 5], [(11, ['r180', 'cw', 'flip_v', 'cw']), 2], [(9, ['cw', 'r180', 'flip_h']), 7], [(11, ['cw', 'flip_v', 'flip_h']), 8], [(5, ['flip_h']), 6], [(6, ['r180', 'flip_v', 'ccw']), 4]], [[(4, ['ccw']), 7], [(0, ['ccw']), 8], [(1, ['ccw']), 8], [(8, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(11, ['r180']), 3], [(1, ['r180', 'flip_h', 'cw', 'flip_v']), 8], [(5, ['flip_h', 'flip_v', 'r180']), 5], [(0, ['r180', 'ccw', 'cw', 'cw']), 8]], [[(8, ['ccw']), 3], [(9, ['ccw', 'flip_v', 'cw']), 2], [(0, ['ccw', 'flip_h']), 7], [(2, ['flip_v', 'flip_v']), 2], [(1, []), 1], [(5, ['r180']), 7], [(9, ['flip_v']), 4], [(6, ['ccw']), 1]]]\nlabels = [\"regression: counter-clockwise step\", \"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":"aa450a10ba53ee102d042624f931b7e7ff949e3ea6da25bab71c8a8ccc6b017e","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 + 1) % 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 = [[[(7, ['flip_v', 'ccw', 'r180']), 3], [(4, ['cw', 'cw', 'ccw', 'flip_h']), 6], [(0, ['ccw', 'flip_v', 'r180', 'cw']), 4], [(8, ['ccw', 'flip_h', 'ccw']), 7], [(3, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(6, []), 6], [(0, ['flip_v']), 4], [(8, ['ccw', 'cw']), 8]], [[(2, ['flip_v', 'ccw', 'cw']), 3], [(1, ['ccw', 'flip_v']), 5], [(11, ['ccw', 'flip_h']), 7], [(8, ['CW']), {'error': 'unknown-op', 'op': 'CW'}], [(0, []), 1], [(4, ['mirror', 'flip_v', 'cw', 'r180']), {'error': 'unknown-op', 'op': 'mirror'}], [(5, ['ccw', 'mirror']), {'error': 'unknown-op', 'op': 'mirror'}], [(7, ['r180', 'ccw', 'flip_v', 'cw']), 6]], [[(6, ['flip_h', 'flip_h', 'ccw', 'r180']), 3], [(9, ['ccw', 'ccw', 'cw', 'r180']), 6], [(9, ['r180', 'r180', 'ccw', 'flip_v']), 5], [(11, ['r180', 'cw', 'flip_v', 'cw']), 2], [(9, ['cw', 'r180', 'flip_h']), 7], [(11, ['cw', 'flip_v', 'flip_h']), 8], [(5, ['flip_h']), 6], [(6, ['r180', 'flip_v', 'ccw']), 4]], [[(4, ['ccw']), 7], [(0, ['ccw']), 8], [(1, ['ccw']), 8], [(8, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(11, ['r180']), 3], [(1, ['r180', 'flip_h', 'cw', 'flip_v']), 8], [(5, ['flip_h', 'flip_v', 'r180']), 5], [(0, ['r180', 'ccw', 'cw', 'cw']), 8]], [[(8, ['ccw']), 3], [(9, ['ccw', 'flip_v', 'cw']), 2], [(0, ['ccw', 'flip_h']), 7], [(2, ['flip_v', 'flip_v']), 2], [(1, []), 1], [(5, ['r180']), 7], [(9, ['flip_v']), 4], [(6, ['ccw']), 1]]]\nlabels = [\"regression: counter-clockwise step\", \"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":"5bc59ce40e467d36428519fbb41b4ad4185e983531fa165f5c2830dab95c2876","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 = [[[(7, ['flip_v', 'ccw', 'r180']), 3], [(4, ['cw', 'cw', 'ccw', 'flip_h']), 6], [(0, ['ccw', 'flip_v', 'r180', 'cw']), 4], [(8, ['ccw', 'flip_h', 'ccw']), 7], [(3, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(6, []), 6], [(0, ['flip_v']), 4], [(8, ['ccw', 'cw']), 8]], [[(2, ['flip_v', 'ccw', 'cw']), 3], [(1, ['ccw', 'flip_v']), 5], [(11, ['ccw', 'flip_h']), 7], [(8, ['CW']), {'error': 'unknown-op', 'op': 'CW'}], [(0, []), 1], [(4, ['mirror', 'flip_v', 'cw', 'r180']), {'error': 'unknown-op', 'op': 'mirror'}], [(5, ['ccw', 'mirror']), {'error': 'unknown-op', 'op': 'mirror'}], [(7, ['r180', 'ccw', 'flip_v', 'cw']), 6]], [[(6, ['flip_h', 'flip_h', 'ccw', 'r180']), 3], [(9, ['ccw', 'ccw', 'cw', 'r180']), 6], [(9, ['r180', 'r180', 'ccw', 'flip_v']), 5], [(11, ['r180', 'cw', 'flip_v', 'cw']), 2], [(9, ['cw', 'r180', 'flip_h']), 7], [(11, ['cw', 'flip_v', 'flip_h']), 8], [(5, ['flip_h']), 6], [(6, ['r180', 'flip_v', 'ccw']), 4]], [[(4, ['ccw']), 7], [(0, ['ccw']), 8], [(1, ['ccw']), 8], [(8, ['rotate']), {'error': 'unknown-op', 'op': 'rotate'}], [(11, ['r180']), 3], [(1, ['r180', 'flip_h', 'cw', 'flip_v']), 8], [(5, ['flip_h', 'flip_v', 'r180']), 5], [(0, ['r180', 'ccw', 'cw', 'cw']), 8]], [[(8, ['ccw']), 3], [(9, ['ccw', 'flip_v', 'cw']), 2], [(0, ['ccw', 'flip_h']), 7], [(2, ['flip_v', 'flip_v']), 2], [(1, []), 1], [(5, ['r180']), 7], [(9, ['flip_v']), 4], [(6, ['ccw']), 1]]]\nlabels = [\"regression: counter-clockwise step\", \"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-ccw-direction","generated_at":"2026-09-29T14:49:39.925258+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":"Add three quarter turns (subtract one modulo 4).","root_cause":"The ccw branch adds one quarter turn instead of three.","sha256":"1f6040a8831c73704a756af3220af97f1aca6e9dc00a39bab2a728c5af0f0444","title":"Counter-clockwise button rotates clockwise · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":38.5,"exit_code":1,"observations":[{"actual":3,"check":"regression: counter-clockwise step 0","expected":3,"passed":true},{"actual":8,"check":"repair trap 1","expected":6,"passed":false},{"actual":2,"check":"combined fault 2","expected":4,"passed":false},{"actual":7,"check":"control 3","expected":7,"passed":true},{"actual":{"error":"unknown-op","op":"rotate"},"check":"control 4","expected":{"error":"unknown-op","op":"rotate"},"passed":true},{"actual":6,"check":"boundary 5","expected":6,"passed":true},{"actual":4,"check":"boundary 6","expected":4,"passed":true},{"actual":8,"check":"control 7","expected":8,"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: counter-clockwise step 0\", \"actual\": 3, \"expected\": 3, \"passed\": true}, {\"check\": \"repair trap 1\", \"actual\": 8, \"expected\": 6, \"passed\": false}, {\"check\": \"combined fault 2\", \"actual\": 2, \"expected\": 4, \"passed\": false}, {\"check\": \"control 3\", \"actual\": 7, \"expected\": 7, \"passed\": true}, {\"check\": \"control 4\", \"actual\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"expected\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": 6, \"expected\": 6, \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": 4, \"expected\": 4, \"passed\": true}, {\"check\": \"control 7\", \"actual\": 8, \"expected\": 8, \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.559,"exit_code":1,"observations":[{"actual":1,"check":"regression: counter-clockwise step 0","expected":3,"passed":false},{"actual":8,"check":"repair trap 1","expected":6,"passed":false},{"actual":2,"check":"combined fault 2","expected":4,"passed":false},{"actual":7,"check":"control 3","expected":7,"passed":true},{"actual":{"error":"unknown-op","op":"rotate"},"check":"control 4","expected":{"error":"unknown-op","op":"rotate"},"passed":true},{"actual":6,"check":"boundary 5","expected":6,"passed":true},{"actual":4,"check":"boundary 6","expected":4,"passed":true},{"actual":6,"check":"control 7","expected":8,"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: counter-clockwise step 0\", \"actual\": 1, \"expected\": 3, \"passed\": false}, {\"check\": \"repair trap 1\", \"actual\": 8, \"expected\": 6, \"passed\": false}, {\"check\": \"combined fault 2\", \"actual\": 2, \"expected\": 4, \"passed\": false}, {\"check\": \"control 3\", \"actual\": 7, \"expected\": 7, \"passed\": true}, {\"check\": \"control 4\", \"actual\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"expected\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": 6, \"expected\": 6, \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": 4, \"expected\": 4, \"passed\": true}, {\"check\": \"control 7\", \"actual\": 6, \"expected\": 8, \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.162,"exit_code":0,"observations":[{"actual":3,"check":"regression: counter-clockwise step 0","expected":3,"passed":true},{"actual":6,"check":"repair trap 1","expected":6,"passed":true},{"actual":4,"check":"combined fault 2","expected":4,"passed":true},{"actual":7,"check":"control 3","expected":7,"passed":true},{"actual":{"error":"unknown-op","op":"rotate"},"check":"control 4","expected":{"error":"unknown-op","op":"rotate"},"passed":true},{"actual":6,"check":"boundary 5","expected":6,"passed":true},{"actual":4,"check":"boundary 6","expected":4,"passed":true},{"actual":8,"check":"control 7","expected":8,"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: counter-clockwise step 0\", \"actual\": 3, \"expected\": 3, \"passed\": true}, {\"check\": \"repair trap 1\", \"actual\": 6, \"expected\": 6, \"passed\": true}, {\"check\": \"combined fault 2\", \"actual\": 4, \"expected\": 4, \"passed\": true}, {\"check\": \"control 3\", \"actual\": 7, \"expected\": 7, \"passed\": true}, {\"check\": \"control 4\", \"actual\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"expected\": {\"error\": \"unknown-op\", \"op\": \"rotate\"}, \"passed\": true}, {\"check\": \"boundary 5\", \"actual\": 6, \"expected\": 6, \"passed\": true}, {\"check\": \"boundary 6\", \"actual\": 4, \"expected\": 4, \"passed\": true}, {\"check\": \"control 7\", \"actual\": 8, \"expected\": 8, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}