FAILURE MAP
← Case archive

FA-33211 / Menu interactions / Open access

Tearing off a menu discards its invocation context · case 01

Tearing off a menu discards its invocation context.

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

ROOT CAUSE

The tearoff-menus model applies `{}` at its copy-context operation instead of the stipulated transformation.

VERIFIED REPAIR

Apply `dict(p['context'])` at copy-context.

Unsuccessful approach: The attempted repair `dict(p['ambient'])` still violates the copy-context oracle.

Case contract

A tear-off menu retains a frozen command context while acquiring an independent surface lifetime; its geometry and closure no longer follow the source popup.

Why this case matters

Cascading and context menus require coherent command and session state as content changes.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import unicodedata
N = 1
observations = []
def solve(action, p):
    if action == 'copy-context':
        return {}
    if action == 'lifetime':
        return None
    if action == 'translate':
        return [p['popup'][0]+p['offset'][0],p['popup'][1]+p['offset'][1]]
    if action == 'source-close':
        return p['torn'] if p['independent'] else []
    if action == 'reattach':
        return {'parent':p['destination'],'independent':False,'context':p['context']}
    if action == 'closed-record':
        return [x for x in p['windows'] if x['id']!=p['id']]
    return {'error': 'unsupported menu operation'}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('copy-context contract', solve('copy-context', {'context':{'document':N},'ambient':{'document':N+1}}), {'document':N})
check('lifetime contract', solve('lifetime', {'parent_session':N,'root_session':N+1}), None)
check('translate contract', solve('translate', {'popup':[N,2*N],'offset':[10,20]}), [N+10,2*N+20])
check('source-close contract', solve('source-close', {'torn':[N],'independent':True,'source':['old']}), [N])
check('reattach contract', solve('reattach', {'destination':'menu'+str(N),'context':'doc'}), {'parent':'menu'+str(N),'independent':False,'context':'doc'})
check('closed-record contract', solve('closed-record', {'windows':[{'id':N},{'id':N+1}],'id':N}), [{'id':N+1}])
check('unknown operation', solve('unknown', {}), {'error': 'unsupported menu operation'})
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
copy-context contract{}{'document': 1}Failed
lifetime contractNoneNonePassed
translate contract[11, 22][11, 22]Passed
source-close contract[1][1]Passed
reattach contract{'context': 'doc', 'independent': False, 'parent': 'menu1'}{'context': 'doc', 'independent': False, 'parent': 'menu1'}Passed
closed-record contract[{'id': 2}][{'id': 2}]Passed
unknown operation{'error': 'unsupported menu operation'}{'error': 'unsupported menu operation'}Passed

SHA-256 / 7a471724603e493f1d202804cc9b17ff4c11e5a68ba237d4472465c0be7003d9

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import unicodedata
N = 1
observations = []
def solve(action, p):
    if action == 'copy-context':
        return dict(p['ambient'])
    if action == 'lifetime':
        return None
    if action == 'translate':
        return [p['popup'][0]+p['offset'][0],p['popup'][1]+p['offset'][1]]
    if action == 'source-close':
        return p['torn'] if p['independent'] else []
    if action == 'reattach':
        return {'parent':p['destination'],'independent':False,'context':p['context']}
    if action == 'closed-record':
        return [x for x in p['windows'] if x['id']!=p['id']]
    return {'error': 'unsupported menu operation'}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('copy-context contract', solve('copy-context', {'context':{'document':N},'ambient':{'document':N+1}}), {'document':N})
check('lifetime contract', solve('lifetime', {'parent_session':N,'root_session':N+1}), None)
check('translate contract', solve('translate', {'popup':[N,2*N],'offset':[10,20]}), [N+10,2*N+20])
check('source-close contract', solve('source-close', {'torn':[N],'independent':True,'source':['old']}), [N])
check('reattach contract', solve('reattach', {'destination':'menu'+str(N),'context':'doc'}), {'parent':'menu'+str(N),'independent':False,'context':'doc'})
check('closed-record contract', solve('closed-record', {'windows':[{'id':N},{'id':N+1}],'id':N}), [{'id':N+1}])
check('unknown operation', solve('unknown', {}), {'error': 'unsupported menu operation'})
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
copy-context contract{'document': 2}{'document': 1}Failed
lifetime contractNoneNonePassed
translate contract[11, 22][11, 22]Passed
source-close contract[1][1]Passed
reattach contract{'context': 'doc', 'independent': False, 'parent': 'menu1'}{'context': 'doc', 'independent': False, 'parent': 'menu1'}Passed
closed-record contract[{'id': 2}][{'id': 2}]Passed
unknown operation{'error': 'unsupported menu operation'}{'error': 'unsupported menu operation'}Passed

SHA-256 / 76a706db351f93ee7dfcf02ec8c490057703c976a38aed50a9e654b6282a303a

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import unicodedata
N = 1
observations = []
def solve(action, p):
    if action == 'copy-context':
        return dict(p['context'])
    if action == 'lifetime':
        return None
    if action == 'translate':
        return [p['popup'][0]+p['offset'][0],p['popup'][1]+p['offset'][1]]
    if action == 'source-close':
        return p['torn'] if p['independent'] else []
    if action == 'reattach':
        return {'parent':p['destination'],'independent':False,'context':p['context']}
    if action == 'closed-record':
        return [x for x in p['windows'] if x['id']!=p['id']]
    return {'error': 'unsupported menu operation'}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('copy-context contract', solve('copy-context', {'context':{'document':N},'ambient':{'document':N+1}}), {'document':N})
check('lifetime contract', solve('lifetime', {'parent_session':N,'root_session':N+1}), None)
check('translate contract', solve('translate', {'popup':[N,2*N],'offset':[10,20]}), [N+10,2*N+20])
check('source-close contract', solve('source-close', {'torn':[N],'independent':True,'source':['old']}), [N])
check('reattach contract', solve('reattach', {'destination':'menu'+str(N),'context':'doc'}), {'parent':'menu'+str(N),'independent':False,'context':'doc'})
check('closed-record contract', solve('closed-record', {'windows':[{'id':N},{'id':N+1}],'id':N}), [{'id':N+1}])
check('unknown operation', solve('unknown', {}), {'error': 'unsupported menu operation'})
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
copy-context contract{'document': 1}{'document': 1}Passed
lifetime contractNoneNonePassed
translate contract[11, 22][11, 22]Passed
source-close contract[1][1]Passed
reattach contract{'context': 'doc', 'independent': False, 'parent': 'menu1'}{'context': 'doc', 'independent': False, 'parent': 'menu1'}Passed
closed-record contract[{'id': 2}][{'id': 2}]Passed
unknown operation{'error': 'unsupported menu operation'}{'error': 'unsupported menu operation'}Passed

SHA-256 / f3cd11b16d33b43cf5acd923ee1d2149e5d462947de6a2aec1ae4673003f357a

Verification & scope

Offline supplied-valid-payload model; excludes DOM, keyboard, focus, selection, announcements and browser conformance. 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:20.065442+00:00.

Case digest / 845922cf6d94181c2c9d29e9438288e42d324114b973c3e3ccfb6b4ad1c059ce