FA-22771 / Autocomplete interactions / Open access
Autocomplete form binding: multi-value autocomplete joins identifiers into one ambiguous value · case 01
The many completion transition produces an incorrect observable state.
ROOT CAUSE
At form-binding/many, the implementation evaluates `[[d['name'],','.join(d['values'])]]` instead of preserving the specified completion transition.
VERIFIED REPAIR
Implement the many contract using `[[d['name'],x] for x in d['values']]`.
Unsuccessful approach: The attempted repair uses `[[d['name'],d['values']]]`, which still violates a normal or boundary completion fixture.
Case contract
Form submission serializes committed suggestion identifiers separately from visible draft text. Required checks apply to committed values, an empty-string identifier is present, disabled fields are omitted, and reset restores the initial identity and label together. Multi-value fields preserve separate values.
Why this case matters
Autocomplete couples draft text, suggestion identity and asynchronous presentation; this bounded lifecycle model isolates one observable interaction defect.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(event, d):
if event == 'serialize': return d['value']
if event == 'present': return d['value'] is not None
if event == 'disabled': return [] if d['disabled'] else [[d['name'],d['value']]]
if event == 'reset-id': return d['initial']
if event == 'reset-label': return d['initial_label']
if event == 'reset-baseline': return [d['initial'],d['initial_label']]
if event == 'many': return [[d['name'],','.join(d['values'])]]
if event == 'dirty': return d['draft']!=d['label']
if event == 'display-field': return d['name']
if event == 'reset-draft': return {'draft':d['initial_label'],'active':None}
return {'unchanged': True}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
normal = {'value':'p1','label':'Pear','draft':'peach','initial':'p0','initial_label':'Plum','name':'fruit','disabled':True,'required':True,'values':['a','b'],'epoch':N}
boundary = {'value':'','label':'','draft':'x','initial':None,'initial_label':'','name':'fruit','disabled':False,'required':True,'values':[],'epoch':N}
check('normal serialize', solve('serialize', normal), 'p1')
check('boundary serialize', solve('serialize', boundary), '')
check('normal present', solve('present', normal), True)
check('boundary present', solve('present', boundary), True)
check('normal disabled', solve('disabled', normal), [])
check('boundary disabled', solve('disabled', boundary), [['fruit','']])
check('normal reset-id', solve('reset-id', normal), 'p0')
check('boundary reset-id', solve('reset-id', boundary), None)
check('normal reset-label', solve('reset-label', normal), 'Plum')
check('boundary reset-label', solve('reset-label', boundary), '')
check('normal reset-baseline', solve('reset-baseline', normal), ['p0','Plum'])
check('boundary reset-baseline', solve('reset-baseline', boundary), [None,''])
check('normal many', solve('many', normal), [['fruit','a'],['fruit','b']])
check('boundary many', solve('many', boundary), [])
check('normal dirty', solve('dirty', normal), True)
check('boundary dirty', solve('dirty', boundary), True)
check('normal display-field', solve('display-field', normal), 'fruit')
check('boundary display-field', solve('display-field', boundary), 'fruit')
check('normal reset-draft', solve('reset-draft', normal), {'draft':'Plum','active':None})
check('boundary reset-draft', solve('reset-draft', boundary), {'draft':'','active':None})
variant = dict(normal, **{'value':'id'+str(N)})
check('variant query or selection payload', solve('serialize', variant), 'id'+str(N))
check('unknown completion event', solve('unrecognized', normal), {'unchanged': True})
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 |
|---|---|---|---|
| normal serialize | p1 | p1 | Passed |
| boundary serialize | | | Passed |
| normal present | True | True | Passed |
| boundary present | True | True | Passed |
| normal disabled | [] | [] | Passed |
| boundary disabled | [['fruit', '']] | [['fruit', '']] | Passed |
| normal reset-id | p0 | p0 | Passed |
| boundary reset-id | None | None | Passed |
| normal reset-label | Plum | Plum | Passed |
| boundary reset-label | | | Passed |
| normal reset-baseline | ['p0', 'Plum'] | ['p0', 'Plum'] | Passed |
| boundary reset-baseline | [None, ''] | [None, ''] | Passed |
| normal many | [['fruit', 'a,b']] | [['fruit', 'a'], ['fruit', 'b']] | Failed |
| boundary many | [['fruit', '']] | [] | Failed |
| normal dirty | True | True | Passed |
| boundary dirty | True | True | Passed |
| normal display-field | fruit | fruit | Passed |
| boundary display-field | fruit | fruit | Passed |
| normal reset-draft | {'active': None, 'draft': 'Plum'} | {'active': None, 'draft': 'Plum'} | Passed |
| boundary reset-draft | {'active': None, 'draft': ''} | {'active': None, 'draft': ''} | Passed |
| variant query or selection payload | id1 | id1 | Passed |
| unknown completion event | {'unchanged': True} | {'unchanged': True} | Passed |
SHA-256 / a06a3394d8fa0cdafab7d5d84c6551dc9dd09a4b49eb8aa8ea449cd768f1ace7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(event, d):
if event == 'serialize': return d['value']
if event == 'present': return d['value'] is not None
if event == 'disabled': return [] if d['disabled'] else [[d['name'],d['value']]]
if event == 'reset-id': return d['initial']
if event == 'reset-label': return d['initial_label']
if event == 'reset-baseline': return [d['initial'],d['initial_label']]
if event == 'many': return [[d['name'],d['values']]]
if event == 'dirty': return d['draft']!=d['label']
if event == 'display-field': return d['name']
if event == 'reset-draft': return {'draft':d['initial_label'],'active':None}
return {'unchanged': True}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
normal = {'value':'p1','label':'Pear','draft':'peach','initial':'p0','initial_label':'Plum','name':'fruit','disabled':True,'required':True,'values':['a','b'],'epoch':N}
boundary = {'value':'','label':'','draft':'x','initial':None,'initial_label':'','name':'fruit','disabled':False,'required':True,'values':[],'epoch':N}
check('normal serialize', solve('serialize', normal), 'p1')
check('boundary serialize', solve('serialize', boundary), '')
check('normal present', solve('present', normal), True)
check('boundary present', solve('present', boundary), True)
check('normal disabled', solve('disabled', normal), [])
check('boundary disabled', solve('disabled', boundary), [['fruit','']])
check('normal reset-id', solve('reset-id', normal), 'p0')
check('boundary reset-id', solve('reset-id', boundary), None)
check('normal reset-label', solve('reset-label', normal), 'Plum')
check('boundary reset-label', solve('reset-label', boundary), '')
check('normal reset-baseline', solve('reset-baseline', normal), ['p0','Plum'])
check('boundary reset-baseline', solve('reset-baseline', boundary), [None,''])
check('normal many', solve('many', normal), [['fruit','a'],['fruit','b']])
check('boundary many', solve('many', boundary), [])
check('normal dirty', solve('dirty', normal), True)
check('boundary dirty', solve('dirty', boundary), True)
check('normal display-field', solve('display-field', normal), 'fruit')
check('boundary display-field', solve('display-field', boundary), 'fruit')
check('normal reset-draft', solve('reset-draft', normal), {'draft':'Plum','active':None})
check('boundary reset-draft', solve('reset-draft', boundary), {'draft':'','active':None})
variant = dict(normal, **{'value':'id'+str(N)})
check('variant query or selection payload', solve('serialize', variant), 'id'+str(N))
check('unknown completion event', solve('unrecognized', normal), {'unchanged': True})
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 |
|---|---|---|---|
| normal serialize | p1 | p1 | Passed |
| boundary serialize | | | Passed |
| normal present | True | True | Passed |
| boundary present | True | True | Passed |
| normal disabled | [] | [] | Passed |
| boundary disabled | [['fruit', '']] | [['fruit', '']] | Passed |
| normal reset-id | p0 | p0 | Passed |
| boundary reset-id | None | None | Passed |
| normal reset-label | Plum | Plum | Passed |
| boundary reset-label | | | Passed |
| normal reset-baseline | ['p0', 'Plum'] | ['p0', 'Plum'] | Passed |
| boundary reset-baseline | [None, ''] | [None, ''] | Passed |
| normal many | [['fruit', ['a', 'b']]] | [['fruit', 'a'], ['fruit', 'b']] | Failed |
| boundary many | [['fruit', []]] | [] | Failed |
| normal dirty | True | True | Passed |
| boundary dirty | True | True | Passed |
| normal display-field | fruit | fruit | Passed |
| boundary display-field | fruit | fruit | Passed |
| normal reset-draft | {'active': None, 'draft': 'Plum'} | {'active': None, 'draft': 'Plum'} | Passed |
| boundary reset-draft | {'active': None, 'draft': ''} | {'active': None, 'draft': ''} | Passed |
| variant query or selection payload | id1 | id1 | Passed |
| unknown completion event | {'unchanged': True} | {'unchanged': True} | Passed |
SHA-256 / d30b20218893d1eb5b4797c9e39cd9743af4090dbd2655baadcaaac6e89e26ef
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(event, d):
if event == 'serialize': return d['value']
if event == 'present': return d['value'] is not None
if event == 'disabled': return [] if d['disabled'] else [[d['name'],d['value']]]
if event == 'reset-id': return d['initial']
if event == 'reset-label': return d['initial_label']
if event == 'reset-baseline': return [d['initial'],d['initial_label']]
if event == 'many': return [[d['name'],x] for x in d['values']]
if event == 'dirty': return d['draft']!=d['label']
if event == 'display-field': return d['name']
if event == 'reset-draft': return {'draft':d['initial_label'],'active':None}
return {'unchanged': True}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
normal = {'value':'p1','label':'Pear','draft':'peach','initial':'p0','initial_label':'Plum','name':'fruit','disabled':True,'required':True,'values':['a','b'],'epoch':N}
boundary = {'value':'','label':'','draft':'x','initial':None,'initial_label':'','name':'fruit','disabled':False,'required':True,'values':[],'epoch':N}
check('normal serialize', solve('serialize', normal), 'p1')
check('boundary serialize', solve('serialize', boundary), '')
check('normal present', solve('present', normal), True)
check('boundary present', solve('present', boundary), True)
check('normal disabled', solve('disabled', normal), [])
check('boundary disabled', solve('disabled', boundary), [['fruit','']])
check('normal reset-id', solve('reset-id', normal), 'p0')
check('boundary reset-id', solve('reset-id', boundary), None)
check('normal reset-label', solve('reset-label', normal), 'Plum')
check('boundary reset-label', solve('reset-label', boundary), '')
check('normal reset-baseline', solve('reset-baseline', normal), ['p0','Plum'])
check('boundary reset-baseline', solve('reset-baseline', boundary), [None,''])
check('normal many', solve('many', normal), [['fruit','a'],['fruit','b']])
check('boundary many', solve('many', boundary), [])
check('normal dirty', solve('dirty', normal), True)
check('boundary dirty', solve('dirty', boundary), True)
check('normal display-field', solve('display-field', normal), 'fruit')
check('boundary display-field', solve('display-field', boundary), 'fruit')
check('normal reset-draft', solve('reset-draft', normal), {'draft':'Plum','active':None})
check('boundary reset-draft', solve('reset-draft', boundary), {'draft':'','active':None})
variant = dict(normal, **{'value':'id'+str(N)})
check('variant query or selection payload', solve('serialize', variant), 'id'+str(N))
check('unknown completion event', solve('unrecognized', normal), {'unchanged': True})
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 |
|---|---|---|---|
| normal serialize | p1 | p1 | Passed |
| boundary serialize | | | Passed |
| normal present | True | True | Passed |
| boundary present | True | True | Passed |
| normal disabled | [] | [] | Passed |
| boundary disabled | [['fruit', '']] | [['fruit', '']] | Passed |
| normal reset-id | p0 | p0 | Passed |
| boundary reset-id | None | None | Passed |
| normal reset-label | Plum | Plum | Passed |
| boundary reset-label | | | Passed |
| normal reset-baseline | ['p0', 'Plum'] | ['p0', 'Plum'] | Passed |
| boundary reset-baseline | [None, ''] | [None, ''] | Passed |
| normal many | [['fruit', 'a'], ['fruit', 'b']] | [['fruit', 'a'], ['fruit', 'b']] | Passed |
| boundary many | [] | [] | Passed |
| normal dirty | True | True | Passed |
| boundary dirty | True | True | Passed |
| normal display-field | fruit | fruit | Passed |
| boundary display-field | fruit | fruit | Passed |
| normal reset-draft | {'active': None, 'draft': 'Plum'} | {'active': None, 'draft': 'Plum'} | Passed |
| boundary reset-draft | {'active': None, 'draft': ''} | {'active': None, 'draft': ''} | Passed |
| variant query or selection payload | id1 | id1 | Passed |
| unknown completion event | {'unchanged': True} | {'unchanged': True} | Passed |
SHA-256 / 7b2e0111c24d33e8494a16d4f7b0a0783a354775d54d5ef60d60d650c8a24af4
Verification & scope
Stipulated deterministic widget transition model; inputs are validated snapshots. It does not model browser event dispatch, network transport, or linguistic standards. 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:40:41.562038+00:00.
Case digest / f90abcf65ff0f5fdb7be454bfdd181b8a9c8e2a7e9170cd2002f0dc21c3a03b3