FA-24121 / Client state / Open access
Page freeze and resume lifecycle: Resume queue drain · case 01
Resume queue drain.
ROOT CAUSE
The resume-queue-drain client decision evaluates `queued` instead of `queued if event in ('resume','pageshow') else []`.
VERIFIED REPAIR
Apply the modeled resume-queue-drain rule: `queued if event in ('resume','pageshow') else []`.
Unsuccessful approach: The partial repair `queued if event=='pageshow' else []` still violates the explicit fixture contract.
Case contract
The stipulated page lifecycle distinguishes a cached pagehide from final disposal. Timers pause on hide/freeze, dirty snapshots flush on any pagehide, and resume/pageshow may revalidate and drain retained work. Operation resume-queue-drain 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):
event, persisted, dirty, active, queued, revision, observed = s
if operation == 'preserved-page-disposition':
return 'suspend' if event=='pagehide' and persisted else ('dispose' if event=='pagehide' else 'keep')
if operation == 'resume-revalidation':
return event in ('resume','pageshow') and (persisted or revision!=observed)
if operation == 'freeze-timer-shutdown':
return [x for x in active if x!='timer'] if event in ('freeze','pagehide') else active
if operation == 'dirty-pagehide-flush':
return dirty and event=='pagehide'
if operation == 'preserved-client-queue':
return queued if persisted or event!='pagehide' else []
if operation == 'resume-queue-drain':
return queued
if operation == 'resume-event-source':
return 'bfcache' if event=='pageshow' and persisted else ('thaw' if event=='resume' else 'ordinary')
if operation == 'resource-disposal-on-unload':
return active if event=='pagehide' and not persisted else []
if operation == 'suspended-work-reason':
return 'frozen' if event=='freeze' else ('cached' if event=='pagehide' and persisted else None)
if operation == 'revalidation-observed-version':
return revision if event in ('resume','pageshow') else observed
raise ValueError('unknown modeled operation')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('preserved-page-disposition scenario 1', solve('preserved-page-disposition', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'suspend')
check('preserved-page-disposition scenario 2', solve('preserved-page-disposition', ('pagehide',False,True,['timer'],[],1,1)), 'dispose')
check('preserved-page-disposition scenario 3', solve('preserved-page-disposition', ('pageshow',True,False,[],['a','b'],3,1)), 'keep')
check('preserved-page-disposition scenario 4', solve('preserved-page-disposition', ('pageshow',False,False,[],[],1,1)), 'keep')
check('preserved-page-disposition scenario 5', solve('preserved-page-disposition', ('freeze',False,True,['socket'],['a'],2,2)), 'keep')
check('preserved-page-disposition scenario 6', solve('preserved-page-disposition', ('resume',False,True,['timer'],['a'],2,3)), 'keep')
check('resume-revalidation scenario 1', solve('resume-revalidation', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), False)
check('resume-revalidation scenario 2', solve('resume-revalidation', ('pagehide',False,True,['timer'],[],1,1)), False)
check('resume-revalidation scenario 3', solve('resume-revalidation', ('pageshow',True,False,[],['a','b'],3,1)), True)
check('resume-revalidation scenario 4', solve('resume-revalidation', ('pageshow',False,False,[],[],1,1)), False)
check('resume-revalidation scenario 5', solve('resume-revalidation', ('freeze',False,True,['socket'],['a'],2,2)), False)
check('resume-revalidation scenario 6', solve('resume-revalidation', ('resume',False,True,['timer'],['a'],2,3)), True)
check('freeze-timer-shutdown scenario 1', solve('freeze-timer-shutdown', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), ['socket'])
check('freeze-timer-shutdown scenario 2', solve('freeze-timer-shutdown', ('pagehide',False,True,['timer'],[],1,1)), [])
check('freeze-timer-shutdown scenario 3', solve('freeze-timer-shutdown', ('pageshow',True,False,[],['a','b'],3,1)), [])
check('freeze-timer-shutdown scenario 4', solve('freeze-timer-shutdown', ('pageshow',False,False,[],[],1,1)), [])
check('freeze-timer-shutdown scenario 5', solve('freeze-timer-shutdown', ('freeze',False,True,['socket'],['a'],2,2)), ['socket'])
check('freeze-timer-shutdown scenario 6', solve('freeze-timer-shutdown', ('resume',False,True,['timer'],['a'],2,3)), ['timer'])
check('dirty-pagehide-flush scenario 1', solve('dirty-pagehide-flush', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), True)
check('dirty-pagehide-flush scenario 2', solve('dirty-pagehide-flush', ('pagehide',False,True,['timer'],[],1,1)), True)
check('dirty-pagehide-flush scenario 3', solve('dirty-pagehide-flush', ('pageshow',True,False,[],['a','b'],3,1)), False)
check('dirty-pagehide-flush scenario 4', solve('dirty-pagehide-flush', ('pageshow',False,False,[],[],1,1)), False)
check('dirty-pagehide-flush scenario 5', solve('dirty-pagehide-flush', ('freeze',False,True,['socket'],['a'],2,2)), False)
check('dirty-pagehide-flush scenario 6', solve('dirty-pagehide-flush', ('resume',False,True,['timer'],['a'],2,3)), False)
check('preserved-client-queue scenario 1', solve('preserved-client-queue', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), ['a']*N)
check('preserved-client-queue scenario 2', solve('preserved-client-queue', ('pagehide',False,True,['timer'],[],1,1)), [])
check('preserved-client-queue scenario 3', solve('preserved-client-queue', ('pageshow',True,False,[],['a','b'],3,1)), ['a','b'])
check('preserved-client-queue scenario 4', solve('preserved-client-queue', ('pageshow',False,False,[],[],1,1)), [])
check('preserved-client-queue scenario 5', solve('preserved-client-queue', ('freeze',False,True,['socket'],['a'],2,2)), ['a'])
check('preserved-client-queue scenario 6', solve('preserved-client-queue', ('resume',False,True,['timer'],['a'],2,3)), ['a'])
check('resume-queue-drain scenario 1', solve('resume-queue-drain', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), [])
check('resume-queue-drain scenario 2', solve('resume-queue-drain', ('pagehide',False,True,['timer'],[],1,1)), [])
check('resume-queue-drain scenario 3', solve('resume-queue-drain', ('pageshow',True,False,[],['a','b'],3,1)), ['a','b'])
check('resume-queue-drain scenario 4', solve('resume-queue-drain', ('pageshow',False,False,[],[],1,1)), [])
check('resume-queue-drain scenario 5', solve('resume-queue-drain', ('freeze',False,True,['socket'],['a'],2,2)), [])
check('resume-queue-drain scenario 6', solve('resume-queue-drain', ('resume',False,True,['timer'],['a'],2,3)), ['a'])
check('resume-event-source scenario 1', solve('resume-event-source', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'ordinary')
check('resume-event-source scenario 2', solve('resume-event-source', ('pagehide',False,True,['timer'],[],1,1)), 'ordinary')
check('resume-event-source scenario 3', solve('resume-event-source', ('pageshow',True,False,[],['a','b'],3,1)), 'bfcache')
check('resume-event-source scenario 4', solve('resume-event-source', ('pageshow',False,False,[],[],1,1)), 'ordinary')
check('resume-event-source scenario 5', solve('resume-event-source', ('freeze',False,True,['socket'],['a'],2,2)), 'ordinary')
check('resume-event-source scenario 6', solve('resume-event-source', ('resume',False,True,['timer'],['a'],2,3)), 'thaw')
check('resource-disposal-on-unload scenario 1', solve('resource-disposal-on-unload', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), [])
check('resource-disposal-on-unload scenario 2', solve('resource-disposal-on-unload', ('pagehide',False,True,['timer'],[],1,1)), ['timer'])
check('resource-disposal-on-unload scenario 3', solve('resource-disposal-on-unload', ('pageshow',True,False,[],['a','b'],3,1)), [])
check('resource-disposal-on-unload scenario 4', solve('resource-disposal-on-unload', ('pageshow',False,False,[],[],1,1)), [])
check('resource-disposal-on-unload scenario 5', solve('resource-disposal-on-unload', ('freeze',False,True,['socket'],['a'],2,2)), [])
check('resource-disposal-on-unload scenario 6', solve('resource-disposal-on-unload', ('resume',False,True,['timer'],['a'],2,3)), [])
check('suspended-work-reason scenario 1', solve('suspended-work-reason', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'cached')
check('suspended-work-reason scenario 2', solve('suspended-work-reason', ('pagehide',False,True,['timer'],[],1,1)), None)
check('suspended-work-reason scenario 3', solve('suspended-work-reason', ('pageshow',True,False,[],['a','b'],3,1)), None)
check('suspended-work-reason scenario 4', solve('suspended-work-reason', ('pageshow',False,False,[],[],1,1)), None)
check('suspended-work-reason scenario 5', solve('suspended-work-reason', ('freeze',False,True,['socket'],['a'],2,2)), 'frozen')
check('suspended-work-reason scenario 6', solve('suspended-work-reason', ('resume',False,True,['timer'],['a'],2,3)), None)
check('revalidation-observed-version scenario 1', solve('revalidation-observed-version', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 2)
check('revalidation-observed-version scenario 2', solve('revalidation-observed-version', ('pagehide',False,True,['timer'],[],1,1)), 1)
check('revalidation-observed-version scenario 3', solve('revalidation-observed-version', ('pageshow',True,False,[],['a','b'],3,1)), 3)
check('revalidation-observed-version scenario 4', solve('revalidation-observed-version', ('pageshow',False,False,[],[],1,1)), 1)
check('revalidation-observed-version scenario 5', solve('revalidation-observed-version', ('freeze',False,True,['socket'],['a'],2,2)), 2)
check('revalidation-observed-version scenario 6', solve('revalidation-observed-version', ('resume',False,True,['timer'],['a'],2,3)), 2)
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 |
|---|---|---|---|
| preserved-page-disposition scenario 1 | suspend | suspend | Passed |
| preserved-page-disposition scenario 2 | dispose | dispose | Passed |
| preserved-page-disposition scenario 3 | keep | keep | Passed |
| preserved-page-disposition scenario 4 | keep | keep | Passed |
| preserved-page-disposition scenario 5 | keep | keep | Passed |
| preserved-page-disposition scenario 6 | keep | keep | Passed |
| resume-revalidation scenario 1 | False | False | Passed |
| resume-revalidation scenario 2 | False | False | Passed |
| resume-revalidation scenario 3 | True | True | Passed |
| resume-revalidation scenario 4 | False | False | Passed |
| resume-revalidation scenario 5 | False | False | Passed |
| resume-revalidation scenario 6 | True | True | Passed |
| freeze-timer-shutdown scenario 1 | ['socket'] | ['socket'] | Passed |
| freeze-timer-shutdown scenario 2 | [] | [] | Passed |
| freeze-timer-shutdown scenario 3 | [] | [] | Passed |
| freeze-timer-shutdown scenario 4 | [] | [] | Passed |
| freeze-timer-shutdown scenario 5 | ['socket'] | ['socket'] | Passed |
| freeze-timer-shutdown scenario 6 | ['timer'] | ['timer'] | Passed |
| dirty-pagehide-flush scenario 1 | True | True | Passed |
| dirty-pagehide-flush scenario 2 | True | True | Passed |
| dirty-pagehide-flush scenario 3 | False | False | Passed |
| dirty-pagehide-flush scenario 4 | False | False | Passed |
| dirty-pagehide-flush scenario 5 | False | False | Passed |
| dirty-pagehide-flush scenario 6 | False | False | Passed |
| preserved-client-queue scenario 1 | ['a'] | ['a'] | Passed |
| preserved-client-queue scenario 2 | [] | [] | Passed |
| preserved-client-queue scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| preserved-client-queue scenario 4 | [] | [] | Passed |
| preserved-client-queue scenario 5 | ['a'] | ['a'] | Passed |
| preserved-client-queue scenario 6 | ['a'] | ['a'] | Passed |
| resume-queue-drain scenario 1 | ['a'] | [] | Failed |
| resume-queue-drain scenario 2 | [] | [] | Passed |
| resume-queue-drain scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| resume-queue-drain scenario 4 | [] | [] | Passed |
| resume-queue-drain scenario 5 | ['a'] | [] | Failed |
| resume-queue-drain scenario 6 | ['a'] | ['a'] | Passed |
| resume-event-source scenario 1 | ordinary | ordinary | Passed |
| resume-event-source scenario 2 | ordinary | ordinary | Passed |
| resume-event-source scenario 3 | bfcache | bfcache | Passed |
| resume-event-source scenario 4 | ordinary | ordinary | Passed |
| resume-event-source scenario 5 | ordinary | ordinary | Passed |
| resume-event-source scenario 6 | thaw | thaw | Passed |
| resource-disposal-on-unload scenario 1 | [] | [] | Passed |
| resource-disposal-on-unload scenario 2 | ['timer'] | ['timer'] | Passed |
| resource-disposal-on-unload scenario 3 | [] | [] | Passed |
| resource-disposal-on-unload scenario 4 | [] | [] | Passed |
| resource-disposal-on-unload scenario 5 | [] | [] | Passed |
| resource-disposal-on-unload scenario 6 | [] | [] | Passed |
| suspended-work-reason scenario 1 | cached | cached | Passed |
| suspended-work-reason scenario 2 | None | None | Passed |
| suspended-work-reason scenario 3 | None | None | Passed |
| suspended-work-reason scenario 4 | None | None | Passed |
| suspended-work-reason scenario 5 | frozen | frozen | Passed |
| suspended-work-reason scenario 6 | None | None | Passed |
| revalidation-observed-version scenario 1 | 2 | 2 | Passed |
| revalidation-observed-version scenario 2 | 1 | 1 | Passed |
| revalidation-observed-version scenario 3 | 3 | 3 | Passed |
| revalidation-observed-version scenario 4 | 1 | 1 | Passed |
| revalidation-observed-version scenario 5 | 2 | 2 | Passed |
| revalidation-observed-version scenario 6 | 2 | 2 | Passed |
SHA-256 / a13d98ffbf9dd6d32c9f18f42f31b2916cb19bd75d830657c7eb4ea8dac89a9f
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(operation, s):
event, persisted, dirty, active, queued, revision, observed = s
if operation == 'preserved-page-disposition':
return 'suspend' if event=='pagehide' and persisted else ('dispose' if event=='pagehide' else 'keep')
if operation == 'resume-revalidation':
return event in ('resume','pageshow') and (persisted or revision!=observed)
if operation == 'freeze-timer-shutdown':
return [x for x in active if x!='timer'] if event in ('freeze','pagehide') else active
if operation == 'dirty-pagehide-flush':
return dirty and event=='pagehide'
if operation == 'preserved-client-queue':
return queued if persisted or event!='pagehide' else []
if operation == 'resume-queue-drain':
return queued if event=='pageshow' else []
if operation == 'resume-event-source':
return 'bfcache' if event=='pageshow' and persisted else ('thaw' if event=='resume' else 'ordinary')
if operation == 'resource-disposal-on-unload':
return active if event=='pagehide' and not persisted else []
if operation == 'suspended-work-reason':
return 'frozen' if event=='freeze' else ('cached' if event=='pagehide' and persisted else None)
if operation == 'revalidation-observed-version':
return revision if event in ('resume','pageshow') else observed
raise ValueError('unknown modeled operation')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('preserved-page-disposition scenario 1', solve('preserved-page-disposition', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'suspend')
check('preserved-page-disposition scenario 2', solve('preserved-page-disposition', ('pagehide',False,True,['timer'],[],1,1)), 'dispose')
check('preserved-page-disposition scenario 3', solve('preserved-page-disposition', ('pageshow',True,False,[],['a','b'],3,1)), 'keep')
check('preserved-page-disposition scenario 4', solve('preserved-page-disposition', ('pageshow',False,False,[],[],1,1)), 'keep')
check('preserved-page-disposition scenario 5', solve('preserved-page-disposition', ('freeze',False,True,['socket'],['a'],2,2)), 'keep')
check('preserved-page-disposition scenario 6', solve('preserved-page-disposition', ('resume',False,True,['timer'],['a'],2,3)), 'keep')
check('resume-revalidation scenario 1', solve('resume-revalidation', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), False)
check('resume-revalidation scenario 2', solve('resume-revalidation', ('pagehide',False,True,['timer'],[],1,1)), False)
check('resume-revalidation scenario 3', solve('resume-revalidation', ('pageshow',True,False,[],['a','b'],3,1)), True)
check('resume-revalidation scenario 4', solve('resume-revalidation', ('pageshow',False,False,[],[],1,1)), False)
check('resume-revalidation scenario 5', solve('resume-revalidation', ('freeze',False,True,['socket'],['a'],2,2)), False)
check('resume-revalidation scenario 6', solve('resume-revalidation', ('resume',False,True,['timer'],['a'],2,3)), True)
check('freeze-timer-shutdown scenario 1', solve('freeze-timer-shutdown', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), ['socket'])
check('freeze-timer-shutdown scenario 2', solve('freeze-timer-shutdown', ('pagehide',False,True,['timer'],[],1,1)), [])
check('freeze-timer-shutdown scenario 3', solve('freeze-timer-shutdown', ('pageshow',True,False,[],['a','b'],3,1)), [])
check('freeze-timer-shutdown scenario 4', solve('freeze-timer-shutdown', ('pageshow',False,False,[],[],1,1)), [])
check('freeze-timer-shutdown scenario 5', solve('freeze-timer-shutdown', ('freeze',False,True,['socket'],['a'],2,2)), ['socket'])
check('freeze-timer-shutdown scenario 6', solve('freeze-timer-shutdown', ('resume',False,True,['timer'],['a'],2,3)), ['timer'])
check('dirty-pagehide-flush scenario 1', solve('dirty-pagehide-flush', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), True)
check('dirty-pagehide-flush scenario 2', solve('dirty-pagehide-flush', ('pagehide',False,True,['timer'],[],1,1)), True)
check('dirty-pagehide-flush scenario 3', solve('dirty-pagehide-flush', ('pageshow',True,False,[],['a','b'],3,1)), False)
check('dirty-pagehide-flush scenario 4', solve('dirty-pagehide-flush', ('pageshow',False,False,[],[],1,1)), False)
check('dirty-pagehide-flush scenario 5', solve('dirty-pagehide-flush', ('freeze',False,True,['socket'],['a'],2,2)), False)
check('dirty-pagehide-flush scenario 6', solve('dirty-pagehide-flush', ('resume',False,True,['timer'],['a'],2,3)), False)
check('preserved-client-queue scenario 1', solve('preserved-client-queue', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), ['a']*N)
check('preserved-client-queue scenario 2', solve('preserved-client-queue', ('pagehide',False,True,['timer'],[],1,1)), [])
check('preserved-client-queue scenario 3', solve('preserved-client-queue', ('pageshow',True,False,[],['a','b'],3,1)), ['a','b'])
check('preserved-client-queue scenario 4', solve('preserved-client-queue', ('pageshow',False,False,[],[],1,1)), [])
check('preserved-client-queue scenario 5', solve('preserved-client-queue', ('freeze',False,True,['socket'],['a'],2,2)), ['a'])
check('preserved-client-queue scenario 6', solve('preserved-client-queue', ('resume',False,True,['timer'],['a'],2,3)), ['a'])
check('resume-queue-drain scenario 1', solve('resume-queue-drain', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), [])
check('resume-queue-drain scenario 2', solve('resume-queue-drain', ('pagehide',False,True,['timer'],[],1,1)), [])
check('resume-queue-drain scenario 3', solve('resume-queue-drain', ('pageshow',True,False,[],['a','b'],3,1)), ['a','b'])
check('resume-queue-drain scenario 4', solve('resume-queue-drain', ('pageshow',False,False,[],[],1,1)), [])
check('resume-queue-drain scenario 5', solve('resume-queue-drain', ('freeze',False,True,['socket'],['a'],2,2)), [])
check('resume-queue-drain scenario 6', solve('resume-queue-drain', ('resume',False,True,['timer'],['a'],2,3)), ['a'])
check('resume-event-source scenario 1', solve('resume-event-source', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'ordinary')
check('resume-event-source scenario 2', solve('resume-event-source', ('pagehide',False,True,['timer'],[],1,1)), 'ordinary')
check('resume-event-source scenario 3', solve('resume-event-source', ('pageshow',True,False,[],['a','b'],3,1)), 'bfcache')
check('resume-event-source scenario 4', solve('resume-event-source', ('pageshow',False,False,[],[],1,1)), 'ordinary')
check('resume-event-source scenario 5', solve('resume-event-source', ('freeze',False,True,['socket'],['a'],2,2)), 'ordinary')
check('resume-event-source scenario 6', solve('resume-event-source', ('resume',False,True,['timer'],['a'],2,3)), 'thaw')
check('resource-disposal-on-unload scenario 1', solve('resource-disposal-on-unload', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), [])
check('resource-disposal-on-unload scenario 2', solve('resource-disposal-on-unload', ('pagehide',False,True,['timer'],[],1,1)), ['timer'])
check('resource-disposal-on-unload scenario 3', solve('resource-disposal-on-unload', ('pageshow',True,False,[],['a','b'],3,1)), [])
check('resource-disposal-on-unload scenario 4', solve('resource-disposal-on-unload', ('pageshow',False,False,[],[],1,1)), [])
check('resource-disposal-on-unload scenario 5', solve('resource-disposal-on-unload', ('freeze',False,True,['socket'],['a'],2,2)), [])
check('resource-disposal-on-unload scenario 6', solve('resource-disposal-on-unload', ('resume',False,True,['timer'],['a'],2,3)), [])
check('suspended-work-reason scenario 1', solve('suspended-work-reason', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'cached')
check('suspended-work-reason scenario 2', solve('suspended-work-reason', ('pagehide',False,True,['timer'],[],1,1)), None)
check('suspended-work-reason scenario 3', solve('suspended-work-reason', ('pageshow',True,False,[],['a','b'],3,1)), None)
check('suspended-work-reason scenario 4', solve('suspended-work-reason', ('pageshow',False,False,[],[],1,1)), None)
check('suspended-work-reason scenario 5', solve('suspended-work-reason', ('freeze',False,True,['socket'],['a'],2,2)), 'frozen')
check('suspended-work-reason scenario 6', solve('suspended-work-reason', ('resume',False,True,['timer'],['a'],2,3)), None)
check('revalidation-observed-version scenario 1', solve('revalidation-observed-version', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 2)
check('revalidation-observed-version scenario 2', solve('revalidation-observed-version', ('pagehide',False,True,['timer'],[],1,1)), 1)
check('revalidation-observed-version scenario 3', solve('revalidation-observed-version', ('pageshow',True,False,[],['a','b'],3,1)), 3)
check('revalidation-observed-version scenario 4', solve('revalidation-observed-version', ('pageshow',False,False,[],[],1,1)), 1)
check('revalidation-observed-version scenario 5', solve('revalidation-observed-version', ('freeze',False,True,['socket'],['a'],2,2)), 2)
check('revalidation-observed-version scenario 6', solve('revalidation-observed-version', ('resume',False,True,['timer'],['a'],2,3)), 2)
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 |
|---|---|---|---|
| preserved-page-disposition scenario 1 | suspend | suspend | Passed |
| preserved-page-disposition scenario 2 | dispose | dispose | Passed |
| preserved-page-disposition scenario 3 | keep | keep | Passed |
| preserved-page-disposition scenario 4 | keep | keep | Passed |
| preserved-page-disposition scenario 5 | keep | keep | Passed |
| preserved-page-disposition scenario 6 | keep | keep | Passed |
| resume-revalidation scenario 1 | False | False | Passed |
| resume-revalidation scenario 2 | False | False | Passed |
| resume-revalidation scenario 3 | True | True | Passed |
| resume-revalidation scenario 4 | False | False | Passed |
| resume-revalidation scenario 5 | False | False | Passed |
| resume-revalidation scenario 6 | True | True | Passed |
| freeze-timer-shutdown scenario 1 | ['socket'] | ['socket'] | Passed |
| freeze-timer-shutdown scenario 2 | [] | [] | Passed |
| freeze-timer-shutdown scenario 3 | [] | [] | Passed |
| freeze-timer-shutdown scenario 4 | [] | [] | Passed |
| freeze-timer-shutdown scenario 5 | ['socket'] | ['socket'] | Passed |
| freeze-timer-shutdown scenario 6 | ['timer'] | ['timer'] | Passed |
| dirty-pagehide-flush scenario 1 | True | True | Passed |
| dirty-pagehide-flush scenario 2 | True | True | Passed |
| dirty-pagehide-flush scenario 3 | False | False | Passed |
| dirty-pagehide-flush scenario 4 | False | False | Passed |
| dirty-pagehide-flush scenario 5 | False | False | Passed |
| dirty-pagehide-flush scenario 6 | False | False | Passed |
| preserved-client-queue scenario 1 | ['a'] | ['a'] | Passed |
| preserved-client-queue scenario 2 | [] | [] | Passed |
| preserved-client-queue scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| preserved-client-queue scenario 4 | [] | [] | Passed |
| preserved-client-queue scenario 5 | ['a'] | ['a'] | Passed |
| preserved-client-queue scenario 6 | ['a'] | ['a'] | Passed |
| resume-queue-drain scenario 1 | [] | [] | Passed |
| resume-queue-drain scenario 2 | [] | [] | Passed |
| resume-queue-drain scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| resume-queue-drain scenario 4 | [] | [] | Passed |
| resume-queue-drain scenario 5 | [] | [] | Passed |
| resume-queue-drain scenario 6 | [] | ['a'] | Failed |
| resume-event-source scenario 1 | ordinary | ordinary | Passed |
| resume-event-source scenario 2 | ordinary | ordinary | Passed |
| resume-event-source scenario 3 | bfcache | bfcache | Passed |
| resume-event-source scenario 4 | ordinary | ordinary | Passed |
| resume-event-source scenario 5 | ordinary | ordinary | Passed |
| resume-event-source scenario 6 | thaw | thaw | Passed |
| resource-disposal-on-unload scenario 1 | [] | [] | Passed |
| resource-disposal-on-unload scenario 2 | ['timer'] | ['timer'] | Passed |
| resource-disposal-on-unload scenario 3 | [] | [] | Passed |
| resource-disposal-on-unload scenario 4 | [] | [] | Passed |
| resource-disposal-on-unload scenario 5 | [] | [] | Passed |
| resource-disposal-on-unload scenario 6 | [] | [] | Passed |
| suspended-work-reason scenario 1 | cached | cached | Passed |
| suspended-work-reason scenario 2 | None | None | Passed |
| suspended-work-reason scenario 3 | None | None | Passed |
| suspended-work-reason scenario 4 | None | None | Passed |
| suspended-work-reason scenario 5 | frozen | frozen | Passed |
| suspended-work-reason scenario 6 | None | None | Passed |
| revalidation-observed-version scenario 1 | 2 | 2 | Passed |
| revalidation-observed-version scenario 2 | 1 | 1 | Passed |
| revalidation-observed-version scenario 3 | 3 | 3 | Passed |
| revalidation-observed-version scenario 4 | 1 | 1 | Passed |
| revalidation-observed-version scenario 5 | 2 | 2 | Passed |
| revalidation-observed-version scenario 6 | 2 | 2 | Passed |
SHA-256 / ac29bd0e77cc69a9410126d5964171f9c6ede16f9b642649b20552f7a257083b
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(operation, s):
event, persisted, dirty, active, queued, revision, observed = s
if operation == 'preserved-page-disposition':
return 'suspend' if event=='pagehide' and persisted else ('dispose' if event=='pagehide' else 'keep')
if operation == 'resume-revalidation':
return event in ('resume','pageshow') and (persisted or revision!=observed)
if operation == 'freeze-timer-shutdown':
return [x for x in active if x!='timer'] if event in ('freeze','pagehide') else active
if operation == 'dirty-pagehide-flush':
return dirty and event=='pagehide'
if operation == 'preserved-client-queue':
return queued if persisted or event!='pagehide' else []
if operation == 'resume-queue-drain':
return queued if event in ('resume','pageshow') else []
if operation == 'resume-event-source':
return 'bfcache' if event=='pageshow' and persisted else ('thaw' if event=='resume' else 'ordinary')
if operation == 'resource-disposal-on-unload':
return active if event=='pagehide' and not persisted else []
if operation == 'suspended-work-reason':
return 'frozen' if event=='freeze' else ('cached' if event=='pagehide' and persisted else None)
if operation == 'revalidation-observed-version':
return revision if event in ('resume','pageshow') else observed
raise ValueError('unknown modeled operation')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('preserved-page-disposition scenario 1', solve('preserved-page-disposition', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'suspend')
check('preserved-page-disposition scenario 2', solve('preserved-page-disposition', ('pagehide',False,True,['timer'],[],1,1)), 'dispose')
check('preserved-page-disposition scenario 3', solve('preserved-page-disposition', ('pageshow',True,False,[],['a','b'],3,1)), 'keep')
check('preserved-page-disposition scenario 4', solve('preserved-page-disposition', ('pageshow',False,False,[],[],1,1)), 'keep')
check('preserved-page-disposition scenario 5', solve('preserved-page-disposition', ('freeze',False,True,['socket'],['a'],2,2)), 'keep')
check('preserved-page-disposition scenario 6', solve('preserved-page-disposition', ('resume',False,True,['timer'],['a'],2,3)), 'keep')
check('resume-revalidation scenario 1', solve('resume-revalidation', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), False)
check('resume-revalidation scenario 2', solve('resume-revalidation', ('pagehide',False,True,['timer'],[],1,1)), False)
check('resume-revalidation scenario 3', solve('resume-revalidation', ('pageshow',True,False,[],['a','b'],3,1)), True)
check('resume-revalidation scenario 4', solve('resume-revalidation', ('pageshow',False,False,[],[],1,1)), False)
check('resume-revalidation scenario 5', solve('resume-revalidation', ('freeze',False,True,['socket'],['a'],2,2)), False)
check('resume-revalidation scenario 6', solve('resume-revalidation', ('resume',False,True,['timer'],['a'],2,3)), True)
check('freeze-timer-shutdown scenario 1', solve('freeze-timer-shutdown', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), ['socket'])
check('freeze-timer-shutdown scenario 2', solve('freeze-timer-shutdown', ('pagehide',False,True,['timer'],[],1,1)), [])
check('freeze-timer-shutdown scenario 3', solve('freeze-timer-shutdown', ('pageshow',True,False,[],['a','b'],3,1)), [])
check('freeze-timer-shutdown scenario 4', solve('freeze-timer-shutdown', ('pageshow',False,False,[],[],1,1)), [])
check('freeze-timer-shutdown scenario 5', solve('freeze-timer-shutdown', ('freeze',False,True,['socket'],['a'],2,2)), ['socket'])
check('freeze-timer-shutdown scenario 6', solve('freeze-timer-shutdown', ('resume',False,True,['timer'],['a'],2,3)), ['timer'])
check('dirty-pagehide-flush scenario 1', solve('dirty-pagehide-flush', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), True)
check('dirty-pagehide-flush scenario 2', solve('dirty-pagehide-flush', ('pagehide',False,True,['timer'],[],1,1)), True)
check('dirty-pagehide-flush scenario 3', solve('dirty-pagehide-flush', ('pageshow',True,False,[],['a','b'],3,1)), False)
check('dirty-pagehide-flush scenario 4', solve('dirty-pagehide-flush', ('pageshow',False,False,[],[],1,1)), False)
check('dirty-pagehide-flush scenario 5', solve('dirty-pagehide-flush', ('freeze',False,True,['socket'],['a'],2,2)), False)
check('dirty-pagehide-flush scenario 6', solve('dirty-pagehide-flush', ('resume',False,True,['timer'],['a'],2,3)), False)
check('preserved-client-queue scenario 1', solve('preserved-client-queue', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), ['a']*N)
check('preserved-client-queue scenario 2', solve('preserved-client-queue', ('pagehide',False,True,['timer'],[],1,1)), [])
check('preserved-client-queue scenario 3', solve('preserved-client-queue', ('pageshow',True,False,[],['a','b'],3,1)), ['a','b'])
check('preserved-client-queue scenario 4', solve('preserved-client-queue', ('pageshow',False,False,[],[],1,1)), [])
check('preserved-client-queue scenario 5', solve('preserved-client-queue', ('freeze',False,True,['socket'],['a'],2,2)), ['a'])
check('preserved-client-queue scenario 6', solve('preserved-client-queue', ('resume',False,True,['timer'],['a'],2,3)), ['a'])
check('resume-queue-drain scenario 1', solve('resume-queue-drain', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), [])
check('resume-queue-drain scenario 2', solve('resume-queue-drain', ('pagehide',False,True,['timer'],[],1,1)), [])
check('resume-queue-drain scenario 3', solve('resume-queue-drain', ('pageshow',True,False,[],['a','b'],3,1)), ['a','b'])
check('resume-queue-drain scenario 4', solve('resume-queue-drain', ('pageshow',False,False,[],[],1,1)), [])
check('resume-queue-drain scenario 5', solve('resume-queue-drain', ('freeze',False,True,['socket'],['a'],2,2)), [])
check('resume-queue-drain scenario 6', solve('resume-queue-drain', ('resume',False,True,['timer'],['a'],2,3)), ['a'])
check('resume-event-source scenario 1', solve('resume-event-source', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'ordinary')
check('resume-event-source scenario 2', solve('resume-event-source', ('pagehide',False,True,['timer'],[],1,1)), 'ordinary')
check('resume-event-source scenario 3', solve('resume-event-source', ('pageshow',True,False,[],['a','b'],3,1)), 'bfcache')
check('resume-event-source scenario 4', solve('resume-event-source', ('pageshow',False,False,[],[],1,1)), 'ordinary')
check('resume-event-source scenario 5', solve('resume-event-source', ('freeze',False,True,['socket'],['a'],2,2)), 'ordinary')
check('resume-event-source scenario 6', solve('resume-event-source', ('resume',False,True,['timer'],['a'],2,3)), 'thaw')
check('resource-disposal-on-unload scenario 1', solve('resource-disposal-on-unload', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), [])
check('resource-disposal-on-unload scenario 2', solve('resource-disposal-on-unload', ('pagehide',False,True,['timer'],[],1,1)), ['timer'])
check('resource-disposal-on-unload scenario 3', solve('resource-disposal-on-unload', ('pageshow',True,False,[],['a','b'],3,1)), [])
check('resource-disposal-on-unload scenario 4', solve('resource-disposal-on-unload', ('pageshow',False,False,[],[],1,1)), [])
check('resource-disposal-on-unload scenario 5', solve('resource-disposal-on-unload', ('freeze',False,True,['socket'],['a'],2,2)), [])
check('resource-disposal-on-unload scenario 6', solve('resource-disposal-on-unload', ('resume',False,True,['timer'],['a'],2,3)), [])
check('suspended-work-reason scenario 1', solve('suspended-work-reason', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 'cached')
check('suspended-work-reason scenario 2', solve('suspended-work-reason', ('pagehide',False,True,['timer'],[],1,1)), None)
check('suspended-work-reason scenario 3', solve('suspended-work-reason', ('pageshow',True,False,[],['a','b'],3,1)), None)
check('suspended-work-reason scenario 4', solve('suspended-work-reason', ('pageshow',False,False,[],[],1,1)), None)
check('suspended-work-reason scenario 5', solve('suspended-work-reason', ('freeze',False,True,['socket'],['a'],2,2)), 'frozen')
check('suspended-work-reason scenario 6', solve('suspended-work-reason', ('resume',False,True,['timer'],['a'],2,3)), None)
check('revalidation-observed-version scenario 1', solve('revalidation-observed-version', ('pagehide',True,True,['timer','socket'],['a']*N,3,2)), 2)
check('revalidation-observed-version scenario 2', solve('revalidation-observed-version', ('pagehide',False,True,['timer'],[],1,1)), 1)
check('revalidation-observed-version scenario 3', solve('revalidation-observed-version', ('pageshow',True,False,[],['a','b'],3,1)), 3)
check('revalidation-observed-version scenario 4', solve('revalidation-observed-version', ('pageshow',False,False,[],[],1,1)), 1)
check('revalidation-observed-version scenario 5', solve('revalidation-observed-version', ('freeze',False,True,['socket'],['a'],2,2)), 2)
check('revalidation-observed-version scenario 6', solve('revalidation-observed-version', ('resume',False,True,['timer'],['a'],2,3)), 2)
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 |
|---|---|---|---|
| preserved-page-disposition scenario 1 | suspend | suspend | Passed |
| preserved-page-disposition scenario 2 | dispose | dispose | Passed |
| preserved-page-disposition scenario 3 | keep | keep | Passed |
| preserved-page-disposition scenario 4 | keep | keep | Passed |
| preserved-page-disposition scenario 5 | keep | keep | Passed |
| preserved-page-disposition scenario 6 | keep | keep | Passed |
| resume-revalidation scenario 1 | False | False | Passed |
| resume-revalidation scenario 2 | False | False | Passed |
| resume-revalidation scenario 3 | True | True | Passed |
| resume-revalidation scenario 4 | False | False | Passed |
| resume-revalidation scenario 5 | False | False | Passed |
| resume-revalidation scenario 6 | True | True | Passed |
| freeze-timer-shutdown scenario 1 | ['socket'] | ['socket'] | Passed |
| freeze-timer-shutdown scenario 2 | [] | [] | Passed |
| freeze-timer-shutdown scenario 3 | [] | [] | Passed |
| freeze-timer-shutdown scenario 4 | [] | [] | Passed |
| freeze-timer-shutdown scenario 5 | ['socket'] | ['socket'] | Passed |
| freeze-timer-shutdown scenario 6 | ['timer'] | ['timer'] | Passed |
| dirty-pagehide-flush scenario 1 | True | True | Passed |
| dirty-pagehide-flush scenario 2 | True | True | Passed |
| dirty-pagehide-flush scenario 3 | False | False | Passed |
| dirty-pagehide-flush scenario 4 | False | False | Passed |
| dirty-pagehide-flush scenario 5 | False | False | Passed |
| dirty-pagehide-flush scenario 6 | False | False | Passed |
| preserved-client-queue scenario 1 | ['a'] | ['a'] | Passed |
| preserved-client-queue scenario 2 | [] | [] | Passed |
| preserved-client-queue scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| preserved-client-queue scenario 4 | [] | [] | Passed |
| preserved-client-queue scenario 5 | ['a'] | ['a'] | Passed |
| preserved-client-queue scenario 6 | ['a'] | ['a'] | Passed |
| resume-queue-drain scenario 1 | [] | [] | Passed |
| resume-queue-drain scenario 2 | [] | [] | Passed |
| resume-queue-drain scenario 3 | ['a', 'b'] | ['a', 'b'] | Passed |
| resume-queue-drain scenario 4 | [] | [] | Passed |
| resume-queue-drain scenario 5 | [] | [] | Passed |
| resume-queue-drain scenario 6 | ['a'] | ['a'] | Passed |
| resume-event-source scenario 1 | ordinary | ordinary | Passed |
| resume-event-source scenario 2 | ordinary | ordinary | Passed |
| resume-event-source scenario 3 | bfcache | bfcache | Passed |
| resume-event-source scenario 4 | ordinary | ordinary | Passed |
| resume-event-source scenario 5 | ordinary | ordinary | Passed |
| resume-event-source scenario 6 | thaw | thaw | Passed |
| resource-disposal-on-unload scenario 1 | [] | [] | Passed |
| resource-disposal-on-unload scenario 2 | ['timer'] | ['timer'] | Passed |
| resource-disposal-on-unload scenario 3 | [] | [] | Passed |
| resource-disposal-on-unload scenario 4 | [] | [] | Passed |
| resource-disposal-on-unload scenario 5 | [] | [] | Passed |
| resource-disposal-on-unload scenario 6 | [] | [] | Passed |
| suspended-work-reason scenario 1 | cached | cached | Passed |
| suspended-work-reason scenario 2 | None | None | Passed |
| suspended-work-reason scenario 3 | None | None | Passed |
| suspended-work-reason scenario 4 | None | None | Passed |
| suspended-work-reason scenario 5 | frozen | frozen | Passed |
| suspended-work-reason scenario 6 | None | None | Passed |
| revalidation-observed-version scenario 1 | 2 | 2 | Passed |
| revalidation-observed-version scenario 2 | 1 | 1 | Passed |
| revalidation-observed-version scenario 3 | 3 | 3 | Passed |
| revalidation-observed-version scenario 4 | 1 | 1 | Passed |
| revalidation-observed-version scenario 5 | 2 | 2 | Passed |
| revalidation-observed-version scenario 6 | 2 | 2 | Passed |
SHA-256 / 7e024e630221a3ef5d052378af123ecbbf7e5eadb9b69492c28e19a81b3d71f2
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:54.242053+00:00.
Case digest / 04cb76f4a9b0ee6d15aae717182f45ff2ff22997f45382cbfd4e515ce1ce4156