FA-37211 / Table interactions / Open access
Atomic table row editing: unknown row reject · case 01
The table unknown row reject result violates the stipulated atomic table row editing contract.
ROOT CAUSE
The unknown row reject decision uses 'if False:' instead of 'if unknown:'.
VERIFIED REPAIR
Apply the complete unknown row reject rule: if unknown:.
Unsuccessful approach: The attempted repair 'if len(unknown)>1:' still loses a required part of the table contract.
Case contract
Row commits validate the merged draft atomically, reject unknown schema fields, ignore readonly fields, preserve untouched cells and stable identity, reject revision conflicts, suppress no-ops, and increment the revision only after actual changes.
Why this case matters
An offline table UI model isolates atomic table row editing, 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(row, draft, schema, revision, base_revision):
allowed={c['id'] for c in schema if c.get('editable',True)}
unknown=sorted(set(draft)-{c['id'] for c in schema})
changes={k:v for k,v in draft.items() if k in allowed and row.get(k)!=v}
errors={c['id']:'required' for c in schema if c.get('required') and draft.get(c['id'],row.get(c['id'])) in ('',None)}
if False: return {'status':'unknown','fields':unknown,'row':row}
if errors: return {'status':'invalid','fields':errors,'row':row}
if base_revision!=revision: return {'status':'conflict','fields':[],'row':row}
if not changes: return {'status':'unchanged','fields':[],'row':row}
updated=dict(row); updated.update(changes)
return {'status':'saved','fields':sorted(changes),'row':updated,'revision':revision+1}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':1+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 4, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 2:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':2+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 5, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 3:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':3+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 6, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 4:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':4+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 7, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 5:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':5+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 8, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
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 |
|---|---|---|---|
| partial draft | {'fields': ['a'], 'revision': 5, 'row': {'a': 4, 'b': 2, 'id': 'r'}, 'status': 'saved'} | {'fields': ['a'], 'revision': 5, 'row': {'a': 4, 'b': 2, 'id': 'r'}, 'status': 'saved'} | Passed |
| readonly draft | {'fields': [], 'row': {'a': 1, 'b': 2, 'id': 'r'}, 'status': 'unchanged'} | {'fields': [], 'row': {'a': 1, 'b': 2, 'id': 'r'}, 'status': 'unchanged'} | Passed |
| unknown draft | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | {'fields': ['missing'], 'row': {'a': 1, 'id': 'r'}, 'status': 'unknown'} | Failed |
| required clear | {'fields': {'a': 'required'}, 'row': {'a': 'ok', 'b': 2, 'id': 'r'}, 'status': 'invalid'} | {'fields': {'a': 'required'}, 'row': {'a': 'ok', 'b': 2, 'id': 'r'}, 'status': 'invalid'} | Passed |
| required untouched | {'fields': ['b'], 'revision': 5, 'row': {'a': 'ok', 'b': 0, 'id': 'r'}, 'status': 'saved'} | {'fields': ['b'], 'revision': 5, 'row': {'a': 'ok', 'b': 0, 'id': 'r'}, 'status': 'saved'} | Passed |
| stale row | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'conflict'} | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'conflict'} | Passed |
| same value | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | Passed |
SHA-256 / d5f4420b91f46449aad91064655dbbcdbfd7b2c194feb17d506e58b2535e15c7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(row, draft, schema, revision, base_revision):
allowed={c['id'] for c in schema if c.get('editable',True)}
unknown=sorted(set(draft)-{c['id'] for c in schema})
changes={k:v for k,v in draft.items() if k in allowed and row.get(k)!=v}
errors={c['id']:'required' for c in schema if c.get('required') and draft.get(c['id'],row.get(c['id'])) in ('',None)}
if len(unknown)>1: return {'status':'unknown','fields':unknown,'row':row}
if errors: return {'status':'invalid','fields':errors,'row':row}
if base_revision!=revision: return {'status':'conflict','fields':[],'row':row}
if not changes: return {'status':'unchanged','fields':[],'row':row}
updated=dict(row); updated.update(changes)
return {'status':'saved','fields':sorted(changes),'row':updated,'revision':revision+1}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':1+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 4, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 2:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':2+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 5, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 3:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':3+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 6, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 4:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':4+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 7, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 5:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':5+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 8, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
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 |
|---|---|---|---|
| partial draft | {'fields': ['a'], 'revision': 5, 'row': {'a': 4, 'b': 2, 'id': 'r'}, 'status': 'saved'} | {'fields': ['a'], 'revision': 5, 'row': {'a': 4, 'b': 2, 'id': 'r'}, 'status': 'saved'} | Passed |
| readonly draft | {'fields': [], 'row': {'a': 1, 'b': 2, 'id': 'r'}, 'status': 'unchanged'} | {'fields': [], 'row': {'a': 1, 'b': 2, 'id': 'r'}, 'status': 'unchanged'} | Passed |
| unknown draft | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | {'fields': ['missing'], 'row': {'a': 1, 'id': 'r'}, 'status': 'unknown'} | Failed |
| required clear | {'fields': {'a': 'required'}, 'row': {'a': 'ok', 'b': 2, 'id': 'r'}, 'status': 'invalid'} | {'fields': {'a': 'required'}, 'row': {'a': 'ok', 'b': 2, 'id': 'r'}, 'status': 'invalid'} | Passed |
| required untouched | {'fields': ['b'], 'revision': 5, 'row': {'a': 'ok', 'b': 0, 'id': 'r'}, 'status': 'saved'} | {'fields': ['b'], 'revision': 5, 'row': {'a': 'ok', 'b': 0, 'id': 'r'}, 'status': 'saved'} | Passed |
| stale row | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'conflict'} | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'conflict'} | Passed |
| same value | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | Passed |
SHA-256 / d754c0084f38f93b871f32bce0905c022051c5d25fda86366d4539ef92173cbc
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(row, draft, schema, revision, base_revision):
allowed={c['id'] for c in schema if c.get('editable',True)}
unknown=sorted(set(draft)-{c['id'] for c in schema})
changes={k:v for k,v in draft.items() if k in allowed and row.get(k)!=v}
errors={c['id']:'required' for c in schema if c.get('required') and draft.get(c['id'],row.get(c['id'])) in ('',None)}
if unknown: return {'status':'unknown','fields':unknown,'row':row}
if errors: return {'status':'invalid','fields':errors,'row':row}
if base_revision!=revision: return {'status':'conflict','fields':[],'row':row}
if not changes: return {'status':'unchanged','fields':[],'row':row}
updated=dict(row); updated.update(changes)
return {'status':'saved','fields':sorted(changes),'row':updated,'revision':revision+1}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':1+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 4, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 2:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':2+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 5, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 3:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':3+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 6, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 4:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':4+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 7, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
if N == 5:
check('partial draft', solve({'id':'r','a':1,'b':2}, {'a':5+3}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'saved', 'fields': ['a'], 'row': {'id': 'r', 'a': 8, 'b': 2}, 'revision': 5})
check('readonly draft', solve({'id':'r','a':1,'b':2}, {'b':9}, [{'id':'a'},{'id':'b','editable':False}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1, 'b': 2}})
check('unknown draft', solve({'id':'r','a':1}, {'missing':2}, [{'id':'a'}], 4, 4), {'status': 'unknown', 'fields': ['missing'], 'row': {'id': 'r', 'a': 1}})
check('required clear', solve({'id':'r','a':'ok','b':2}, {'a':''}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'invalid', 'fields': {'a': 'required'}, 'row': {'id': 'r', 'a': 'ok', 'b': 2}})
check('required untouched', solve({'id':'r','a':'ok','b':2}, {'b':0}, [{'id':'a','required':True},{'id':'b'}], 4, 4), {'status': 'saved', 'fields': ['b'], 'row': {'id': 'r', 'a': 'ok', 'b': 0}, 'revision': 5})
check('stale row', solve({'id':'r','a':1}, {'a':2}, [{'id':'a'}], 4, 3), {'status': 'conflict', 'fields': [], 'row': {'id': 'r', 'a': 1}})
check('same value', solve({'id':'r','a':1}, {'a':1}, [{'id':'a'}], 4, 4), {'status': 'unchanged', 'fields': [], 'row': {'id': 'r', 'a': 1}})
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 |
|---|---|---|---|
| partial draft | {'fields': ['a'], 'revision': 5, 'row': {'a': 4, 'b': 2, 'id': 'r'}, 'status': 'saved'} | {'fields': ['a'], 'revision': 5, 'row': {'a': 4, 'b': 2, 'id': 'r'}, 'status': 'saved'} | Passed |
| readonly draft | {'fields': [], 'row': {'a': 1, 'b': 2, 'id': 'r'}, 'status': 'unchanged'} | {'fields': [], 'row': {'a': 1, 'b': 2, 'id': 'r'}, 'status': 'unchanged'} | Passed |
| unknown draft | {'fields': ['missing'], 'row': {'a': 1, 'id': 'r'}, 'status': 'unknown'} | {'fields': ['missing'], 'row': {'a': 1, 'id': 'r'}, 'status': 'unknown'} | Passed |
| required clear | {'fields': {'a': 'required'}, 'row': {'a': 'ok', 'b': 2, 'id': 'r'}, 'status': 'invalid'} | {'fields': {'a': 'required'}, 'row': {'a': 'ok', 'b': 2, 'id': 'r'}, 'status': 'invalid'} | Passed |
| required untouched | {'fields': ['b'], 'revision': 5, 'row': {'a': 'ok', 'b': 0, 'id': 'r'}, 'status': 'saved'} | {'fields': ['b'], 'revision': 5, 'row': {'a': 'ok', 'b': 0, 'id': 'r'}, 'status': 'saved'} | Passed |
| stale row | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'conflict'} | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'conflict'} | Passed |
| same value | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | {'fields': [], 'row': {'a': 1, 'id': 'r'}, 'status': 'unchanged'} | Passed |
SHA-256 / 78c3b45fabae211ccd7d70b8d1d0f12fb803c906e5517e6cc603863397e25c7a
Verification & scope
Schema IDs are unique, revisions are integers, and required validation means only None or empty string. 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:42:59.014625+00:00.
Case digest / 8f8fdffcacc4358d43bb1cac870ef0e0a3aaf0f299622fb111b0bc749861e9bf