FA-96756 / Phone number formatting / Open access
Pattern-driven phone input mask: escaped X consumes a digit · case 01
"E\XT XXXX" shows a backslash and uses the first digit as the X.
ROOT CAUSE
Backslash escapes are not recognized.
VERIFIED REPAIR
Treat the character after a backslash as a literal.
Unsuccessful approach: Recognizing the escape but keeping the backslash prints "E\XT".
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 == '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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| complete ten digits | (555) 011-3456 | (555) 011-3456 | Passed |
| three digits keep the bracket pending | (555 | (555 | Passed |
| six digits | (555) 011 | (555) 011 | Passed |
| nothing typed | | | Passed |
| pattern ending in a literal | (555) | (555) | Passed |
| escaped letter X | E\5T 550 | EXT 5550 | Failed |
| one digit too many | None | None | Passed |
| pairs pattern complete | 55 50 11 34 56 | 55 50 11 34 56 | Passed |
| pairs pattern partial | 55 50 | 55 50 | Passed |
SHA-256 / 69e34ebfc386924ae1b0c27243ecf7436ecba81217c1aa8d7ff0e30cb9a74ed4
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 = ''
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| complete ten digits | (555) 011-3456 | (555) 011-3456 | Passed |
| three digits keep the bracket pending | (555 | (555 | Passed |
| six digits | (555) 011 | (555) 011 | Passed |
| nothing typed | | | Passed |
| pattern ending in a literal | (555) | (555) | Passed |
| escaped letter X | E\XT 5550 | EXT 5550 | Failed |
| one digit too many | None | None | Passed |
| pairs pattern complete | 55 50 11 34 56 | 55 50 11 34 56 | Passed |
| pairs pattern partial | 55 50 | 55 50 | Passed |
SHA-256 / 5e74a804f336545daab8d7615f544929d0629a80fadd936a87c25cec800f3777
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| complete ten digits | (555) 011-3456 | (555) 011-3456 | Passed |
| three digits keep the bracket pending | (555 | (555 | Passed |
| six digits | (555) 011 | (555) 011 | Passed |
| nothing typed | | | Passed |
| pattern ending in a literal | (555) | (555) | Passed |
| escaped letter X | EXT 5550 | EXT 5550 | Passed |
| one digit too many | None | None | Passed |
| pairs pattern complete | 55 50 11 34 56 | 55 50 11 34 56 | Passed |
| pairs pattern partial | 55 50 | 55 50 | Passed |
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.650357+00:00.
Case digest / bd8418b8962182b0131c4c01ccb21c8b12ffd6d3207ea41d620b4b40e32d7064