{"abstract":"\"R1a3\" is reported illegal although the a1 rook can play it.","category":"Chess move legality","checks":8,"contract":"Input: {\"board\", \"white\": side to move, \"san\"} for a non-castling move. Check suffixes + and # are ignored. Resolve the SAN to the unique origin square of a pseudo-legal move (sliders need a clear path; pawns push one or, from their start rank through an empty square, two; pawns capture one step diagonally forward). \"x\" requires an enemy piece on the target and its absence requires an empty target. File/rank disambiguators filter candidates. Return the origin, \"ambiguous\" or \"illegal\".","evaluation_group":"w2-chess_move_legality-san-origin-resolution","failed_approach":"Ignoring file letters makes \"Nbd2\" ambiguous.","family":"w2-chess_move_legality-san-origin-resolution-disambiguator-matching","id":"FA-82636","implementations":{"attempt":{"sha256":"60bc2c1cd5d27b1956ca7c022b93131c0a6915080131ef08a9a2114e7b22d4d5","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    b=x['board']; white=x['white']; s=x['san'].rstrip('+#')\n    def c(q): return ord(q[0])-97,int(q[1])-1\n    def n(f,r): return chr(97+f)+str(r+1)\n    piece=s[0] if s[0] in 'NBRQK' else 'P'\n    body=s[1:] if piece!='P' else s\n    capture='x' in body\n    body=body.replace('x','')\n    to=body[-2:]; dis=body[:-2]\n    tf,tr=c(to)\n    occ=b.get(to)\n    if capture and (occ is None or occ.isupper()==white): return 'illegal'\n    if not capture and occ is not None: return 'illegal'\n    letter=piece if white else piece.lower()\n    cands=[]\n    for q,v in b.items():\n        if v!=letter: continue\n        f,r=c(q)\n        if piece=='P':\n            d=1 if white else -1\n            if capture:\n                ok=abs(tf-f)==1 and tr-r==d\n            else:\n                ok=tf==f and (tr-r==d or (tr-r==2*d and r==(1 if white else 6) and n(f,r+d) not in b))\n        elif piece=='N':\n            ok=(abs(tf-f),abs(tr-r)) in ((1,2),(2,1))\n        elif piece=='K':\n            ok=max(abs(tf-f),abs(tr-r))==1\n        else:\n            df,dr=tf-f,tr-r\n            orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0\n            ok=(piece=='R' and orth) or (piece=='B' and diag) or (piece=='Q' and (orth or diag))\n            if ok:\n                sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)\n                cf,cr=f+sf,r+sr\n                while (cf,cr)!=(tf,tr):\n                    if n(cf,cr) in b: ok=False\n                    cf+=sf; cr+=sr\n        if ok and all(ch==q[1] if ch.isdigit() else True for ch in dis):\n            cands.append(q)\n    if len(cands)==1: return cands[0]\n    return 'ambiguous' if cands else 'illegal'\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('mate suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qf7#', 'white': True}, 'h5'),\n  ('check suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qe5+', 'white': True},\n   'h5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('quiet move onto own',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'P', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('capture with x',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nxf3', 'white': True}, 'g1'),\n  ('black double push', {'board': {'d7': 'p', 'e1': 'K', 'e8': 'k'}, 'san': 'd5', 'white': False},\n   'd7'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('black double push', {'board': {'d7': 'p', 'e1': 'K', 'e8': 'k'}, 'san': 'd5', 'white': False},\n   'd7'),\n  ('white double push', {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k'}, 'san': 'e4', 'white': True},\n   'e2'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4'),\n  ('backward pawn capture',\n   {'board': {'d3': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd3', 'white': True},\n   'illegal'),\n  ('black pawn capture',\n   {'board': {'d4': 'P', 'e1': 'K', 'e5': 'p', 'e8': 'k'}, 'san': 'exd4', 'white': False}, 'e5')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4'),\n  ('black pawn capture',\n   {'board': {'d4': 'P', 'e1': 'K', 'e5': 'p', 'e8': 'k'}, 'san': 'exd4', 'white': False}, 'e5'),\n  ('rook blocked candidate',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'san': 'Rd1', 'white': True},\n   'h1'),\n  ('bishop simple', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'san': 'Bg5', 'white': True},\n   'c1')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('mate suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qf7#', 'white': True}, 'h5'),\n  ('check suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qe5+', 'white': True},\n   'h5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, 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":"bcb3142755d67e62557f1d2d9901e5b7e2a6dfe6adb9d084493e1b3a38f761cc","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    b=x['board']; white=x['white']; s=x['san'].rstrip('+#')\n    def c(q): return ord(q[0])-97,int(q[1])-1\n    def n(f,r): return chr(97+f)+str(r+1)\n    piece=s[0] if s[0] in 'NBRQK' else 'P'\n    body=s[1:] if piece!='P' else s\n    capture='x' in body\n    body=body.replace('x','')\n    to=body[-2:]; dis=body[:-2]\n    tf,tr=c(to)\n    occ=b.get(to)\n    if capture and (occ is None or occ.isupper()==white): return 'illegal'\n    if not capture and occ is not None: return 'illegal'\n    letter=piece if white else piece.lower()\n    cands=[]\n    for q,v in b.items():\n        if v!=letter: continue\n        f,r=c(q)\n        if piece=='P':\n            d=1 if white else -1\n            if capture:\n                ok=abs(tf-f)==1 and tr-r==d\n            else:\n                ok=tf==f and (tr-r==d or (tr-r==2*d and r==(1 if white else 6) and n(f,r+d) not in b))\n        elif piece=='N':\n            ok=(abs(tf-f),abs(tr-r)) in ((1,2),(2,1))\n        elif piece=='K':\n            ok=max(abs(tf-f),abs(tr-r))==1\n        else:\n            df,dr=tf-f,tr-r\n            orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0\n            ok=(piece=='R' and orth) or (piece=='B' and diag) or (piece=='Q' and (orth or diag))\n            if ok:\n                sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)\n                cf,cr=f+sf,r+sr\n                while (cf,cr)!=(tf,tr):\n                    if n(cf,cr) in b: ok=False\n                    cf+=sf; cr+=sr\n        if ok and all(ch==q[0] for ch in dis):\n            cands.append(q)\n    if len(cands)==1: return cands[0]\n    return 'ambiguous' if cands else 'illegal'\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('mate suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qf7#', 'white': True}, 'h5'),\n  ('check suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qe5+', 'white': True},\n   'h5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('quiet move onto own',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'P', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('capture with x',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nxf3', 'white': True}, 'g1'),\n  ('black double push', {'board': {'d7': 'p', 'e1': 'K', 'e8': 'k'}, 'san': 'd5', 'white': False},\n   'd7'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('black double push', {'board': {'d7': 'p', 'e1': 'K', 'e8': 'k'}, 'san': 'd5', 'white': False},\n   'd7'),\n  ('white double push', {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k'}, 'san': 'e4', 'white': True},\n   'e2'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4'),\n  ('backward pawn capture',\n   {'board': {'d3': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd3', 'white': True},\n   'illegal'),\n  ('black pawn capture',\n   {'board': {'d4': 'P', 'e1': 'K', 'e5': 'p', 'e8': 'k'}, 'san': 'exd4', 'white': False}, 'e5')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4'),\n  ('black pawn capture',\n   {'board': {'d4': 'P', 'e1': 'K', 'e5': 'p', 'e8': 'k'}, 'san': 'exd4', 'white': False}, 'e5'),\n  ('rook blocked candidate',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'san': 'Rd1', 'white': True},\n   'h1'),\n  ('bishop simple', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'san': 'Bg5', 'white': True},\n   'c1')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('mate suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qf7#', 'white': True}, 'h5'),\n  ('check suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qe5+', 'white': True},\n   'h5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, 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":"dfb6424c8d9c1fd49f0b5ed8b2ebeec25c93be7a077b57b8dbbbed1ac39dd2ec","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    b=x['board']; white=x['white']; s=x['san'].rstrip('+#')\n    def c(q): return ord(q[0])-97,int(q[1])-1\n    def n(f,r): return chr(97+f)+str(r+1)\n    piece=s[0] if s[0] in 'NBRQK' else 'P'\n    body=s[1:] if piece!='P' else s\n    capture='x' in body\n    body=body.replace('x','')\n    to=body[-2:]; dis=body[:-2]\n    tf,tr=c(to)\n    occ=b.get(to)\n    if capture and (occ is None or occ.isupper()==white): return 'illegal'\n    if not capture and occ is not None: return 'illegal'\n    letter=piece if white else piece.lower()\n    cands=[]\n    for q,v in b.items():\n        if v!=letter: continue\n        f,r=c(q)\n        if piece=='P':\n            d=1 if white else -1\n            if capture:\n                ok=abs(tf-f)==1 and tr-r==d\n            else:\n                ok=tf==f and (tr-r==d or (tr-r==2*d and r==(1 if white else 6) and n(f,r+d) not in b))\n        elif piece=='N':\n            ok=(abs(tf-f),abs(tr-r)) in ((1,2),(2,1))\n        elif piece=='K':\n            ok=max(abs(tf-f),abs(tr-r))==1\n        else:\n            df,dr=tf-f,tr-r\n            orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0\n            ok=(piece=='R' and orth) or (piece=='B' and diag) or (piece=='Q' and (orth or diag))\n            if ok:\n                sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)\n                cf,cr=f+sf,r+sr\n                while (cf,cr)!=(tf,tr):\n                    if n(cf,cr) in b: ok=False\n                    cf+=sf; cr+=sr\n        if ok and all((ch==q[0]) if ch.isalpha() else (ch==q[1]) for ch in dis):\n            cands.append(q)\n    if len(cands)==1: return cands[0]\n    return 'ambiguous' if cands else 'illegal'\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('mate suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qf7#', 'white': True}, 'h5'),\n  ('check suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qe5+', 'white': True},\n   'h5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('quiet move onto own',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'P', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('capture with x',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nxf3', 'white': True}, 'g1'),\n  ('black double push', {'board': {'d7': 'p', 'e1': 'K', 'e8': 'k'}, 'san': 'd5', 'white': False},\n   'd7'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('black double push', {'board': {'d7': 'p', 'e1': 'K', 'e8': 'k'}, 'san': 'd5', 'white': False},\n   'd7'),\n  ('white double push', {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k'}, 'san': 'e4', 'white': True},\n   'e2'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4'),\n  ('backward pawn capture',\n   {'board': {'d3': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd3', 'white': True},\n   'illegal'),\n  ('black pawn capture',\n   {'board': {'d4': 'P', 'e1': 'K', 'e5': 'p', 'e8': 'k'}, 'san': 'exd4', 'white': False}, 'e5')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4'),\n  ('black pawn capture',\n   {'board': {'d4': 'P', 'e1': 'K', 'e5': 'p', 'e8': 'k'}, 'san': 'exd4', 'white': False}, 'e5'),\n  ('rook blocked candidate',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'san': 'Rd1', 'white': True},\n   'h1'),\n  ('bishop simple', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'san': 'Bg5', 'white': True},\n   'c1')],\n [('knight file disambiguation',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nbd2', 'white': True}, 'b1'),\n  ('knight ambiguous',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'san': 'Nd2', 'white': True},\n   'ambiguous'),\n  ('rook rank disambiguation',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R1a3', 'white': True}, 'a1'),\n  ('rook rank disambiguation upper',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'san': 'R5a3', 'white': True}, 'a5'),\n  ('mate suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qf7#', 'white': True}, 'h5'),\n  ('check suffix', {'board': {'e1': 'K', 'e8': 'k', 'h5': 'Q'}, 'san': 'Qe5+', 'white': True},\n   'h5'),\n  ('quiet move onto enemy',\n   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'}, 'san': 'Nf3', 'white': True},\n   'illegal'),\n  ('pawn capture file',\n   {'board': {'c4': 'P', 'd5': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'san': 'exd5', 'white': True},\n   'e4')]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, 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 toy model with an explicitly stated contract; boards are {square: piece} with white upper-case and black lower-case pieces; no claim of full FIDE Laws conformance. 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-chess_move_legality-san-origin-resolution-disambiguator-matching","generated_at":"2026-09-29T14:50:13.995630+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"PGN import and move entry depend on resolving SAN to exactly one move.","repair":"Letters filter by file and digits filter by rank.","root_cause":"Every disambiguation character is matched against the origin file.","sha256":"b9aa5a088e239247a082596bb0cf43331d5e8c900f4edc9f3613f7a9b65ce2ab","title":"Rank disambiguator compared with the file letter · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":40.437,"exit_code":1,"observations":[{"actual":"ambiguous","check":"knight file disambiguation","expected":"b1","passed":false},{"actual":"ambiguous","check":"knight ambiguous","expected":"ambiguous","passed":true},{"actual":"a1","check":"rook rank disambiguation","expected":"a1","passed":true},{"actual":"a5","check":"rook rank disambiguation upper","expected":"a5","passed":true},{"actual":"h5","check":"mate suffix","expected":"h5","passed":true},{"actual":"h5","check":"check suffix","expected":"h5","passed":true},{"actual":"illegal","check":"quiet move onto enemy","expected":"illegal","passed":true},{"actual":"ambiguous","check":"pawn capture file","expected":"e4","passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"knight file disambiguation\", \"actual\": \"ambiguous\", \"expected\": \"b1\", \"passed\": false}, {\"check\": \"knight ambiguous\", \"actual\": \"ambiguous\", \"expected\": \"ambiguous\", \"passed\": true}, {\"check\": \"rook rank disambiguation\", \"actual\": \"a1\", \"expected\": \"a1\", \"passed\": true}, {\"check\": \"rook rank disambiguation upper\", \"actual\": \"a5\", \"expected\": \"a5\", \"passed\": true}, {\"check\": \"mate suffix\", \"actual\": \"h5\", \"expected\": \"h5\", \"passed\": true}, {\"check\": \"check suffix\", \"actual\": \"h5\", \"expected\": \"h5\", \"passed\": true}, {\"check\": \"quiet move onto enemy\", \"actual\": \"illegal\", \"expected\": \"illegal\", \"passed\": true}, {\"check\": \"pawn capture file\", \"actual\": \"ambiguous\", \"expected\": \"e4\", \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":42.069,"exit_code":1,"observations":[{"actual":"b1","check":"knight file disambiguation","expected":"b1","passed":true},{"actual":"ambiguous","check":"knight ambiguous","expected":"ambiguous","passed":true},{"actual":"illegal","check":"rook rank disambiguation","expected":"a1","passed":false},{"actual":"illegal","check":"rook rank disambiguation upper","expected":"a5","passed":false},{"actual":"h5","check":"mate suffix","expected":"h5","passed":true},{"actual":"h5","check":"check suffix","expected":"h5","passed":true},{"actual":"illegal","check":"quiet move onto enemy","expected":"illegal","passed":true},{"actual":"e4","check":"pawn capture file","expected":"e4","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"knight file disambiguation\", \"actual\": \"b1\", \"expected\": \"b1\", \"passed\": true}, {\"check\": \"knight ambiguous\", \"actual\": \"ambiguous\", \"expected\": \"ambiguous\", \"passed\": true}, {\"check\": \"rook rank disambiguation\", \"actual\": \"illegal\", \"expected\": \"a1\", \"passed\": false}, {\"check\": \"rook rank disambiguation upper\", \"actual\": \"illegal\", \"expected\": \"a5\", \"passed\": false}, {\"check\": \"mate suffix\", \"actual\": \"h5\", \"expected\": \"h5\", \"passed\": true}, {\"check\": \"check suffix\", \"actual\": \"h5\", \"expected\": \"h5\", \"passed\": true}, {\"check\": \"quiet move onto enemy\", \"actual\": \"illegal\", \"expected\": \"illegal\", \"passed\": true}, {\"check\": \"pawn capture file\", \"actual\": \"e4\", \"expected\": \"e4\", \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":42.399,"exit_code":0,"observations":[{"actual":"b1","check":"knight file disambiguation","expected":"b1","passed":true},{"actual":"ambiguous","check":"knight ambiguous","expected":"ambiguous","passed":true},{"actual":"a1","check":"rook rank disambiguation","expected":"a1","passed":true},{"actual":"a5","check":"rook rank disambiguation upper","expected":"a5","passed":true},{"actual":"h5","check":"mate suffix","expected":"h5","passed":true},{"actual":"h5","check":"check suffix","expected":"h5","passed":true},{"actual":"illegal","check":"quiet move onto enemy","expected":"illegal","passed":true},{"actual":"e4","check":"pawn capture file","expected":"e4","passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"knight file disambiguation\", \"actual\": \"b1\", \"expected\": \"b1\", \"passed\": true}, {\"check\": \"knight ambiguous\", \"actual\": \"ambiguous\", \"expected\": \"ambiguous\", \"passed\": true}, {\"check\": \"rook rank disambiguation\", \"actual\": \"a1\", \"expected\": \"a1\", \"passed\": true}, {\"check\": \"rook rank disambiguation upper\", \"actual\": \"a5\", \"expected\": \"a5\", \"passed\": true}, {\"check\": \"mate suffix\", \"actual\": \"h5\", \"expected\": \"h5\", \"passed\": true}, {\"check\": \"check suffix\", \"actual\": \"h5\", \"expected\": \"h5\", \"passed\": true}, {\"check\": \"quiet move onto enemy\", \"actual\": \"illegal\", \"expected\": \"illegal\", \"passed\": true}, {\"check\": \"pawn capture file\", \"actual\": \"e4\", \"expected\": \"e4\", \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}