FAILURE MAP
← Case archive

FA-37586 / Table interactions / Open access

Table viewport anchor restoration: column inset clamp · case 01

The table column inset clamp result violates the stipulated table viewport anchor restoration contract.

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

ROOT CAUSE

The column inset clamp decision uses 'column_inset' instead of "max(0,min(column_inset,new_columns[ci]['width']-1))".

VERIFIED REPAIR

Apply the complete column inset clamp rule: max(0,min(column_inset,new_columns[ci]['width']-1)).

Unsuccessful approach: The attempted repair '0' still loses a required part of the table contract.

Case contract

Restore a table viewport by stable row and column anchors after structural changes. A removed row chooses its next surviving former successor or final row, resets its inset, clamps surviving insets to new sizes, and clamps vertical scroll to the viewport extent.

Why this case matters

An offline table UI model isolates table viewport anchor restoration, 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(before, after, anchor, inset, old_scroll, viewport, old_columns, new_columns, column_anchor, column_inset):
    old_ids=[x['id'] for x in before]; new_ids=[x['id'] for x in after]
    if anchor in new_ids: chosen=anchor
    else:
        following=old_ids[old_ids.index(anchor)+1:] if anchor in old_ids else []
        chosen=next((x for x in following if x in new_ids),new_ids[-1] if new_ids else None)
    idx=new_ids.index(chosen) if chosen is not None else 0
    prefix=sum(x['height'] for x in after[:idx])
    local=min(max(inset,0),max(0,after[idx]['height']-1)) if chosen==anchor and after else 0
    y=min(max(prefix+local,0),max(0,sum(x['height'] for x in after)-viewport))
    cols=[x['id'] for x in new_columns]
    ci=cols.index(column_anchor) if column_anchor in cols else 0
    x=sum(c['width'] for c in new_columns[:ci])+(column_inset if column_anchor in cols else 0)
    return {'row':chosen,'scroll_y':y,'column':cols[ci] if cols else None,'scroll_x':x}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':1+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 10, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 2:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':2+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 11, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 3:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':3+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 12, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 4:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':4+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 13, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 5:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':5+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 14, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

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
insert before anchored row{'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 10}{'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 10}Passed
removed anchor successor{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}Passed
removed last anchor{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5}Passed
shrunk anchored cell{'column': 'a', 'row': 'a', 'scroll_x': 18, 'scroll_y': 3}{'column': 'a', 'row': 'a', 'scroll_x': 4, 'scroll_y': 3}Failed
bottom clamp{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 2}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 2}Passed
surviving middle{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7}Passed
first successor{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}Passed
interior shrink{'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4}{'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4}Passed
empty table{'column': None, 'row': None, 'scroll_x': 0, 'scroll_y': 0}{'column': None, 'row': None, 'scroll_x': 0, 'scroll_y': 0}Passed

SHA-256 / 462bd133800100219484c604b02ae62651b9406a3c20e7982b805182a9c568e2

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(before, after, anchor, inset, old_scroll, viewport, old_columns, new_columns, column_anchor, column_inset):
    old_ids=[x['id'] for x in before]; new_ids=[x['id'] for x in after]
    if anchor in new_ids: chosen=anchor
    else:
        following=old_ids[old_ids.index(anchor)+1:] if anchor in old_ids else []
        chosen=next((x for x in following if x in new_ids),new_ids[-1] if new_ids else None)
    idx=new_ids.index(chosen) if chosen is not None else 0
    prefix=sum(x['height'] for x in after[:idx])
    local=min(max(inset,0),max(0,after[idx]['height']-1)) if chosen==anchor and after else 0
    y=min(max(prefix+local,0),max(0,sum(x['height'] for x in after)-viewport))
    cols=[x['id'] for x in new_columns]
    ci=cols.index(column_anchor) if column_anchor in cols else 0
    x=sum(c['width'] for c in new_columns[:ci])+(0 if column_anchor in cols else 0)
    return {'row':chosen,'scroll_y':y,'column':cols[ci] if cols else None,'scroll_x':x}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':1+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 10, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 2:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':2+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 11, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 3:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':3+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 12, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 4:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':4+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 13, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 5:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':5+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 14, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

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
insert before anchored row{'column': 'b', 'row': 'b', 'scroll_x': 8, 'scroll_y': 10}{'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 10}Failed
removed anchor successor{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}Passed
removed last anchor{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5}Passed
shrunk anchored cell{'column': 'a', 'row': 'a', 'scroll_x': 0, 'scroll_y': 3}{'column': 'a', 'row': 'a', 'scroll_x': 4, 'scroll_y': 3}Failed
bottom clamp{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 2}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 2}Passed
surviving middle{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7}Passed
first successor{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}Passed
interior shrink{'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4}{'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4}Passed
empty table{'column': None, 'row': None, 'scroll_x': 0, 'scroll_y': 0}{'column': None, 'row': None, 'scroll_x': 0, 'scroll_y': 0}Passed

