FA-37556 / Table interactions / Open access
Table viewport anchor restoration: row prefix height · case 01
The table row prefix height result violates the stipulated table viewport anchor restoration contract.
ROOT CAUSE
The row prefix height decision uses 'after[:idx+1]' instead of 'after[:idx]'.
VERIFIED REPAIR
Apply the complete row prefix height rule: after[:idx].
Unsuccessful approach: The attempted repair 'before[:idx]' 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+1])
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| insert before anchored row | {'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 12} | {'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 10} | Failed |
| removed anchor successor | {'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 10} | {'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5} | Failed |
| removed last anchor | {'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 9} | {'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 5} | Failed |
| 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': 15} | {'column': None, 'row': 'b', 'scroll_x': 0, 'scroll_y': 7} | Failed |
| first successor | {'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 14} | {'column': None, 'row': 'c', 'scroll_x': 0, 'scroll_y': 5} | Failed |
| interior shrink | {'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 9} | {'column': None, 'row': 'a', 'scroll_x': 0, 'scroll_y': 4} | Failed |
| 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 / 1ebe724f1727952663b6cf2e4f176e22faf87d2ae77eba0566bd789c37f01305
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 before[: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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| insert before anchored row | {'column': 'b', 'row': 'b', 'scroll_x': 10, 'scroll_y': 12} | {'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': 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 / 014e5f2393fb2309ed00eb6dbc2949873e35b8e5f11483537ab7d04c28bf5b22
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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.337066+00:00.
Case digest / f8ef62d925e561e3a87ece5d96d981577b4be7568ab64e3f43505da19d378361