{"abstract":"Komi written as 6½ is rejected.","category":"Go territory scoring","checks":8,"contract":"Input a komi string: optional sign, whole points, and an optional half written \".5\"/\".0\" or \"½\". A bare half (\"½\", \".5\") is allowed. Return komi in tenths or \"invalid\".","evaluation_group":"w2-go-territory-scoring-komi-parse","failed_approach":"Detecting the glyph without stripping it leaves a non-digit in the whole part.","family":"w2-go-territory-scoring-komi-parse-half-glyph","id":"FA-83306","implementations":{"attempt":{"sha256":"1a90873b57f7da4821ff9e37425c678022876fa09d2cf3272d9d83fec2a90217","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    s = x.strip()\n    neg = s.startswith('-')\n    if s[:1] in '+-' and s:\n        s = s[1:]\n    half = 0\n    if s.endswith('½'):\n        half = 5\n    elif '.' in s:\n        s, _, frac = s.partition('.')\n        if frac not in ('0', '5'):\n            return 'invalid'\n        half = int(frac)\n    if not s.isdigit():\n        if s == '' and half:\n            s = '0'\n        else:\n            return 'invalid'\n    v = int(s) * 10 + half\n    return -v if neg else v\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['6½', 65], ['-6½', -65], ['7.0', 70], ['6.3', 'invalid'], ['.5', 5], ['', 'invalid'], ['-', 'invalid'], ['abc', 'invalid']], [['abc', 'invalid'], ['5.', 'invalid'], [' 6.5 ', 65], ['-3', -30], ['-7.5', -75], ['0.0', 0], ['+½', 5], ['+½', 5]], [['6.5', 65], ['7', 70], ['-0.5', -5], ['6½', 65], ['-6½', -65], ['6.50', 'invalid'], ['+', 'invalid'], ['+½', 5]], [['0.5', 5], ['6½', 65], ['½', 5], ['½', 5], ['-6½', -65], ['0', 0], ['+5.5', 55], ['7.0', 70]], [['6½', 65], ['-6½', -65], ['-', 'invalid'], ['abc', 'invalid'], ['5.', 'invalid'], [' 6.5 ', 65], ['-3', -30], ['-7.5', -75]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"komi case %d\" % 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":"9a96ad3df959947a98e8055a9717d97ba71c5ceb7c9b39213fb385471c50364e","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    s = x.strip()\n    neg = s.startswith('-')\n    if s[:1] in '+-' and s:\n        s = s[1:]\n    half = 0\n    if s.endswith('1/2'):\n        half = 5\n        s = s[:-1]\n    elif '.' in s:\n        s, _, frac = s.partition('.')\n        if frac not in ('0', '5'):\n            return 'invalid'\n        half = int(frac)\n    if not s.isdigit():\n        if s == '' and half:\n            s = '0'\n        else:\n            return 'invalid'\n    v = int(s) * 10 + half\n    return -v if neg else v\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['6½', 65], ['-6½', -65], ['7.0', 70], ['6.3', 'invalid'], ['.5', 5], ['', 'invalid'], ['-', 'invalid'], ['abc', 'invalid']], [['abc', 'invalid'], ['5.', 'invalid'], [' 6.5 ', 65], ['-3', -30], ['-7.5', -75], ['0.0', 0], ['+½', 5], ['+½', 5]], [['6.5', 65], ['7', 70], ['-0.5', -5], ['6½', 65], ['-6½', -65], ['6.50', 'invalid'], ['+', 'invalid'], ['+½', 5]], [['0.5', 5], ['6½', 65], ['½', 5], ['½', 5], ['-6½', -65], ['0', 0], ['+5.5', 55], ['7.0', 70]], [['6½', 65], ['-6½', -65], ['-', 'invalid'], ['abc', 'invalid'], ['5.', 'invalid'], [' 6.5 ', 65], ['-3', -30], ['-7.5', -75]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"komi case %d\" % 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":"c3531af67ec3f893486e700e64decdbfa106bb8221a98b7f059f90be62e5fc8b","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    s = x.strip()\n    neg = s.startswith('-')\n    if s[:1] in '+-' and s:\n        s = s[1:]\n    half = 0\n    if s.endswith('½'):\n        half = 5\n        s = s[:-1]\n    elif '.' in s:\n        s, _, frac = s.partition('.')\n        if frac not in ('0', '5'):\n            return 'invalid'\n        half = int(frac)\n    if not s.isdigit():\n        if s == '' and half:\n            s = '0'\n        else:\n            return 'invalid'\n    v = int(s) * 10 + half\n    return -v if neg else v\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['6½', 65], ['-6½', -65], ['7.0', 70], ['6.3', 'invalid'], ['.5', 5], ['', 'invalid'], ['-', 'invalid'], ['abc', 'invalid']], [['abc', 'invalid'], ['5.', 'invalid'], [' 6.5 ', 65], ['-3', -30], ['-7.5', -75], ['0.0', 0], ['+½', 5], ['+½', 5]], [['6.5', 65], ['7', 70], ['-0.5', -5], ['6½', 65], ['-6½', -65], ['6.50', 'invalid'], ['+', 'invalid'], ['+½', 5]], [['0.5', 5], ['6½', 65], ['½', 5], ['½', 5], ['-6½', -65], ['0', 0], ['+5.5', 55], ['7.0', 70]], [['6½', 65], ['-6½', -65], ['-', 'invalid'], ['abc', 'invalid'], ['5.', 'invalid'], [' 6.5 ', 65], ['-3', -30], ['-7.5', -75]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"komi case %d\" % 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":"Small rectangular toy boards given as strings of B, W and dot; a bounded teaching model of one scoring or bookkeeping rule, not a complete rules engine or server implementation. 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-go-territory-scoring-komi-parse-half-glyph","generated_at":"2026-09-29T14:50:20.349834+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Go servers and scoring tools compute this value automatically; a wrong answer changes a game result.","repair":"Detect the \"½\" suffix and strip it.","root_cause":"The suffix test looks for \"1/2\" rather than the glyph.","sha256":"1ffbe6f1024d31d8eced97e3b3284663fb2bdf73ba06498c27cc6f4d97933bf5","title":"The half glyph is not recognised · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":39.506,"exit_code":1,"observations":[{"actual":"invalid","check":"komi case 0","expected":65,"passed":false},{"actual":"invalid","check":"komi case 1","expected":-65,"passed":false},{"actual":70,"check":"komi case 2","expected":70,"passed":true},{"actual":"invalid","check":"komi case 3","expected":"invalid","passed":true},{"actual":5,"check":"komi case 4","expected":5,"passed":true},{"actual":"invalid","check":"komi case 5","expected":"invalid","passed":true},{"actual":"invalid","check":"komi case 6","expected":"invalid","passed":true},{"actual":"invalid","check":"komi case 7","expected":"invalid","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"komi case 0\", \"actual\": \"invalid\", \"expected\": 65, \"passed\": false}, {\"check\": \"komi case 1\", \"actual\": \"invalid\", \"expected\": -65, \"passed\": false}, {\"check\": \"komi case 2\", \"actual\": 70, \"expected\": 70, \"passed\": true}, {\"check\": \"komi case 3\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 4\", \"actual\": 5, \"expected\": 5, \"passed\": true}, {\"check\": \"komi case 5\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 6\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 7\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.147,"exit_code":1,"observations":[{"actual":"invalid","check":"komi case 0","expected":65,"passed":false},{"actual":"invalid","check":"komi case 1","expected":-65,"passed":false},{"actual":70,"check":"komi case 2","expected":70,"passed":true},{"actual":"invalid","check":"komi case 3","expected":"invalid","passed":true},{"actual":5,"check":"komi case 4","expected":5,"passed":true},{"actual":"invalid","check":"komi case 5","expected":"invalid","passed":true},{"actual":"invalid","check":"komi case 6","expected":"invalid","passed":true},{"actual":"invalid","check":"komi case 7","expected":"invalid","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"komi case 0\", \"actual\": \"invalid\", \"expected\": 65, \"passed\": false}, {\"check\": \"komi case 1\", \"actual\": \"invalid\", \"expected\": -65, \"passed\": false}, {\"check\": \"komi case 2\", \"actual\": 70, \"expected\": 70, \"passed\": true}, {\"check\": \"komi case 3\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 4\", \"actual\": 5, \"expected\": 5, \"passed\": true}, {\"check\": \"komi case 5\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 6\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 7\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.555,"exit_code":0,"observations":[{"actual":65,"check":"komi case 0","expected":65,"passed":true},{"actual":-65,"check":"komi case 1","expected":-65,"passed":true},{"actual":70,"check":"komi case 2","expected":70,"passed":true},{"actual":"invalid","check":"komi case 3","expected":"invalid","passed":true},{"actual":5,"check":"komi case 4","expected":5,"passed":true},{"actual":"invalid","check":"komi case 5","expected":"invalid","passed":true},{"actual":"invalid","check":"komi case 6","expected":"invalid","passed":true},{"actual":"invalid","check":"komi case 7","expected":"invalid","passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"komi case 0\", \"actual\": 65, \"expected\": 65, \"passed\": true}, {\"check\": \"komi case 1\", \"actual\": -65, \"expected\": -65, \"passed\": true}, {\"check\": \"komi case 2\", \"actual\": 70, \"expected\": 70, \"passed\": true}, {\"check\": \"komi case 3\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 4\", \"actual\": 5, \"expected\": 5, \"passed\": true}, {\"check\": \"komi case 5\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 6\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}, {\"check\": \"komi case 7\", \"actual\": \"invalid\", \"expected\": \"invalid\", \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}