SHA-256 / 223ac5886d4b37d39bd0b2d18f1518ecb62a64ccc6c20a6cd415c4b9b5dc18fb

3 / The verified repair

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

N = 1
observations = []
def solve(before, after, anchor, inset, old_scroll, viewport, old_columns, new_columns, column_anchor, column_inset):
    old_ids=[x['id'] for x in before]; new_ids=[x['id'] for x in after]
    if anchor in new_ids: chosen=anchor
    else:
        following=old_ids[old_ids.index(anchor)+1:] if anchor in old_ids else []
        chosen=next((x for x in following if x in new_ids),new_ids[-1] if new_ids else None)
    idx=new_ids.index(chosen) if chosen is not None else 0
    prefix=sum(x['height'] for x in after[:idx])
    local=min(max(inset,0),max(0,after[idx]['height']-1)) if chosen==anchor and after else 0
    y=min(max(prefix+local,0),max(0,sum(x['height'] for x in after)-viewport))
    cols=[x['id'] for x in new_columns]
    ci=cols.index(column_anchor) if column_anchor in cols else 0
    x=sum(c['width'] for c in new_columns[:ci])+(max(0,min(column_inset,new_columns[ci]['width']-1)) if column_anchor in cols else 0)
    return {'row':chosen,'scroll_y':y,'column':cols[ci] if cols else None,'scroll_x':x}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':1+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 10, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 2:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':2+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 11, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 3:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':3+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 12, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 4:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':4+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 13, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

if N == 5:
    check('insert before anchored row', solve([{'id':'a','height':5},{'id':'b','height':8}], [{'id':'x','height':5+2},{'id':'a','height':5},{'id':'b','height':8}], 'b', 2, 7, 4, [{'id':'a','width':5},{'id':'b','width':8}], [{'id':'x','width':3},{'id':'a','width':5},{'id':'b','width':8}], 'b', 2), {'row': 'b', 'scroll_y': 14, 'column': 'b', 'scroll_x': 10})
    check('removed anchor successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'c','height':9}], 'b', 3, 8, 4, [], [], 'gone', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('removed last anchor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8}], 'c', 3, 16, 4, [], [], 'gone', 0), {'row': 'b', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('shrunk anchored cell', solve([{'id':'a','height':20}], [{'id':'a','height':5}], 'a', 18, 18, 2, [{'id':'a','width':20}], [{'id':'a','width':5}], 'a', 18), {'row': 'a', 'scroll_y': 3, 'column': 'a', 'scroll_x': 4})
    check('bottom clamp', solve([{'id':'a','height':5},{'id':'b','height':10}], [{'id':'a','height':5},{'id':'b','height':4}], 'b', 3, 8, 7, [], [], '', 0), {'row': 'b', 'scroll_y': 2, 'column': None, 'scroll_x': 0})
    check('surviving middle', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], [{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'b', 'scroll_y': 7, 'column': None, 'scroll_x': 0})
    check('first successor', solve([{'id':'a','height':5},{'id':'b','height':8},{'id':'c','height':9},{'id':'d','height':10}], [{'id':'a','height':5},{'id':'c','height':9},{'id':'d','height':10}], 'b', 2, 7, 4, [], [], '', 0), {'row': 'c', 'scroll_y': 5, 'column': None, 'scroll_x': 0})
    check('interior shrink', solve([{'id':'a','height':20},{'id':'b','height':30}], [{'id':'a','height':5},{'id':'b','height':30}], 'a', 18, 18, 2, [], [], '', 0), {'row': 'a', 'scroll_y': 4, 'column': None, 'scroll_x': 0})
    check('empty table', solve([{'id':'a','height':5}], [], 'a', 2, 2, 4, [], [], '', 0), {'row': None, 'scroll_y': 0, 'column': None, 'scroll_x': 0})

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
insert before anchored row{'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 10}{'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 10}Passed
removed anchor successor{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}Passed
removed last anchor{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5}Passed
shrunk anchored cell{'column': 'a', 'row': 'a', 'scroll_x': 4, 'scroll_y': 3}{'column': 'a', 'row': 'a', 'scroll_x': 4, 'scroll_y': 3}Passed
bottom clamp{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 2}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 2}Passed
surviving middle{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7}{'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7}Passed
first successor{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}{'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5}Passed
interior shrink{'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4}{'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4}Passed
empty table{'column': None, 'row': None, 'scroll_x': 0, 'scroll_y': 0}{'column': None, 'row': None, 'scroll_x': 0, 'scroll_y': 0}Passed

SHA-256 / 7c66f1720ede9c567f28c7dc345ba1b41dc121e846bd4f344ec87753ec654ad0

Verification & scope

Source and replacement axes have unique IDs and positive dimensions; viewport extent is nonnegative. 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:02.648287+00:00.

Case digest / 39db4c4e84af5bb01e461f18405336bc0a7a10f2ac30c033f4fbde50333329d1