FA-24351 / Client state / Open access
Editor autosave revision reconciliation: Composition defers save · case 01
Composition defers save.
ROOT CAUSE
The composition-defers-save client decision evaluates `online and bool(dirty_fields)` instead of `online and bool(dirty_fields) and not composing`.
VERIFIED REPAIR
Apply the modeled composition-defers-save rule: `online and bool(dirty_fields) and not composing`.
Unsuccessful approach: The partial repair `not composing and bool(dirty_fields)` still violates the explicit fixture contract.
Case contract
Autosave snapshots both revision and field set. A successful old save acknowledges its sent revision without clearing newer edits. Offline and composition defer new saves, and conflicts preserve local edits for explicit resolution. Operation composition-defers-save has the six explicit input/output oracles below.
Why this case matters
An offline client lifecycle model that isolates a state-management defect without DOM rendering or network services.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(operation, s):
current, sent, acknowledged, dirty_fields, sent_fields, response, online, composing = s
if operation == 'acknowledge-sent-revision':
return sent if response=='ok' else acknowledged
if operation == 'newer-edit-retains-dirty':
return dirty_fields if current!=sent or response!='ok' else [f for f in dirty_fields if f not in sent_fields]
if operation == 'composition-defers-save':
return online and bool(dirty_fields)
if operation == 'save-completion-status':
return 'conflict' if response=='conflict' else ('error' if response=='failed' else ('saved' if current==sent else 'unsaved'))
if operation == 'next-save-revision':
return current if current>sent else None
if operation == 'unsent-field-difference':
return [f for f in dirty_fields if f not in sent_fields]
if operation == 'conflict-preserves-local-fields':
return dirty_fields if response=='conflict' else []
if operation == 'save-payload-field-snapshot':
return list(sent_fields)
if operation == 'unacknowledged-edit-distance':
return max(0,current-acknowledged)
if operation == 'resave-after-ack':
return response=='ok' and current>sent and online and not composing
raise ValueError('unknown modeled operation')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('acknowledge-sent-revision scenario 1', solve('acknowledge-sent-revision', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), N+1)
check('acknowledge-sent-revision scenario 2', solve('acknowledge-sent-revision', (1,1,0,['a'],['a'],'ok',True,False)), 1)
check('acknowledge-sent-revision scenario 3', solve('acknowledge-sent-revision', (2,1,0,['a','b'],['a'],'failed',True,False)), 0)
check('acknowledge-sent-revision scenario 4', solve('acknowledge-sent-revision', (0,0,0,[],[],'ok',True,True)), 0)
check('acknowledge-sent-revision scenario 5', solve('acknowledge-sent-revision', (3,2,1,['b'],['a'],'ok',False,False)), 2)
check('acknowledge-sent-revision scenario 6', solve('acknowledge-sent-revision', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 3)
check('newer-edit-retains-dirty scenario 1', solve('newer-edit-retains-dirty', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['a','b'])
check('newer-edit-retains-dirty scenario 2', solve('newer-edit-retains-dirty', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('newer-edit-retains-dirty scenario 3', solve('newer-edit-retains-dirty', (2,1,0,['a','b'],['a'],'failed',True,False)), ['a','b'])
check('newer-edit-retains-dirty scenario 4', solve('newer-edit-retains-dirty', (0,0,0,[],[],'ok',True,True)), [])
check('newer-edit-retains-dirty scenario 5', solve('newer-edit-retains-dirty', (3,2,1,['b'],['a'],'ok',False,False)), ['b'])
check('newer-edit-retains-dirty scenario 6', solve('newer-edit-retains-dirty', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('composition-defers-save scenario 1', solve('composition-defers-save', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), True)
check('composition-defers-save scenario 2', solve('composition-defers-save', (1,1,0,['a'],['a'],'ok',True,False)), True)
check('composition-defers-save scenario 3', solve('composition-defers-save', (2,1,0,['a','b'],['a'],'failed',True,False)), True)
check('composition-defers-save scenario 4', solve('composition-defers-save', (0,0,0,[],[],'ok',True,True)), False)
check('composition-defers-save scenario 5', solve('composition-defers-save', (3,2,1,['b'],['a'],'ok',False,False)), False)
check('composition-defers-save scenario 6', solve('composition-defers-save', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), False)
check('save-completion-status scenario 1', solve('save-completion-status', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), 'unsaved')
check('save-completion-status scenario 2', solve('save-completion-status', (1,1,0,['a'],['a'],'ok',True,False)), 'saved')
check('save-completion-status scenario 3', solve('save-completion-status', (2,1,0,['a','b'],['a'],'failed',True,False)), 'error')
check('save-completion-status scenario 4', solve('save-completion-status', (0,0,0,[],[],'ok',True,True)), 'saved')
check('save-completion-status scenario 5', solve('save-completion-status', (3,2,1,['b'],['a'],'ok',False,False)), 'unsaved')
check('save-completion-status scenario 6', solve('save-completion-status', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 'conflict')
check('next-save-revision scenario 1', solve('next-save-revision', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), N+2)
check('next-save-revision scenario 2', solve('next-save-revision', (1,1,0,['a'],['a'],'ok',True,False)), None)
check('next-save-revision scenario 3', solve('next-save-revision', (2,1,0,['a','b'],['a'],'failed',True,False)), 2)
check('next-save-revision scenario 4', solve('next-save-revision', (0,0,0,[],[],'ok',True,True)), None)
check('next-save-revision scenario 5', solve('next-save-revision', (3,2,1,['b'],['a'],'ok',False,False)), 3)
check('next-save-revision scenario 6', solve('next-save-revision', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), None)
check('unsent-field-difference scenario 1', solve('unsent-field-difference', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['b'])
check('unsent-field-difference scenario 2', solve('unsent-field-difference', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('unsent-field-difference scenario 3', solve('unsent-field-difference', (2,1,0,['a','b'],['a'],'failed',True,False)), ['b'])
check('unsent-field-difference scenario 4', solve('unsent-field-difference', (0,0,0,[],[],'ok',True,True)), [])
check('unsent-field-difference scenario 5', solve('unsent-field-difference', (3,2,1,['b'],['a'],'ok',False,False)), ['b'])
check('unsent-field-difference scenario 6', solve('unsent-field-difference', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), [])
check('conflict-preserves-local-fields scenario 1', solve('conflict-preserves-local-fields', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), [])
check('conflict-preserves-local-fields scenario 2', solve('conflict-preserves-local-fields', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('conflict-preserves-local-fields scenario 3', solve('conflict-preserves-local-fields', (2,1,0,['a','b'],['a'],'failed',True,False)), [])
check('conflict-preserves-local-fields scenario 4', solve('conflict-preserves-local-fields', (0,0,0,[],[],'ok',True,True)), [])
check('conflict-preserves-local-fields scenario 5', solve('conflict-preserves-local-fields', (3,2,1,['b'],['a'],'ok',False,False)), [])
check('conflict-preserves-local-fields scenario 6', solve('conflict-preserves-local-fields', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('save-payload-field-snapshot scenario 1', solve('save-payload-field-snapshot', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['a'])
check('save-payload-field-snapshot scenario 2', solve('save-payload-field-snapshot', (1,1,0,['a'],['a'],'ok',True,False)), ['a'])
check('save-payload-field-snapshot scenario 3', solve('save-payload-field-snapshot', (2,1,0,['a','b'],['a'],'failed',True,False)), ['a'])
check('save-payload-field-snapshot scenario 4', solve('save-payload-field-snapshot', (0,0,0,[],[],'ok',True,True)), [])
check('save-payload-field-snapshot scenario 5', solve('save-payload-field-snapshot', (3,2,1,['b'],['a'],'ok',False,False)), ['a'])
check('save-payload-field-snapshot scenario 6', solve('save-payload-field-snapshot', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('unacknowledged-edit-distance scenario 1', solve('unacknowledged-edit-distance', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), 2)
check('unacknowledged-edit-distance scenario 2', solve('unacknowledged-edit-distance', (1,1,0,['a'],['a'],'ok',True,False)), 1)
check('unacknowledged-edit-distance scenario 3', solve('unacknowledged-edit-distance', (2,1,0,['a','b'],['a'],'failed',True,False)), 2)
check('unacknowledged-edit-distance scenario 4', solve('unacknowledged-edit-distance', (0,0,0,[],[],'ok',True,True)), 0)
check('unacknowledged-edit-distance scenario 5', solve('unacknowledged-edit-distance', (3,2,1,['b'],['a'],'ok',False,False)), 2)
check('unacknowledged-edit-distance scenario 6', solve('unacknowledged-edit-distance', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 1)
check('resave-after-ack scenario 1', solve('resave-after-ack', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), True)
check('resave-after-ack scenario 2', solve('resave-after-ack', (1,1,0,['a'],['a'],'ok',True,False)), False)
check('resave-after-ack scenario 3', solve('resave-after-ack', (2,1,0,['a','b'],['a'],'failed',True,False)), False)
check('resave-after-ack scenario 4', solve('resave-after-ack', (0,0,0,[],[],'ok',True,True)), False)
check('resave-after-ack scenario 5', solve('resave-after-ack', (3,2,1,['b'],['a'],'ok',False,False)), False)
check('resave-after-ack scenario 6', solve('resave-after-ack', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), False)
check('many edits during conflicting save: acknowledge-sent-revision', solve('acknowledge-sent-revision', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), 1)
check('many edits during conflicting save: newer-edit-retains-dirty', solve('newer-edit-retains-dirty', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a','b'])
check('many edits during conflicting save: composition-defers-save', solve('composition-defers-save', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), True)
check('many edits during conflicting save: save-completion-status', solve('save-completion-status', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), 'conflict')
check('many edits during conflicting save: next-save-revision', solve('next-save-revision', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), N+5)
check('many edits during conflicting save: unsent-field-difference', solve('unsent-field-difference', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['b'])
check('many edits during conflicting save: conflict-preserves-local-fields', solve('conflict-preserves-local-fields', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a','b'])
check('many edits during conflicting save: save-payload-field-snapshot', solve('save-payload-field-snapshot', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a'])
check('many edits during conflicting save: unacknowledged-edit-distance', solve('unacknowledged-edit-distance', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), N+4)
check('many edits during conflicting save: resave-after-ack', solve('resave-after-ack', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), False)
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 |
|---|---|---|---|
| acknowledge-sent-revision scenario 1 | 2 | 2 | Passed |
| acknowledge-sent-revision scenario 2 | 1 | 1 | Passed |
| acknowledge-sent-revision scenario 3 | 0 | 0 | Passed |
| acknowledge-sent-revision scenario 4 | 0 | 0 | Passed |
| acknowledge-sent-revision scenario 5 | 2 | 2 | Passed |
| acknowledge-sent-revision scenario 6 | 3 | 3 | Passed |
| newer-edit-retains-dirty scenario 1 | ['a', 'b'] | ['a', 'b'] | Passed |
| newer-edit-retains-dirty scenario 2 | [] | [] | Passed |
| newer-edit-retains-dirty scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| newer-edit-retains-dirty scenario 4 | [] | [] | Passed |
| newer-edit-retains-dirty scenario 5 | ['b'] | ['b'] | Passed |
| newer-edit-retains-dirty scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| composition-defers-save scenario 1 | True | True | Passed |
| composition-defers-save scenario 2 | True | True | Passed |
| composition-defers-save scenario 3 | True | True | Passed |
| composition-defers-save scenario 4 | False | False | Passed |
| composition-defers-save scenario 5 | False | False | Passed |
| composition-defers-save scenario 6 | True | False | Failed |
| save-completion-status scenario 1 | unsaved | unsaved | Passed |
| save-completion-status scenario 2 | saved | saved | Passed |
| save-completion-status scenario 3 | error | error | Passed |
| save-completion-status scenario 4 | saved | saved | Passed |
| save-completion-status scenario 5 | unsaved | unsaved | Passed |
| save-completion-status scenario 6 | conflict | conflict | Passed |
| next-save-revision scenario 1 | 3 | 3 | Passed |
| next-save-revision scenario 2 | None | None | Passed |
| next-save-revision scenario 3 | 2 | 2 | Passed |
| next-save-revision scenario 4 | None | None | Passed |
| next-save-revision scenario 5 | 3 | 3 | Passed |
| next-save-revision scenario 6 | None | None | Passed |
| unsent-field-difference scenario 1 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 2 | [] | [] | Passed |
| unsent-field-difference scenario 3 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 4 | [] | [] | Passed |
| unsent-field-difference scenario 5 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 6 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 1 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 2 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 3 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 4 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 5 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| save-payload-field-snapshot scenario 1 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 2 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 3 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 4 | [] | [] | Passed |
| save-payload-field-snapshot scenario 5 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| unacknowledged-edit-distance scenario 1 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 2 | 1 | 1 | Passed |
| unacknowledged-edit-distance scenario 3 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 4 | 0 | 0 | Passed |
| unacknowledged-edit-distance scenario 5 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 6 | 1 | 1 | Passed |
| resave-after-ack scenario 1 | True | True | Passed |
| resave-after-ack scenario 2 | False | False | Passed |
| resave-after-ack scenario 3 | False | False | Passed |
| resave-after-ack scenario 4 | False | False | Passed |
| resave-after-ack scenario 5 | False | False | Passed |
| resave-after-ack scenario 6 | False | False | Passed |
| many edits during conflicting save: acknowledge-sent-revision | 1 | 1 | Passed |
| many edits during conflicting save: newer-edit-retains-dirty | ['a', 'b'] | ['a', 'b'] | Passed |
| many edits during conflicting save: composition-defers-save | True | True | Passed |
| many edits during conflicting save: save-completion-status | conflict | conflict | Passed |
| many edits during conflicting save: next-save-revision | 6 | 6 | Passed |
| many edits during conflicting save: unsent-field-difference | ['b'] | ['b'] | Passed |
| many edits during conflicting save: conflict-preserves-local-fields | ['a', 'b'] | ['a', 'b'] | Passed |
| many edits during conflicting save: save-payload-field-snapshot | ['a'] | ['a'] | Passed |
| many edits during conflicting save: unacknowledged-edit-distance | 5 | 5 | Passed |
| many edits during conflicting save: resave-after-ack | False | False | Passed |
SHA-256 / b6d51b25b5d177734c5eb948dc585fdb73ef5a043cfc14fef374105521e5ef78
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(operation, s):
current, sent, acknowledged, dirty_fields, sent_fields, response, online, composing = s
if operation == 'acknowledge-sent-revision':
return sent if response=='ok' else acknowledged
if operation == 'newer-edit-retains-dirty':
return dirty_fields if current!=sent or response!='ok' else [f for f in dirty_fields if f not in sent_fields]
if operation == 'composition-defers-save':
return not composing and bool(dirty_fields)
if operation == 'save-completion-status':
return 'conflict' if response=='conflict' else ('error' if response=='failed' else ('saved' if current==sent else 'unsaved'))
if operation == 'next-save-revision':
return current if current>sent else None
if operation == 'unsent-field-difference':
return [f for f in dirty_fields if f not in sent_fields]
if operation == 'conflict-preserves-local-fields':
return dirty_fields if response=='conflict' else []
if operation == 'save-payload-field-snapshot':
return list(sent_fields)
if operation == 'unacknowledged-edit-distance':
return max(0,current-acknowledged)
if operation == 'resave-after-ack':
return response=='ok' and current>sent and online and not composing
raise ValueError('unknown modeled operation')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('acknowledge-sent-revision scenario 1', solve('acknowledge-sent-revision', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), N+1)
check('acknowledge-sent-revision scenario 2', solve('acknowledge-sent-revision', (1,1,0,['a'],['a'],'ok',True,False)), 1)
check('acknowledge-sent-revision scenario 3', solve('acknowledge-sent-revision', (2,1,0,['a','b'],['a'],'failed',True,False)), 0)
check('acknowledge-sent-revision scenario 4', solve('acknowledge-sent-revision', (0,0,0,[],[],'ok',True,True)), 0)
check('acknowledge-sent-revision scenario 5', solve('acknowledge-sent-revision', (3,2,1,['b'],['a'],'ok',False,False)), 2)
check('acknowledge-sent-revision scenario 6', solve('acknowledge-sent-revision', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 3)
check('newer-edit-retains-dirty scenario 1', solve('newer-edit-retains-dirty', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['a','b'])
check('newer-edit-retains-dirty scenario 2', solve('newer-edit-retains-dirty', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('newer-edit-retains-dirty scenario 3', solve('newer-edit-retains-dirty', (2,1,0,['a','b'],['a'],'failed',True,False)), ['a','b'])
check('newer-edit-retains-dirty scenario 4', solve('newer-edit-retains-dirty', (0,0,0,[],[],'ok',True,True)), [])
check('newer-edit-retains-dirty scenario 5', solve('newer-edit-retains-dirty', (3,2,1,['b'],['a'],'ok',False,False)), ['b'])
check('newer-edit-retains-dirty scenario 6', solve('newer-edit-retains-dirty', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('composition-defers-save scenario 1', solve('composition-defers-save', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), True)
check('composition-defers-save scenario 2', solve('composition-defers-save', (1,1,0,['a'],['a'],'ok',True,False)), True)
check('composition-defers-save scenario 3', solve('composition-defers-save', (2,1,0,['a','b'],['a'],'failed',True,False)), True)
check('composition-defers-save scenario 4', solve('composition-defers-save', (0,0,0,[],[],'ok',True,True)), False)
check('composition-defers-save scenario 5', solve('composition-defers-save', (3,2,1,['b'],['a'],'ok',False,False)), False)
check('composition-defers-save scenario 6', solve('composition-defers-save', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), False)
check('save-completion-status scenario 1', solve('save-completion-status', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), 'unsaved')
check('save-completion-status scenario 2', solve('save-completion-status', (1,1,0,['a'],['a'],'ok',True,False)), 'saved')
check('save-completion-status scenario 3', solve('save-completion-status', (2,1,0,['a','b'],['a'],'failed',True,False)), 'error')
check('save-completion-status scenario 4', solve('save-completion-status', (0,0,0,[],[],'ok',True,True)), 'saved')
check('save-completion-status scenario 5', solve('save-completion-status', (3,2,1,['b'],['a'],'ok',False,False)), 'unsaved')
check('save-completion-status scenario 6', solve('save-completion-status', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 'conflict')
check('next-save-revision scenario 1', solve('next-save-revision', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), N+2)
check('next-save-revision scenario 2', solve('next-save-revision', (1,1,0,['a'],['a'],'ok',True,False)), None)
check('next-save-revision scenario 3', solve('next-save-revision', (2,1,0,['a','b'],['a'],'failed',True,False)), 2)
check('next-save-revision scenario 4', solve('next-save-revision', (0,0,0,[],[],'ok',True,True)), None)
check('next-save-revision scenario 5', solve('next-save-revision', (3,2,1,['b'],['a'],'ok',False,False)), 3)
check('next-save-revision scenario 6', solve('next-save-revision', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), None)
check('unsent-field-difference scenario 1', solve('unsent-field-difference', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['b'])
check('unsent-field-difference scenario 2', solve('unsent-field-difference', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('unsent-field-difference scenario 3', solve('unsent-field-difference', (2,1,0,['a','b'],['a'],'failed',True,False)), ['b'])
check('unsent-field-difference scenario 4', solve('unsent-field-difference', (0,0,0,[],[],'ok',True,True)), [])
check('unsent-field-difference scenario 5', solve('unsent-field-difference', (3,2,1,['b'],['a'],'ok',False,False)), ['b'])
check('unsent-field-difference scenario 6', solve('unsent-field-difference', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), [])
check('conflict-preserves-local-fields scenario 1', solve('conflict-preserves-local-fields', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), [])
check('conflict-preserves-local-fields scenario 2', solve('conflict-preserves-local-fields', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('conflict-preserves-local-fields scenario 3', solve('conflict-preserves-local-fields', (2,1,0,['a','b'],['a'],'failed',True,False)), [])
check('conflict-preserves-local-fields scenario 4', solve('conflict-preserves-local-fields', (0,0,0,[],[],'ok',True,True)), [])
check('conflict-preserves-local-fields scenario 5', solve('conflict-preserves-local-fields', (3,2,1,['b'],['a'],'ok',False,False)), [])
check('conflict-preserves-local-fields scenario 6', solve('conflict-preserves-local-fields', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('save-payload-field-snapshot scenario 1', solve('save-payload-field-snapshot', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['a'])
check('save-payload-field-snapshot scenario 2', solve('save-payload-field-snapshot', (1,1,0,['a'],['a'],'ok',True,False)), ['a'])
check('save-payload-field-snapshot scenario 3', solve('save-payload-field-snapshot', (2,1,0,['a','b'],['a'],'failed',True,False)), ['a'])
check('save-payload-field-snapshot scenario 4', solve('save-payload-field-snapshot', (0,0,0,[],[],'ok',True,True)), [])
check('save-payload-field-snapshot scenario 5', solve('save-payload-field-snapshot', (3,2,1,['b'],['a'],'ok',False,False)), ['a'])
check('save-payload-field-snapshot scenario 6', solve('save-payload-field-snapshot', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('unacknowledged-edit-distance scenario 1', solve('unacknowledged-edit-distance', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), 2)
check('unacknowledged-edit-distance scenario 2', solve('unacknowledged-edit-distance', (1,1,0,['a'],['a'],'ok',True,False)), 1)
check('unacknowledged-edit-distance scenario 3', solve('unacknowledged-edit-distance', (2,1,0,['a','b'],['a'],'failed',True,False)), 2)
check('unacknowledged-edit-distance scenario 4', solve('unacknowledged-edit-distance', (0,0,0,[],[],'ok',True,True)), 0)
check('unacknowledged-edit-distance scenario 5', solve('unacknowledged-edit-distance', (3,2,1,['b'],['a'],'ok',False,False)), 2)
check('unacknowledged-edit-distance scenario 6', solve('unacknowledged-edit-distance', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 1)
check('resave-after-ack scenario 1', solve('resave-after-ack', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), True)
check('resave-after-ack scenario 2', solve('resave-after-ack', (1,1,0,['a'],['a'],'ok',True,False)), False)
check('resave-after-ack scenario 3', solve('resave-after-ack', (2,1,0,['a','b'],['a'],'failed',True,False)), False)
check('resave-after-ack scenario 4', solve('resave-after-ack', (0,0,0,[],[],'ok',True,True)), False)
check('resave-after-ack scenario 5', solve('resave-after-ack', (3,2,1,['b'],['a'],'ok',False,False)), False)
check('resave-after-ack scenario 6', solve('resave-after-ack', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), False)
check('many edits during conflicting save: acknowledge-sent-revision', solve('acknowledge-sent-revision', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), 1)
check('many edits during conflicting save: newer-edit-retains-dirty', solve('newer-edit-retains-dirty', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a','b'])
check('many edits during conflicting save: composition-defers-save', solve('composition-defers-save', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), True)
check('many edits during conflicting save: save-completion-status', solve('save-completion-status', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), 'conflict')
check('many edits during conflicting save: next-save-revision', solve('next-save-revision', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), N+5)
check('many edits during conflicting save: unsent-field-difference', solve('unsent-field-difference', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['b'])
check('many edits during conflicting save: conflict-preserves-local-fields', solve('conflict-preserves-local-fields', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a','b'])
check('many edits during conflicting save: save-payload-field-snapshot', solve('save-payload-field-snapshot', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a'])
check('many edits during conflicting save: unacknowledged-edit-distance', solve('unacknowledged-edit-distance', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), N+4)
check('many edits during conflicting save: resave-after-ack', solve('resave-after-ack', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), False)
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 |
|---|---|---|---|
| acknowledge-sent-revision scenario 1 | 2 | 2 | Passed |
| acknowledge-sent-revision scenario 2 | 1 | 1 | Passed |
| acknowledge-sent-revision scenario 3 | 0 | 0 | Passed |
| acknowledge-sent-revision scenario 4 | 0 | 0 | Passed |
| acknowledge-sent-revision scenario 5 | 2 | 2 | Passed |
| acknowledge-sent-revision scenario 6 | 3 | 3 | Passed |
| newer-edit-retains-dirty scenario 1 | ['a', 'b'] | ['a', 'b'] | Passed |
| newer-edit-retains-dirty scenario 2 | [] | [] | Passed |
| newer-edit-retains-dirty scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| newer-edit-retains-dirty scenario 4 | [] | [] | Passed |
| newer-edit-retains-dirty scenario 5 | ['b'] | ['b'] | Passed |
| newer-edit-retains-dirty scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| composition-defers-save scenario 1 | True | True | Passed |
| composition-defers-save scenario 2 | True | True | Passed |
| composition-defers-save scenario 3 | True | True | Passed |
| composition-defers-save scenario 4 | False | False | Passed |
| composition-defers-save scenario 5 | True | False | Failed |
| composition-defers-save scenario 6 | False | False | Passed |
| save-completion-status scenario 1 | unsaved | unsaved | Passed |
| save-completion-status scenario 2 | saved | saved | Passed |
| save-completion-status scenario 3 | error | error | Passed |
| save-completion-status scenario 4 | saved | saved | Passed |
| save-completion-status scenario 5 | unsaved | unsaved | Passed |
| save-completion-status scenario 6 | conflict | conflict | Passed |
| next-save-revision scenario 1 | 3 | 3 | Passed |
| next-save-revision scenario 2 | None | None | Passed |
| next-save-revision scenario 3 | 2 | 2 | Passed |
| next-save-revision scenario 4 | None | None | Passed |
| next-save-revision scenario 5 | 3 | 3 | Passed |
| next-save-revision scenario 6 | None | None | Passed |
| unsent-field-difference scenario 1 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 2 | [] | [] | Passed |
| unsent-field-difference scenario 3 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 4 | [] | [] | Passed |
| unsent-field-difference scenario 5 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 6 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 1 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 2 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 3 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 4 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 5 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| save-payload-field-snapshot scenario 1 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 2 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 3 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 4 | [] | [] | Passed |
| save-payload-field-snapshot scenario 5 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| unacknowledged-edit-distance scenario 1 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 2 | 1 | 1 | Passed |
| unacknowledged-edit-distance scenario 3 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 4 | 0 | 0 | Passed |
| unacknowledged-edit-distance scenario 5 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 6 | 1 | 1 | Passed |
| resave-after-ack scenario 1 | True | True | Passed |
| resave-after-ack scenario 2 | False | False | Passed |
| resave-after-ack scenario 3 | False | False | Passed |
| resave-after-ack scenario 4 | False | False | Passed |
| resave-after-ack scenario 5 | False | False | Passed |
| resave-after-ack scenario 6 | False | False | Passed |
| many edits during conflicting save: acknowledge-sent-revision | 1 | 1 | Passed |
| many edits during conflicting save: newer-edit-retains-dirty | ['a', 'b'] | ['a', 'b'] | Passed |
| many edits during conflicting save: composition-defers-save | True | True | Passed |
| many edits during conflicting save: save-completion-status | conflict | conflict | Passed |
| many edits during conflicting save: next-save-revision | 6 | 6 | Passed |
| many edits during conflicting save: unsent-field-difference | ['b'] | ['b'] | Passed |
| many edits during conflicting save: conflict-preserves-local-fields | ['a', 'b'] | ['a', 'b'] | Passed |
| many edits during conflicting save: save-payload-field-snapshot | ['a'] | ['a'] | Passed |
| many edits during conflicting save: unacknowledged-edit-distance | 5 | 5 | Passed |
| many edits during conflicting save: resave-after-ack | False | False | Passed |
SHA-256 / a92abbd7aa5a6c2cd30c5a0b1f28a000368e0d637e03c27606604719ff6c368c
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(operation, s):
current, sent, acknowledged, dirty_fields, sent_fields, response, online, composing = s
if operation == 'acknowledge-sent-revision':
return sent if response=='ok' else acknowledged
if operation == 'newer-edit-retains-dirty':
return dirty_fields if current!=sent or response!='ok' else [f for f in dirty_fields if f not in sent_fields]
if operation == 'composition-defers-save':
return online and bool(dirty_fields) and not composing
if operation == 'save-completion-status':
return 'conflict' if response=='conflict' else ('error' if response=='failed' else ('saved' if current==sent else 'unsaved'))
if operation == 'next-save-revision':
return current if current>sent else None
if operation == 'unsent-field-difference':
return [f for f in dirty_fields if f not in sent_fields]
if operation == 'conflict-preserves-local-fields':
return dirty_fields if response=='conflict' else []
if operation == 'save-payload-field-snapshot':
return list(sent_fields)
if operation == 'unacknowledged-edit-distance':
return max(0,current-acknowledged)
if operation == 'resave-after-ack':
return response=='ok' and current>sent and online and not composing
raise ValueError('unknown modeled operation')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('acknowledge-sent-revision scenario 1', solve('acknowledge-sent-revision', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), N+1)
check('acknowledge-sent-revision scenario 2', solve('acknowledge-sent-revision', (1,1,0,['a'],['a'],'ok',True,False)), 1)
check('acknowledge-sent-revision scenario 3', solve('acknowledge-sent-revision', (2,1,0,['a','b'],['a'],'failed',True,False)), 0)
check('acknowledge-sent-revision scenario 4', solve('acknowledge-sent-revision', (0,0,0,[],[],'ok',True,True)), 0)
check('acknowledge-sent-revision scenario 5', solve('acknowledge-sent-revision', (3,2,1,['b'],['a'],'ok',False,False)), 2)
check('acknowledge-sent-revision scenario 6', solve('acknowledge-sent-revision', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 3)
check('newer-edit-retains-dirty scenario 1', solve('newer-edit-retains-dirty', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['a','b'])
check('newer-edit-retains-dirty scenario 2', solve('newer-edit-retains-dirty', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('newer-edit-retains-dirty scenario 3', solve('newer-edit-retains-dirty', (2,1,0,['a','b'],['a'],'failed',True,False)), ['a','b'])
check('newer-edit-retains-dirty scenario 4', solve('newer-edit-retains-dirty', (0,0,0,[],[],'ok',True,True)), [])
check('newer-edit-retains-dirty scenario 5', solve('newer-edit-retains-dirty', (3,2,1,['b'],['a'],'ok',False,False)), ['b'])
check('newer-edit-retains-dirty scenario 6', solve('newer-edit-retains-dirty', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('composition-defers-save scenario 1', solve('composition-defers-save', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), True)
check('composition-defers-save scenario 2', solve('composition-defers-save', (1,1,0,['a'],['a'],'ok',True,False)), True)
check('composition-defers-save scenario 3', solve('composition-defers-save', (2,1,0,['a','b'],['a'],'failed',True,False)), True)
check('composition-defers-save scenario 4', solve('composition-defers-save', (0,0,0,[],[],'ok',True,True)), False)
check('composition-defers-save scenario 5', solve('composition-defers-save', (3,2,1,['b'],['a'],'ok',False,False)), False)
check('composition-defers-save scenario 6', solve('composition-defers-save', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), False)
check('save-completion-status scenario 1', solve('save-completion-status', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), 'unsaved')
check('save-completion-status scenario 2', solve('save-completion-status', (1,1,0,['a'],['a'],'ok',True,False)), 'saved')
check('save-completion-status scenario 3', solve('save-completion-status', (2,1,0,['a','b'],['a'],'failed',True,False)), 'error')
check('save-completion-status scenario 4', solve('save-completion-status', (0,0,0,[],[],'ok',True,True)), 'saved')
check('save-completion-status scenario 5', solve('save-completion-status', (3,2,1,['b'],['a'],'ok',False,False)), 'unsaved')
check('save-completion-status scenario 6', solve('save-completion-status', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 'conflict')
check('next-save-revision scenario 1', solve('next-save-revision', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), N+2)
check('next-save-revision scenario 2', solve('next-save-revision', (1,1,0,['a'],['a'],'ok',True,False)), None)
check('next-save-revision scenario 3', solve('next-save-revision', (2,1,0,['a','b'],['a'],'failed',True,False)), 2)
check('next-save-revision scenario 4', solve('next-save-revision', (0,0,0,[],[],'ok',True,True)), None)
check('next-save-revision scenario 5', solve('next-save-revision', (3,2,1,['b'],['a'],'ok',False,False)), 3)
check('next-save-revision scenario 6', solve('next-save-revision', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), None)
check('unsent-field-difference scenario 1', solve('unsent-field-difference', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['b'])
check('unsent-field-difference scenario 2', solve('unsent-field-difference', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('unsent-field-difference scenario 3', solve('unsent-field-difference', (2,1,0,['a','b'],['a'],'failed',True,False)), ['b'])
check('unsent-field-difference scenario 4', solve('unsent-field-difference', (0,0,0,[],[],'ok',True,True)), [])
check('unsent-field-difference scenario 5', solve('unsent-field-difference', (3,2,1,['b'],['a'],'ok',False,False)), ['b'])
check('unsent-field-difference scenario 6', solve('unsent-field-difference', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), [])
check('conflict-preserves-local-fields scenario 1', solve('conflict-preserves-local-fields', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), [])
check('conflict-preserves-local-fields scenario 2', solve('conflict-preserves-local-fields', (1,1,0,['a'],['a'],'ok',True,False)), [])
check('conflict-preserves-local-fields scenario 3', solve('conflict-preserves-local-fields', (2,1,0,['a','b'],['a'],'failed',True,False)), [])
check('conflict-preserves-local-fields scenario 4', solve('conflict-preserves-local-fields', (0,0,0,[],[],'ok',True,True)), [])
check('conflict-preserves-local-fields scenario 5', solve('conflict-preserves-local-fields', (3,2,1,['b'],['a'],'ok',False,False)), [])
check('conflict-preserves-local-fields scenario 6', solve('conflict-preserves-local-fields', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('save-payload-field-snapshot scenario 1', solve('save-payload-field-snapshot', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), ['a'])
check('save-payload-field-snapshot scenario 2', solve('save-payload-field-snapshot', (1,1,0,['a'],['a'],'ok',True,False)), ['a'])
check('save-payload-field-snapshot scenario 3', solve('save-payload-field-snapshot', (2,1,0,['a','b'],['a'],'failed',True,False)), ['a'])
check('save-payload-field-snapshot scenario 4', solve('save-payload-field-snapshot', (0,0,0,[],[],'ok',True,True)), [])
check('save-payload-field-snapshot scenario 5', solve('save-payload-field-snapshot', (3,2,1,['b'],['a'],'ok',False,False)), ['a'])
check('save-payload-field-snapshot scenario 6', solve('save-payload-field-snapshot', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), ['a','b'])
check('unacknowledged-edit-distance scenario 1', solve('unacknowledged-edit-distance', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), 2)
check('unacknowledged-edit-distance scenario 2', solve('unacknowledged-edit-distance', (1,1,0,['a'],['a'],'ok',True,False)), 1)
check('unacknowledged-edit-distance scenario 3', solve('unacknowledged-edit-distance', (2,1,0,['a','b'],['a'],'failed',True,False)), 2)
check('unacknowledged-edit-distance scenario 4', solve('unacknowledged-edit-distance', (0,0,0,[],[],'ok',True,True)), 0)
check('unacknowledged-edit-distance scenario 5', solve('unacknowledged-edit-distance', (3,2,1,['b'],['a'],'ok',False,False)), 2)
check('unacknowledged-edit-distance scenario 6', solve('unacknowledged-edit-distance', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), 1)
check('resave-after-ack scenario 1', solve('resave-after-ack', (N+2,N+1,N,['a','b'],['a'],'ok',True,False)), True)
check('resave-after-ack scenario 2', solve('resave-after-ack', (1,1,0,['a'],['a'],'ok',True,False)), False)
check('resave-after-ack scenario 3', solve('resave-after-ack', (2,1,0,['a','b'],['a'],'failed',True,False)), False)
check('resave-after-ack scenario 4', solve('resave-after-ack', (0,0,0,[],[],'ok',True,True)), False)
check('resave-after-ack scenario 5', solve('resave-after-ack', (3,2,1,['b'],['a'],'ok',False,False)), False)
check('resave-after-ack scenario 6', solve('resave-after-ack', (4,4,3,['a','b'],['a','b'],'conflict',True,True)), False)
check('many edits during conflicting save: acknowledge-sent-revision', solve('acknowledge-sent-revision', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), 1)
check('many edits during conflicting save: newer-edit-retains-dirty', solve('newer-edit-retains-dirty', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a','b'])
check('many edits during conflicting save: composition-defers-save', solve('composition-defers-save', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), True)
check('many edits during conflicting save: save-completion-status', solve('save-completion-status', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), 'conflict')
check('many edits during conflicting save: next-save-revision', solve('next-save-revision', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), N+5)
check('many edits during conflicting save: unsent-field-difference', solve('unsent-field-difference', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['b'])
check('many edits during conflicting save: conflict-preserves-local-fields', solve('conflict-preserves-local-fields', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a','b'])
check('many edits during conflicting save: save-payload-field-snapshot', solve('save-payload-field-snapshot', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), ['a'])
check('many edits during conflicting save: unacknowledged-edit-distance', solve('unacknowledged-edit-distance', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), N+4)
check('many edits during conflicting save: resave-after-ack', solve('resave-after-ack', (N+5,2,1,['a','b'],['a'],'conflict',True,False)), False)
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 |
|---|---|---|---|
| acknowledge-sent-revision scenario 1 | 2 | 2 | Passed |
| acknowledge-sent-revision scenario 2 | 1 | 1 | Passed |
| acknowledge-sent-revision scenario 3 | 0 | 0 | Passed |
| acknowledge-sent-revision scenario 4 | 0 | 0 | Passed |
| acknowledge-sent-revision scenario 5 | 2 | 2 | Passed |
| acknowledge-sent-revision scenario 6 | 3 | 3 | Passed |
| newer-edit-retains-dirty scenario 1 | ['a', 'b'] | ['a', 'b'] | Passed |
| newer-edit-retains-dirty scenario 2 | [] | [] | Passed |
| newer-edit-retains-dirty scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| newer-edit-retains-dirty scenario 4 | [] | [] | Passed |
| newer-edit-retains-dirty scenario 5 | ['b'] | ['b'] | Passed |
| newer-edit-retains-dirty scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| composition-defers-save scenario 1 | True | True | Passed |
| composition-defers-save scenario 2 | True | True | Passed |
| composition-defers-save scenario 3 | True | True | Passed |
| composition-defers-save scenario 4 | False | False | Passed |
| composition-defers-save scenario 5 | False | False | Passed |
| composition-defers-save scenario 6 | False | False | Passed |
| save-completion-status scenario 1 | unsaved | unsaved | Passed |
| save-completion-status scenario 2 | saved | saved | Passed |
| save-completion-status scenario 3 | error | error | Passed |
| save-completion-status scenario 4 | saved | saved | Passed |
| save-completion-status scenario 5 | unsaved | unsaved | Passed |
| save-completion-status scenario 6 | conflict | conflict | Passed |
| next-save-revision scenario 1 | 3 | 3 | Passed |
| next-save-revision scenario 2 | None | None | Passed |
| next-save-revision scenario 3 | 2 | 2 | Passed |
| next-save-revision scenario 4 | None | None | Passed |
| next-save-revision scenario 5 | 3 | 3 | Passed |
| next-save-revision scenario 6 | None | None | Passed |
| unsent-field-difference scenario 1 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 2 | [] | [] | Passed |
| unsent-field-difference scenario 3 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 4 | [] | [] | Passed |
| unsent-field-difference scenario 5 | ['b'] | ['b'] | Passed |
| unsent-field-difference scenario 6 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 1 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 2 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 3 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 4 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 5 | [] | [] | Passed |
| conflict-preserves-local-fields scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| save-payload-field-snapshot scenario 1 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 2 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 3 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 4 | [] | [] | Passed |
| save-payload-field-snapshot scenario 5 | ['a'] | ['a'] | Passed |
| save-payload-field-snapshot scenario 6 | ['a', 'b'] | ['a', 'b'] | Passed |
| unacknowledged-edit-distance scenario 1 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 2 | 1 | 1 | Passed |
| unacknowledged-edit-distance scenario 3 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 4 | 0 | 0 | Passed |
| unacknowledged-edit-distance scenario 5 | 2 | 2 | Passed |
| unacknowledged-edit-distance scenario 6 | 1 | 1 | Passed |
| resave-after-ack scenario 1 | True | True | Passed |
| resave-after-ack scenario 2 | False | False | Passed |
| resave-after-ack scenario 3 | False | False | Passed |
| resave-after-ack scenario 4 | False | False | Passed |
| resave-after-ack scenario 5 | False | False | Passed |
| resave-after-ack scenario 6 | False | False | Passed |
| many edits during conflicting save: acknowledge-sent-revision | 1 | 1 | Passed |
| many edits during conflicting save: newer-edit-retains-dirty | ['a', 'b'] | ['a', 'b'] | Passed |
| many edits during conflicting save: composition-defers-save | True | True | Passed |
| many edits during conflicting save: save-completion-status | conflict | conflict | Passed |
| many edits during conflicting save: next-save-revision | 6 | 6 | Passed |
| many edits during conflicting save: unsent-field-difference | ['b'] | ['b'] | Passed |
| many edits during conflicting save: conflict-preserves-local-fields | ['a', 'b'] | ['a', 'b'] | Passed |
| many edits during conflicting save: save-payload-field-snapshot | ['a'] | ['a'] | Passed |
| many edits during conflicting save: unacknowledged-edit-distance | 5 | 5 | Passed |
| many edits during conflicting save: resave-after-ack | False | False | Passed |
SHA-256 / 08a8a8ddde8f114e5e3dc0e5bc7412bd59cf88cb35bc079dd634b8df7c76b591
Verification & scope
Only the explicitly specified operations and finite deterministic records are modeled; no browser or framework 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:40:56.463192+00:00.
Case digest / d65b6a1689d84746559917a5fbcebe23e5a4b5b98c1182d44a0af4e50e75b643