FAILURE MAP
← Case archive

FA-38251 / Table interactions / Open access

Table cell render invalidation: cell error change · case 01

The table cell error change result violates the stipulated table cell render invalidation contract.

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

ROOT CAUSE

The cell error change decision uses 'False' instead of 'old_errors.get(cell)!=new_errors.get(cell)'.

VERIFIED REPAIR

Apply the complete cell error change rule: old_errors.get(cell)!=new_errors.get(cell).

Unsuccessful approach: The attempted repair 'bool(old_errors.get(cell))!=bool(new_errors.get(cell))' still loses a required part of the table contract.

Case contract

Table invalidation uses column field accessors and stable row IDs; repaint follows value, symmetric selection, error-text, width, stripe parity, or theme changes. Only wrapped cells remeasure on value/width changes, and added/removed row IDs drive mount/disposal.

Why this case matters

An offline table UI model isolates table cell render invalidation, including adversarial row/column relationships.

1 / The failure

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

N = 1
observations = []
def solve(old_rows, new_rows, columns, selected_before, selected_after, old_widths, new_widths, old_theme, new_theme, old_errors, new_errors):
    old={r['id']:r for r in old_rows}; new={r['id']:r for r in new_rows}
    old_order=[r['id'] for r in old_rows]; new_order=[r['id'] for r in new_rows]
    paint=[]; measure=[]
    for r in new_rows:
        key=r['id']
        for c in columns:
            cell=(key,c['id'])
            changed=key not in old or old[key].get(c['field'])!=r.get(c['field'])
            decor=(cell in selected_before)!=(cell in selected_after) or False
            layout=old_widths.get(c['id'])!=new_widths.get(c['id'])
            stripe=c.get('stripe',False) and (key not in old_order or old_order.index(key)%2!=new_order.index(key)%2)
            if changed or decor or layout or stripe or old_theme!=new_theme: paint.append(cell)
            if c.get('wrap',False) and (changed or layout): measure.append(cell)
    return {'paint':paint,'measure':measure,'removed':[k for k in old_order if k not in new],'added':[k for k in new_order if k not in old]}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':1+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 2:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':2+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 3:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':3+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 4:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':4+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 5:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':5+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

