FA-8276 / Direct manipulation / Open access
Drop-target acceptance: Unsupported drop effects reach the mutation handler · case 01
Unsupported drop effects reach the mutation handler.
ROOT CAUSE
The effect operation uses `if False: return None` where the contract requires `if effect not in ('move', 'copy'): return None`.
VERIFIED REPAIR
Implement the effect operation as `if effect not in ('move', 'copy'): return None`.
Unsuccessful approach: Restricting to move also rejects supported copy actions.
Case contract
Accept only enabled, compatible targets outside the source subtree, with a supported move or copy effect.
Why this case matters
A deterministic model of drop-target acceptance; this isolates one interface invariant without requiring a browser.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(drag_type, accepts, disabled, source, target, descendants, effect):
if disabled: return None
if drag_type not in accepts: return None
if source == target: return None
if target in descendants: return None
if False: return None
return effect
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disabled', solve('node', ['node'], True, 'a', 'b', [], 'move'), None)
check('type', solve('file', ['node'], False, 'a', 'b', [], 'move'), None)
check('self', solve('node', ['node'], False, 'a', 'a', [], 'move'), None)
check('cycle', solve('node', ['node'], False, 'a', 'b', ['b'], 'move'), None)
check('unsupported', solve('node', ['node'], False, 'a', 'b', [], 'link'), None)
check('copy', solve('node', ['node'], False, 'a', 'b', [], 'copy'), 'copy')
check('move', solve('node', ['node'], False, 'a', 'b', [], 'move'), 'move')
check('parameterized payload type', solve('type'+str(N), ['type'+str(N)], False, 'a', 'b', [], 'copy'), 'copy')
for repetition in range(N):
check('repeat move', solve('node', ['node'], False, 'a', 'b', [], 'move'), 'move')
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 |
|---|---|---|---|
| disabled | None | None | Passed |
| type | None | None | Passed |
| self | None | None | Passed |
| cycle | None | None | Passed |
| unsupported | link | None | Failed |
| copy | copy | copy | Passed |
| move | move | move | Passed |
| parameterized payload type | copy | copy | Passed |
| repeat move | move | move | Passed |
SHA-256 / c84ff335ebead0a63f60c37a09e1c67c39745fd4916d37e55c1e093a85eea0c3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(drag_type, accepts, disabled, source, target, descendants, effect):
if disabled: return None
if drag_type not in accepts: return None
if source == target: return None
if target in descendants: return None
if effect != 'move': return None
return effect
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disabled', solve('node', ['node'], True, 'a', 'b', [], 'move'), None)
check('type', solve('file', ['node'], False, 'a', 'b', [], 'move'), None)
check('self', solve('node', ['node'], False, 'a', 'a', [], 'move'), None)
check('cycle', solve('node', ['node'], False, 'a', 'b', ['b'], 'move'), None)
check('unsupported', solve('node', ['node'], False, 'a', 'b', [], 'link'), None)
check('copy', solve('node', ['node'], False, 'a', 'b', [], 'copy'), 'copy')
check('move', solve('node', ['node'], False, 'a', 'b', [], 'move'), 'move')
check('parameterized payload type', solve('type'+str(N), ['type'+str(N)], False, 'a', 'b', [], 'copy'), 'copy')
for repetition in range(N):
check('repeat move', solve('node', ['node'], False, 'a', 'b', [], 'move'), 'move')
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 |
|---|---|---|---|
| disabled | None | None | Passed |
| type | None | None | Passed |
| self | None | None | Passed |
| cycle | None | None | Passed |
| unsupported | None | None | Passed |
| copy | None | copy | Failed |
| move | move | move | Passed |
| parameterized payload type | None | copy | Failed |
| repeat move | move | move | Passed |
SHA-256 / df5181b785fecb4557291eca07b8f68110af82e6f08b2799a4db7baab5a5a412
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(drag_type, accepts, disabled, source, target, descendants, effect):
if disabled: return None
if drag_type not in accepts: return None
if source == target: return None
if target in descendants: return None
if effect not in ('move', 'copy'): return None
return effect
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disabled', solve('node', ['node'], True, 'a', 'b', [], 'move'), None)
check('type', solve('file', ['node'], False, 'a', 'b', [], 'move'), None)
check('self', solve('node', ['node'], False, 'a', 'a', [], 'move'), None)
check('cycle', solve('node', ['node'], False, 'a', 'b', ['b'], 'move'), None)
check('unsupported', solve('node', ['node'], False, 'a', 'b', [], 'link'), None)
check('copy', solve('node', ['node'], False, 'a', 'b', [], 'copy'), 'copy')
check('move', solve('node', ['node'], False, 'a', 'b', [], 'move'), 'move')
check('parameterized payload type', solve('type'+str(N), ['type'+str(N)], False, 'a', 'b', [], 'copy'), 'copy')
for repetition in range(N):
check('repeat move', solve('node', ['node'], False, 'a', 'b', [], 'move'), 'move')
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 |
|---|---|---|---|
| disabled | None | None | Passed |
| type | None | None | Passed |
| self | None | None | Passed |
| cycle | None | None | Passed |
| unsupported | None | None | Passed |
| copy | copy | copy | Passed |
| move | move | move | Passed |
| parameterized payload type | copy | copy | Passed |
| repeat move | move | move | Passed |
SHA-256 / c44f3b71dd68211cefd7ee9d8376cc9d723012adb6eb4a65054d6ea6c2d0ed86
Verification & scope
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:38:20.012792+00:00.
Case digest / b3132946ca19443ff047a86fc282680a8ee95cf886842d4131e21d71a26845a3