FAILURE MAP
← Case archive

FA-96771 / Phone number formatting / Open access

Pattern-driven phone input mask: the literal buffer is never cleared · case 01

Every digit is preceded by all literals seen so far: "(5(55(555) ...".

Verified by executionVariant 1 · 9 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The pending literal buffer is not emptied after being written.

VERIFIED REPAIR

Clear the buffer after writing it in front of a digit.

Unsuccessful approach: Keeping the last buffered character repeats it before every digit.

Case contract

Input [digits, pattern]. Each X consumes the next digit; "\" makes the next pattern character a literal; other characters are literals. Literals are buffered and written only in front of the next digit, so a partial input never ends in a literal; when the whole pattern was consumed the trailing literals are written too. More digits than X slots returns None.

Why this case matters

Input masks drive what users see while typing; stray punctuation, lost literals or silently dropped digits produce numbers that differ from what was typed.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    digits, pattern = x
    out, i, k, pend = [], 0, 0, ''
    while k < len(pattern):
        ch = pattern[k]
        if ch == '\\' and k + 1 < len(pattern):
            pend += pattern[k + 1]
            k += 2
            continue
        if ch == 'X':
            if i >= len(digits):
                break
            out.append(pend + digits[i])
            i += 1
        else:
            pend += ch
        k += 1
    if i < len(digits):
        return None
    if k >= len(pattern):
        out.append(pend)
    return ''.join(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['complete ten digits', ['5550113456', '(XXX) XXX-XXXX'], '(555) 011-3456'], ['three digits keep the bracket pending', ['555', '(XXX) XXX-XXXX'], '(555'], ['six digits', ['555011', '(XXX) XXX-XXXX'], '(555) 011'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['555', '(XXX)'], '(555)'], ['escaped letter X', ['5550', 'E\\XT XXXX'], 'EXT 5550'], ['one digit too many', ['55501134561', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['5550113456', 'XX XX XX XX XX'], '55 50 11 34 56'], ['pairs pattern partial', ['5550', 'XX XX XX XX XX'], '55 50']], [['complete ten digits', ['6550123456', '(XXX) XXX-XXXX'], '(655) 012-3456'], ['three digits keep the bracket pending', ['655', '(XXX) XXX-XXXX'], '(655'], ['six digits', ['655012', '(XXX) XXX-XXXX'], '(655) 012'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['655', '(XXX)'], '(655)'], ['escaped letter X', ['6550', 'E\\XT XXXX'], 'EXT 6550'], ['one digit too many', ['65501234562', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['6550123456', 'XX XX XX XX XX'], '65 50 12 34 56'], ['pairs pattern partial', ['6550', 'XX XX XX XX XX'], '65 50']], [['complete ten digits', ['7550133456', '(XXX) XXX-XXXX'], '(755) 013-3456'], ['three digits keep the bracket pending', ['755', '(XXX) XXX-XXXX'], '(755'], ['six digits', ['755013', '(XXX) XXX-XXXX'], '(755) 013'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['755', '(XXX)'], '(755)'], ['escaped letter X', ['7550', 'E\\XT XXXX'], 'EXT 7550'], ['one digit too many', ['75501334563', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['7550133456', 'XX XX XX XX XX'], '75 50 13 34 56'], ['pairs pattern partial', ['7550', 'XX XX XX XX XX'], '75 50']], [['complete ten digits', ['8550143456', '(XXX) XXX-XXXX'], '(855) 014-3456'], ['three digits keep the bracket pending', ['855', '(XXX) XXX-XXXX'], '(855'], ['six digits', ['855014', '(XXX) XXX-XXXX'], '(855) 014'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['855', '(XXX)'], '(855)'], ['escaped letter X', ['8550', 'E\\XT XXXX'], 'EXT 8550'], ['one digit too many', ['85501434564', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['8550143456', 'XX XX XX XX XX'], '85 50 14 34 56'], ['pairs pattern partial', ['8550', 'XX XX XX XX XX'], '85 50']], [['complete ten digits', ['9550153456', '(XXX) XXX-XXXX'], '(955) 015-3456'], ['three digits keep the bracket pending', ['955', '(XXX) XXX-XXXX'], '(955'], ['six digits', ['955015', '(XXX) XXX-XXXX'], '(955) 015'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['955', '(XXX)'], '(955)'], ['escaped letter X', ['9550', 'E\\XT XXXX'], 'EXT 9550'], ['one digit too many', ['95501534565', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['9550153456', 'XX XX XX XX XX'], '95 50 15 34 56'], ['pairs pattern partial', ['9550', 'XX XX XX XX XX'], '95 50']]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
complete ten digits(5(5(5() 0() 1() 1() -3() -4() -5() -6() -(555) 011-3456Failed
three digits keep the bracket pending(5(5(5(555Failed
six digits(5(5(5() 0() 1() 1(555) 011Failed
nothing typedPassed
pattern ending in a literal(5(5(5()(555)Failed
escaped letter XEXT 5EXT 5EXT 5EXT 0EXT EXT 5550Failed
one digit too manyNoneNonePassed
pairs pattern complete55 5 0 1 1 3 4 5 6 55 50 11 34 56Failed
pairs pattern partial55 5 055 50Failed

SHA-256 / 759c10b26bd118bfe8373c2a4ea7805984dde12f171d658db78e53f99b7345cc

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    digits, pattern = x
    out, i, k, pend = [], 0, 0, ''
    while k < len(pattern):
        ch = pattern[k]
        if ch == '\\' and k + 1 < len(pattern):
            pend += pattern[k + 1]
            k += 2
            continue
        if ch == 'X':
            if i >= len(digits):
                break
            out.append(pend + digits[i])
            pend = pend[-1:]
            i += 1
        else:
            pend += ch
        k += 1
    if i < len(digits):
        return None
    if k >= len(pattern):
        out.append(pend)
    return ''.join(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['complete ten digits', ['5550113456', '(XXX) XXX-XXXX'], '(555) 011-3456'], ['three digits keep the bracket pending', ['555', '(XXX) XXX-XXXX'], '(555'], ['six digits', ['555011', '(XXX) XXX-XXXX'], '(555) 011'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['555', '(XXX)'], '(555)'], ['escaped letter X', ['5550', 'E\\XT XXXX'], 'EXT 5550'], ['one digit too many', ['55501134561', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['5550113456', 'XX XX XX XX XX'], '55 50 11 34 56'], ['pairs pattern partial', ['5550', 'XX XX XX XX XX'], '55 50']], [['complete ten digits', ['6550123456', '(XXX) XXX-XXXX'], '(655) 012-3456'], ['three digits keep the bracket pending', ['655', '(XXX) XXX-XXXX'], '(655'], ['six digits', ['655012', '(XXX) XXX-XXXX'], '(655) 012'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['655', '(XXX)'], '(655)'], ['escaped letter X', ['6550', 'E\\XT XXXX'], 'EXT 6550'], ['one digit too many', ['65501234562', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['6550123456', 'XX XX XX XX XX'], '65 50 12 34 56'], ['pairs pattern partial', ['6550', 'XX XX XX XX XX'], '65 50']], [['complete ten digits', ['7550133456', '(XXX) XXX-XXXX'], '(755) 013-3456'], ['three digits keep the bracket pending', ['755', '(XXX) XXX-XXXX'], '(755'], ['six digits', ['755013', '(XXX) XXX-XXXX'], '(755) 013'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['755', '(XXX)'], '(755)'], ['escaped letter X', ['7550', 'E\\XT XXXX'], 'EXT 7550'], ['one digit too many', ['75501334563', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['7550133456', 'XX XX XX XX XX'], '75 50 13 34 56'], ['pairs pattern partial', ['7550', 'XX XX XX XX XX'], '75 50']], [['complete ten digits', ['8550143456', '(XXX) XXX-XXXX'], '(855) 014-3456'], ['three digits keep the bracket pending', ['855', '(XXX) XXX-XXXX'], '(855'], ['six digits', ['855014', '(XXX) XXX-XXXX'], '(855) 014'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['855', '(XXX)'], '(855)'], ['escaped letter X', ['8550', 'E\\XT XXXX'], 'EXT 8550'], ['one digit too many', ['85501434564', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['8550143456', 'XX XX XX XX XX'], '85 50 14 34 56'], ['pairs pattern partial', ['8550', 'XX XX XX XX XX'], '85 50']], [['complete ten digits', ['9550153456', '(XXX) XXX-XXXX'], '(955) 015-3456'], ['three digits keep the bracket pending', ['955', '(XXX) XXX-XXXX'], '(955'], ['six digits', ['955015', '(XXX) XXX-XXXX'], '(955) 015'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['955', '(XXX)'], '(955)'], ['escaped letter X', ['9550', 'E\\XT XXXX'], 'EXT 9550'], ['one digit too many', ['95501534565', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['9550153456', 'XX XX XX XX XX'], '95 50 15 34 56'], ['pairs pattern partial', ['9550', 'XX XX XX XX XX'], '95 50']]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
complete ten digits(5(5(5() 0 1 1 -3-4-5-6-(555) 011-3456Failed
three digits keep the bracket pending(5(5(5(555Failed
six digits(5(5(5() 0 1 1(555) 011Failed
nothing typedPassed
pattern ending in a literal(5(5(5()(555)Failed
escaped letter XEXT 5 5 5 0 EXT 5550Failed
one digit too manyNoneNonePassed
pairs pattern complete55 5 0 1 1 3 4 5 6 55 50 11 34 56Failed
pairs pattern partial55 5 055 50Failed

SHA-256 / e426ac3f2c2417cefb6ce41f93c622705e2d321de9d977cc53f033f4523053f8

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    digits, pattern = x
    out, i, k, pend = [], 0, 0, ''
    while k < len(pattern):
        ch = pattern[k]
        if ch == '\\' and k + 1 < len(pattern):
            pend += pattern[k + 1]
            k += 2
            continue
        if ch == 'X':
            if i >= len(digits):
                break
            out.append(pend + digits[i])
            pend = ''
            i += 1
        else:
            pend += ch
        k += 1
    if i < len(digits):
        return None
    if k >= len(pattern):
        out.append(pend)
    return ''.join(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['complete ten digits', ['5550113456', '(XXX) XXX-XXXX'], '(555) 011-3456'], ['three digits keep the bracket pending', ['555', '(XXX) XXX-XXXX'], '(555'], ['six digits', ['555011', '(XXX) XXX-XXXX'], '(555) 011'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['555', '(XXX)'], '(555)'], ['escaped letter X', ['5550', 'E\\XT XXXX'], 'EXT 5550'], ['one digit too many', ['55501134561', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['5550113456', 'XX XX XX XX XX'], '55 50 11 34 56'], ['pairs pattern partial', ['5550', 'XX XX XX XX XX'], '55 50']], [['complete ten digits', ['6550123456', '(XXX) XXX-XXXX'], '(655) 012-3456'], ['three digits keep the bracket pending', ['655', '(XXX) XXX-XXXX'], '(655'], ['six digits', ['655012', '(XXX) XXX-XXXX'], '(655) 012'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['655', '(XXX)'], '(655)'], ['escaped letter X', ['6550', 'E\\XT XXXX'], 'EXT 6550'], ['one digit too many', ['65501234562', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['6550123456', 'XX XX XX XX XX'], '65 50 12 34 56'], ['pairs pattern partial', ['6550', 'XX XX XX XX XX'], '65 50']], [['complete ten digits', ['7550133456', '(XXX) XXX-XXXX'], '(755) 013-3456'], ['three digits keep the bracket pending', ['755', '(XXX) XXX-XXXX'], '(755'], ['six digits', ['755013', '(XXX) XXX-XXXX'], '(755) 013'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['755', '(XXX)'], '(755)'], ['escaped letter X', ['7550', 'E\\XT XXXX'], 'EXT 7550'], ['one digit too many', ['75501334563', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['7550133456', 'XX XX XX XX XX'], '75 50 13 34 56'], ['pairs pattern partial', ['7550', 'XX XX XX XX XX'], '75 50']], [['complete ten digits', ['8550143456', '(XXX) XXX-XXXX'], '(855) 014-3456'], ['three digits keep the bracket pending', ['855', '(XXX) XXX-XXXX'], '(855'], ['six digits', ['855014', '(XXX) XXX-XXXX'], '(855) 014'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['855', '(XXX)'], '(855)'], ['escaped letter X', ['8550', 'E\\XT XXXX'], 'EXT 8550'], ['one digit too many', ['85501434564', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['8550143456', 'XX XX XX XX XX'], '85 50 14 34 56'], ['pairs pattern partial', ['8550', 'XX XX XX XX XX'], '85 50']], [['complete ten digits', ['9550153456', '(XXX) XXX-XXXX'], '(955) 015-3456'], ['three digits keep the bracket pending', ['955', '(XXX) XXX-XXXX'], '(955'], ['six digits', ['955015', '(XXX) XXX-XXXX'], '(955) 015'], ['nothing typed', ['', '(XXX) XXX-XXXX'], ''], ['pattern ending in a literal', ['955', '(XXX)'], '(955)'], ['escaped letter X', ['9550', 'E\\XT XXXX'], 'EXT 9550'], ['one digit too many', ['95501534565', '(XXX) XXX-XXXX'], None], ['pairs pattern complete', ['9550153456', 'XX XX XX XX XX'], '95 50 15 34 56'], ['pairs pattern partial', ['9550', 'XX XX XX XX XX'], '95 50']]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
complete ten digits(555) 011-3456(555) 011-3456Passed
three digits keep the bracket pending(555(555Passed
six digits(555) 011(555) 011Passed
nothing typedPassed
pattern ending in a literal(555)(555)Passed
escaped letter XEXT 5550EXT 5550Passed
one digit too manyNoneNonePassed
pairs pattern complete55 50 11 34 5655 50 11 34 56Passed
pairs pattern partial55 5055 50Passed

SHA-256 / f8306aef227a4142d80f6d1a1338405bd8b2b733653b7a052c0afca57c97078d

Verification & scope

A deterministic toy contract over synthetic, obviously fictitious telephone numbers and toy country tables. The rules are stipulated for this model only and make no claim of conformance with any numbering plan or telecommunications standard. 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.

Observations recorded using Python 3.12.14 at 2026-09-29T14:52:25.741009+00:00.

Case digest / 989b56437cdcad8b8c784daaa867cebf9c12f30d0c9fb86c2fc05218db643ad0