check('variant wrapping width invalidation', solve([{'id':'r','a':1}], [{'id':'r','a':1}], [{'id':'a','field':'a','wrap':True}], [], [], {'a':N}, {'a':3}, 'light', 'light', {}, {}), {'paint':[('r','a')] if N!=3 else [],'measure':[('r','a')] if N!=3 else [],'removed':[],'added':[]})
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
accessor value changes{'added': [], 'measure': [['a', 'display']], 'paint': [['a', 'display']], 'removed': []}{'added': [], 'measure': [['a', 'display']], 'paint': [['a', 'display']], 'removed': []}Passed
selection removed and added{'added': [], 'measure': [], 'paint': [['a', 'v'], ['b', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v'], ['b', 'v']], 'removed': []}Passed
error message changes{'added': [], 'measure': [], 'paint': [], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}Failed
width shrinks wrapping{'added': [], 'measure': [['a', 'v']], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [['a', 'v']], 'paint': [['a', 'v']], 'removed': []}Passed
theme-only repaint{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}Passed
parity and removals{'added': ['new'], 'measure': [], 'paint': [['b', 'v'], ['c', 'v'], ['new', 'v']], 'removed': ['gone']}{'added': ['new'], 'measure': [], 'paint': [['b', 'v'], ['c', 'v'], ['new', 'v']], 'removed': ['gone']}Passed
unchanged{'added': [], 'measure': [], 'paint': [], 'removed': []}{'added': [], 'measure': [], 'paint': [], 'removed': []}Passed
variant wrapping width invalidation{'added': [], 'measure': [['r', 'a']], 'paint': [['r', 'a']], 'removed': []}{'added': [], 'measure': [['r', 'a']], 'paint': [['r', 'a']], 'removed': []}Passed

SHA-256 / 40214f599aec0f1b784c79bb203cc07844a8617dc60048d3b83a91926e13352b

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(old_rows, new_rows, columns, selected_before, selected_after, old_widths, new_widths, old_theme, new_theme, old_errors, new_errors):
    old={r['id']:r for r in old_rows}; new={r['id']:r for r in new_rows}
    old_order=[r['id'] for r in old_rows]; new_order=[r['id'] for r in new_rows]
    paint=[]; measure=[]
    for r in new_rows:
        key=r['id']
        for c in columns:
            cell=(key,c['id'])
            changed=key not in old or old[key].get(c['field'])!=r.get(c['field'])
            decor=(cell in selected_before)!=(cell in selected_after) or bool(old_errors.get(cell))!=bool(new_errors.get(cell))
            layout=old_widths.get(c['id'])!=new_widths.get(c['id'])
            stripe=c.get('stripe',False) and (key not in old_order or old_order.index(key)%2!=new_order.index(key)%2)
            if changed or decor or layout or stripe or old_theme!=new_theme: paint.append(cell)
            if c.get('wrap',False) and (changed or layout): measure.append(cell)
    return {'paint':paint,'measure':measure,'removed':[k for k in old_order if k not in new],'added':[k for k in new_order if k not in old]}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':1+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 2:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':2+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 3:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':3+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 4:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':4+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 5:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':5+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

check('variant wrapping width invalidation', solve([{'id':'r','a':1}], [{'id':'r','a':1}], [{'id':'a','field':'a','wrap':True}], [], [], {'a':N}, {'a':3}, 'light', 'light', {}, {}), {'paint':[('r','a')] if N!=3 else [],'measure':[('r','a')] if N!=3 else [],'removed':[],'added':[]})
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
accessor value changes{'added': [], 'measure': [['a', 'display']], 'paint': [['a', 'display']], 'removed': []}{'added': [], 'measure': [['a', 'display']], 'paint': [['a', 'display']], 'removed': []}Passed
selection removed and added{'added': [], 'measure': [], 'paint': [['a', 'v'], ['b', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v'], ['b', 'v']], 'removed': []}Passed
error message changes{'added': [], 'measure': [], 'paint': [], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}Failed
width shrinks wrapping{'added': [], 'measure': [['a', 'v']], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [['a', 'v']], 'paint': [['a', 'v']], 'removed': []}Passed
theme-only repaint{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}Passed
parity and removals{'added': ['new'], 'measure': [], 'paint': [['b', 'v'], ['c', 'v'], ['new', 'v']], 'removed': ['gone']}{'added': ['new'], 'measure': [], 'paint': [['b', 'v'], ['c', 'v'], ['new', 'v']], 'removed': ['gone']}Passed
unchanged{'added': [], 'measure': [], 'paint': [], 'removed': []}{'added': [], 'measure': [], 'paint': [], 'removed': []}Passed
variant wrapping width invalidation{'added': [], 'measure': [['r', 'a']], 'paint': [['r', 'a']], 'removed': []}{'added': [], 'measure': [['r', 'a']], 'paint': [['r', 'a']], 'removed': []}Passed

SHA-256 / 643b93ecf1bb04ea6aea748663495ceda02176ef770a2f17966aa43ed1d0c6a3

3 / The verified repair

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

N = 1
observations = []
def solve(old_rows, new_rows, columns, selected_before, selected_after, old_widths, new_widths, old_theme, new_theme, old_errors, new_errors):
    old={r['id']:r for r in old_rows}; new={r['id']:r for r in new_rows}
    old_order=[r['id'] for r in old_rows]; new_order=[r['id'] for r in new_rows]
    paint=[]; measure=[]
    for r in new_rows:
        key=r['id']
        for c in columns:
            cell=(key,c['id'])
            changed=key not in old or old[key].get(c['field'])!=r.get(c['field'])
            decor=(cell in selected_before)!=(cell in selected_after) or old_errors.get(cell)!=new_errors.get(cell)
            layout=old_widths.get(c['id'])!=new_widths.get(c['id'])
            stripe=c.get('stripe',False) and (key not in old_order or old_order.index(key)%2!=new_order.index(key)%2)
            if changed or decor or layout or stripe or old_theme!=new_theme: paint.append(cell)
            if c.get('wrap',False) and (changed or layout): measure.append(cell)
    return {'paint':paint,'measure':measure,'removed':[k for k in old_order if k not in new],'added':[k for k in new_order if k not in old]}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':1+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 2:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':2+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 3:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':3+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 4:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':4+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

if N == 5:
    check('accessor value changes', solve([{'id':'a','amount':1,'note':'same'}], [{'id':'a','amount':5+2,'note':'same'}], [{'id':'display','field':'amount','wrap':True},{'id':'note','field':'note'}], [], [], {'display':8,'note':4}, {'display':8,'note':4}, 'light', 'light', {}, {}), {'paint': [('a', 'display')], 'measure': [('a', 'display')], 'removed': [], 'added': []})
    check('selection removed and added', solve([{'id':'a','v':1},{'id':'b','v':2}], [{'id':'a','v':1},{'id':'b','v':2}], [{'id':'v','field':'v','wrap':True}], [('a','v')], [('b','v')], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('a', 'v'), ('b', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('error message changes', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {('a','v'):'old'}, {('a','v'):'new'}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('width shrinks wrapping', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':8}, {'v':4}, 'light', 'light', {}, {}), {'paint': [('a', 'v')], 'measure': [('a', 'v')], 'removed': [], 'added': []})
    check('theme-only repaint', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v','wrap':True}], [], [], {'v':5}, {'v':5}, 'light', 'dark', {}, {}), {'paint': [('a', 'v')], 'measure': [], 'removed': [], 'added': []})
    check('parity and removals', solve([{'id':'a','v':1},{'id':'b','v':2},{'id':'c','v':3},{'id':'gone','v':4}], [{'id':'b','v':2},{'id':'c','v':3},{'id':'a','v':1},{'id':'new','v':5}], [{'id':'v','field':'v','stripe':True}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [('b', 'v'), ('c', 'v'), ('new', 'v')], 'measure': [], 'removed': ['gone'], 'added': ['new']})
    check('unchanged', solve([{'id':'a','v':1}], [{'id':'a','v':1}], [{'id':'v','field':'v'}], [], [], {'v':5}, {'v':5}, 'light', 'light', {}, {}), {'paint': [], 'measure': [], 'removed': [], 'added': []})

check('variant wrapping width invalidation', solve([{'id':'r','a':1}], [{'id':'r','a':1}], [{'id':'a','field':'a','wrap':True}], [], [], {'a':N}, {'a':3}, 'light', 'light', {}, {}), {'paint':[('r','a')] if N!=3 else [],'measure':[('r','a')] if N!=3 else [],'removed':[],'added':[]})
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
accessor value changes{'added': [], 'measure': [['a', 'display']], 'paint': [['a', 'display']], 'removed': []}{'added': [], 'measure': [['a', 'display']], 'paint': [['a', 'display']], 'removed': []}Passed
selection removed and added{'added': [], 'measure': [], 'paint': [['a', 'v'], ['b', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v'], ['b', 'v']], 'removed': []}Passed
error message changes{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}Passed
width shrinks wrapping{'added': [], 'measure': [['a', 'v']], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [['a', 'v']], 'paint': [['a', 'v']], 'removed': []}Passed
theme-only repaint{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}{'added': [], 'measure': [], 'paint': [['a', 'v']], 'removed': []}Passed
parity and removals{'added': ['new'], 'measure': [], 'paint': [['b', 'v'], ['c', 'v'], ['new', 'v']], 'removed': ['gone']}{'added': ['new'], 'measure': [], 'paint': [['b', 'v'], ['c', 'v'], ['new', 'v']], 'removed': ['gone']}Passed
unchanged{'added': [], 'measure': [], 'paint': [], 'removed': []}{'added': [], 'measure': [], 'paint': [], 'removed': []}Passed
variant wrapping width invalidation{'added': [], 'measure': [['r', 'a']], 'paint': [['r', 'a']], 'removed': []}{'added': [], 'measure': [['r', 'a']], 'paint': [['r', 'a']], 'removed': []}Passed

SHA-256 / 84efd57e3cf5914da913f12eb56893863bd1efc35bbacd038f1657d584c9ff83

Verification & scope

Source row and schema IDs are unique; accessors name direct fields and stripe invalidation uses parity only. Deterministic offline table UI model; no browser, DOM, framework, or standards conformance is claimed. 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:43:09.300907+00:00.

Case digest / 7f34efcfa54b45837ca09e19b09e4aa4f3dae89e525fed9b3453a99a3125667a