FA-4476 / Borrow checking / Open access
Exclusive borrow excludes readers · case 01
The operation returns a result or retained state that violates this contract: A single local object grants either any number of shared borrows or one exclusive borrow. Commands are [operation,token,value]. Reads return the value or denied; writes and acquisitions return booleans. Ownership can move only with no borrows. An exclusive borrow requires a live object and no outstanding borrow of either kind.
ROOT CAUSE
An exclusive borrow requires a live object and no outstanding borrow of either kind. The broken transition violates that invariant.
VERIFIED REPAIR
A single local object grants either any number of shared borrows or one exclusive borrow. Commands are [operation,token,value]. Reads return the value or denied; writes and acquisitions return booleans. Ownership can move only with no borrows. An exclusive borrow requires a live object and no outstanding borrow of either kind.
Unsuccessful approach: The attempted transition changes the behavior but still violates the same invariant in at least one independent regression fixture.
Case contract
A single local object grants either any number of shared borrows or one exclusive borrow. Commands are [operation,token,value]. Reads return the value or denied; writes and acquisitions return booleans. Ownership can move only with no borrows. An exclusive borrow requires a live object and no outstanding borrow of either kind. Inputs are the finite Python values shown by the executable fixtures; no concurrent execution is assumed.
Why this case matters
A controlled local-runtime regression for collection APIs, language semantics, or ownership wrappers. Fixtures include boundary and interaction cases.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x, y=None):
shared=set(); exclusive=None; value=y; live=True; out=[]
for op,k,arg in x:
if op=='shared':
ok=live and exclusive is None and k not in shared
if ok: shared.add(k)
out.append(ok)
elif op=='exclusive':
ok=live and exclusive is None
if ok: exclusive=k
out.append(ok)
elif op=='release':
shared.discard(k)
if exclusive==k: exclusive=None
out.append(True)
elif op=='read':
out.append(value if live and (k in shared or (exclusive is not None and k==exclusive)) else 'denied')
elif op=='write':
ok=live and exclusive is not None and k==exclusive
if ok: value=arg
out.append(ok)
elif op=='ownerwrite':
ok=live and not shared and exclusive is None
if ok: value=arg
out.append(ok)
elif op=='move':
ok=live and not shared and exclusive is None
if ok: live=False
out.append(ok)
elif op=='inspect': out.append([value,live,sorted(shared),exclusive])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shared readers prohibit mutation', solve([['shared', 'a', None], ['shared', 'a', None], ['shared', 'b', None], ['exclusive', 'w', None], ['write', 'a', 'bad'], ['ownerwrite', None, 'bad'], ['move', None, None], ['read', 'a', None], ['read', 'ghost', None], ['inspect', None, None]], 'initial'), [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]])
check('exclusive token protects identity', solve([['exclusive', 'w', None], ['exclusive', 'other', None], ['shared', 'a', None], ['write', 'ghost', 'bad'], ['release', 'ghost', None], ['ownerwrite', None, 'bad'], ['move', None, None], ['write', 'w', 'new'], ['read', 'w', None], ['inspect', None, None]], 'initial'), [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']])
check('released token loses rights', solve([['shared', 'a', None], ['release', 'a', None], ['read', 'a', None], ['exclusive', 'w', None], ['release', 'w', None], ['write', 'w', 'bad'], ['ownerwrite', None, 'new'], ['inspect', None, None]], 'initial'), [True, True, 'denied', True, True, False, True, ['new', True, [], None]])
check('moved object stays unavailable', solve([['move', None, None], ['shared', 'a', None], ['exclusive', 'w', None], ['ownerwrite', None, 'bad'], ['read', None, None], ['move', None, None], ['inspect', None, None]], 'initial'), [True, False, False, False, 'denied', False, ['initial', False, [], None]])
check('None is not a borrowed token', solve([['read',None,None]], 'initial'), ['denied'])
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 |
|---|---|---|---|
| shared readers prohibit mutation | [True, False, True, True, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], 'w']] | [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]] | Failed |
| exclusive token protects identity | [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']] | [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']] | Passed |
| released token loses rights | [True, True, 'denied', True, True, False, True, ['new', True, [], None]] | [True, True, 'denied', True, True, False, True, ['new', True, [], None]] | Passed |
| moved object stays unavailable | [True, False, False, False, 'denied', False, ['initial', False, [], None]] | [True, False, False, False, 'denied', False, ['initial', False, [], None]] | Passed |
| None is not a borrowed token | ['denied'] | ['denied'] | Passed |
SHA-256 / 02e5829e2762dff88634a67fdde54d8f7505d4b7109c6451d96c97584020eff3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x, y=None):
shared=set(); exclusive=None; value=y; live=True; out=[]
for op,k,arg in x:
if op=='shared':
ok=live and exclusive is None and k not in shared
if ok: shared.add(k)
out.append(ok)
elif op=='exclusive':
ok=live and not shared
if ok: exclusive=k
out.append(ok)
elif op=='release':
shared.discard(k)
if exclusive==k: exclusive=None
out.append(True)
elif op=='read':
out.append(value if live and (k in shared or (exclusive is not None and k==exclusive)) else 'denied')
elif op=='write':
ok=live and exclusive is not None and k==exclusive
if ok: value=arg
out.append(ok)
elif op=='ownerwrite':
ok=live and not shared and exclusive is None
if ok: value=arg
out.append(ok)
elif op=='move':
ok=live and not shared and exclusive is None
if ok: live=False
out.append(ok)
elif op=='inspect': out.append([value,live,sorted(shared),exclusive])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shared readers prohibit mutation', solve([['shared', 'a', None], ['shared', 'a', None], ['shared', 'b', None], ['exclusive', 'w', None], ['write', 'a', 'bad'], ['ownerwrite', None, 'bad'], ['move', None, None], ['read', 'a', None], ['read', 'ghost', None], ['inspect', None, None]], 'initial'), [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]])
check('exclusive token protects identity', solve([['exclusive', 'w', None], ['exclusive', 'other', None], ['shared', 'a', None], ['write', 'ghost', 'bad'], ['release', 'ghost', None], ['ownerwrite', None, 'bad'], ['move', None, None], ['write', 'w', 'new'], ['read', 'w', None], ['inspect', None, None]], 'initial'), [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']])
check('released token loses rights', solve([['shared', 'a', None], ['release', 'a', None], ['read', 'a', None], ['exclusive', 'w', None], ['release', 'w', None], ['write', 'w', 'bad'], ['ownerwrite', None, 'new'], ['inspect', None, None]], 'initial'), [True, True, 'denied', True, True, False, True, ['new', True, [], None]])
check('moved object stays unavailable', solve([['move', None, None], ['shared', 'a', None], ['exclusive', 'w', None], ['ownerwrite', None, 'bad'], ['read', None, None], ['move', None, None], ['inspect', None, None]], 'initial'), [True, False, False, False, 'denied', False, ['initial', False, [], None]])
check('None is not a borrowed token', solve([['read',None,None]], 'initial'), ['denied'])
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 |
|---|---|---|---|
| shared readers prohibit mutation | [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]] | [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]] | Passed |
| exclusive token protects identity | [True, True, False, False, True, False, False, False, 'denied', ['initial', True, [], 'other']] | [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']] | Failed |
| released token loses rights | [True, True, 'denied', True, True, False, True, ['new', True, [], None]] | [True, True, 'denied', True, True, False, True, ['new', True, [], None]] | Passed |
| moved object stays unavailable | [True, False, False, False, 'denied', False, ['initial', False, [], None]] | [True, False, False, False, 'denied', False, ['initial', False, [], None]] | Passed |
| None is not a borrowed token | ['denied'] | ['denied'] | Passed |
SHA-256 / c49dca355e9f74fdd808112e4eed3f9eb859f52d6ffdbfb4a585a0585ebde47d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x, y=None):
shared=set(); exclusive=None; value=y; live=True; out=[]
for op,k,arg in x:
if op=='shared':
ok=live and exclusive is None and k not in shared
if ok: shared.add(k)
out.append(ok)
elif op=='exclusive':
ok=live and not shared and exclusive is None
if ok: exclusive=k
out.append(ok)
elif op=='release':
shared.discard(k)
if exclusive==k: exclusive=None
out.append(True)
elif op=='read':
out.append(value if live and (k in shared or (exclusive is not None and k==exclusive)) else 'denied')
elif op=='write':
ok=live and exclusive is not None and k==exclusive
if ok: value=arg
out.append(ok)
elif op=='ownerwrite':
ok=live and not shared and exclusive is None
if ok: value=arg
out.append(ok)
elif op=='move':
ok=live and not shared and exclusive is None
if ok: live=False
out.append(ok)
elif op=='inspect': out.append([value,live,sorted(shared),exclusive])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shared readers prohibit mutation', solve([['shared', 'a', None], ['shared', 'a', None], ['shared', 'b', None], ['exclusive', 'w', None], ['write', 'a', 'bad'], ['ownerwrite', None, 'bad'], ['move', None, None], ['read', 'a', None], ['read', 'ghost', None], ['inspect', None, None]], 'initial'), [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]])
check('exclusive token protects identity', solve([['exclusive', 'w', None], ['exclusive', 'other', None], ['shared', 'a', None], ['write', 'ghost', 'bad'], ['release', 'ghost', None], ['ownerwrite', None, 'bad'], ['move', None, None], ['write', 'w', 'new'], ['read', 'w', None], ['inspect', None, None]], 'initial'), [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']])
check('released token loses rights', solve([['shared', 'a', None], ['release', 'a', None], ['read', 'a', None], ['exclusive', 'w', None], ['release', 'w', None], ['write', 'w', 'bad'], ['ownerwrite', None, 'new'], ['inspect', None, None]], 'initial'), [True, True, 'denied', True, True, False, True, ['new', True, [], None]])
check('moved object stays unavailable', solve([['move', None, None], ['shared', 'a', None], ['exclusive', 'w', None], ['ownerwrite', None, 'bad'], ['read', None, None], ['move', None, None], ['inspect', None, None]], 'initial'), [True, False, False, False, 'denied', False, ['initial', False, [], None]])
check('None is not a borrowed token', solve([['read',None,None]], 'initial'), ['denied'])
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 |
|---|---|---|---|
| shared readers prohibit mutation | [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]] | [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]] | Passed |
| exclusive token protects identity | [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']] | [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']] | Passed |
| released token loses rights | [True, True, 'denied', True, True, False, True, ['new', True, [], None]] | [True, True, 'denied', True, True, False, True, ['new', True, [], None]] | Passed |
| moved object stays unavailable | [True, False, False, False, 'denied', False, ['initial', False, [], None]] | [True, False, False, False, 'denied', False, ['initial', False, [], None]] | Passed |
| None is not a borrowed token | ['denied'] | ['denied'] | Passed |
SHA-256 / 179e9bebac9713850918ef163042ca730821218a1f1f0f23d55cf7caa0466f20
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:37:39.523235+00:00.
Case digest / c309373c73064fc1e69e277fc6a297a1a9493c0a1f73722e50f936fa4f628e7c