FA-8066 / Client navigation / Open access
Browser-style history transitions: Replace adds a history entry instead of updating current · case 01
Replace adds a history entry instead of updating current.
ROOT CAUSE
The replace operation uses `entries.append(url)` where the contract requires `entries[index] = url`.
VERIFIED REPAIR
Implement the replace operation as `entries[index] = url`.
Unsuccessful approach: Replacing the entire list destroys back history.
Case contract
Push truncates forward history and selects the new entry; replace retains stack length; back and forward clamp to existing entries; reload leaves history intact.
Why this case matters
A deterministic model of browser-style history transitions; 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(entries, index, action, url):
entries = list(entries)
if action == 'push': return (entries[:index+1] + [url], index+1)
if action == 'replace': entries.append(url)
elif action == 'back': index = max(0, index-1)
elif action == 'forward': index = min(len(entries)-1, index+1)
elif action == 'reload': return (entries, index)
return (entries, index)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('branch', solve(['a','b','c'], 1, 'push', 'x'), (['a', 'b', 'x'], 2))
check('replace', solve(['a','b','c'], 1, 'replace', 'x'), (['a', 'x', 'c'], 1))
check('first back', solve(['a','b'], 0, 'back', None), (['a', 'b'], 0))
check('back', solve(['a','b'], 1, 'back', None), (['a', 'b'], 0))
check('last forward', solve(['a','b'], 1, 'forward', None), (['a', 'b'], 1))
check('forward', solve(['a','b'], 0, 'forward', None), (['a', 'b'], 1))
check('reload', solve(['a','b'], 1, 'reload', None), (['a', 'b'], 1))
check('parameterized push depth', solve(list(range(N+1)), N, 'push', N+1), (list(range(N+2)), N+1))
for repetition in range(N):
check('repeat reload', solve(['a','b'], 1, 'reload', None), (['a', 'b'], 1))
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 |
|---|---|---|---|
| branch | [['a', 'b', 'x'], 2] | [['a', 'b', 'x'], 2] | Passed |
| replace | [['a', 'b', 'c', 'x'], 1] | [['a', 'x', 'c'], 1] | Failed |
| first back | [['a', 'b'], 0] | [['a', 'b'], 0] | Passed |
| back | [['a', 'b'], 0] | [['a', 'b'], 0] | Passed |
| last forward | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| forward | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| reload | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| parameterized push depth | [[0, 1, 2], 2] | [[0, 1, 2], 2] | Passed |
| repeat reload | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
SHA-256 / cf27dd5fa56633b8a7fc7b0e192e3e22962a455c02d7777e7f9c5b2555cab14b
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(entries, index, action, url):
entries = list(entries)
if action == 'push': return (entries[:index+1] + [url], index+1)
if action == 'replace': entries = [url]
elif action == 'back': index = max(0, index-1)
elif action == 'forward': index = min(len(entries)-1, index+1)
elif action == 'reload': return (entries, index)
return (entries, index)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('branch', solve(['a','b','c'], 1, 'push', 'x'), (['a', 'b', 'x'], 2))
check('replace', solve(['a','b','c'], 1, 'replace', 'x'), (['a', 'x', 'c'], 1))
check('first back', solve(['a','b'], 0, 'back', None), (['a', 'b'], 0))
check('back', solve(['a','b'], 1, 'back', None), (['a', 'b'], 0))
check('last forward', solve(['a','b'], 1, 'forward', None), (['a', 'b'], 1))
check('forward', solve(['a','b'], 0, 'forward', None), (['a', 'b'], 1))
check('reload', solve(['a','b'], 1, 'reload', None), (['a', 'b'], 1))
check('parameterized push depth', solve(list(range(N+1)), N, 'push', N+1), (list(range(N+2)), N+1))
for repetition in range(N):
check('repeat reload', solve(['a','b'], 1, 'reload', None), (['a', 'b'], 1))
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 |
|---|---|---|---|
| branch | [['a', 'b', 'x'], 2] | [['a', 'b', 'x'], 2] | Passed |
| replace | [['x'], 1] | [['a', 'x', 'c'], 1] | Failed |
| first back | [['a', 'b'], 0] | [['a', 'b'], 0] | Passed |
| back | [['a', 'b'], 0] | [['a', 'b'], 0] | Passed |
| last forward | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| forward | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| reload | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| parameterized push depth | [[0, 1, 2], 2] | [[0, 1, 2], 2] | Passed |
| repeat reload | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
SHA-256 / d5c4852f03e9c3c9223dcc3986db9d02fab71c07f986832d69c5a25c50c4a48e
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(entries, index, action, url):
entries = list(entries)
if action == 'push': return (entries[:index+1] + [url], index+1)
if action == 'replace': entries[index] = url
elif action == 'back': index = max(0, index-1)
elif action == 'forward': index = min(len(entries)-1, index+1)
elif action == 'reload': return (entries, index)
return (entries, index)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('branch', solve(['a','b','c'], 1, 'push', 'x'), (['a', 'b', 'x'], 2))
check('replace', solve(['a','b','c'], 1, 'replace', 'x'), (['a', 'x', 'c'], 1))
check('first back', solve(['a','b'], 0, 'back', None), (['a', 'b'], 0))
check('back', solve(['a','b'], 1, 'back', None), (['a', 'b'], 0))
check('last forward', solve(['a','b'], 1, 'forward', None), (['a', 'b'], 1))
check('forward', solve(['a','b'], 0, 'forward', None), (['a', 'b'], 1))
check('reload', solve(['a','b'], 1, 'reload', None), (['a', 'b'], 1))
check('parameterized push depth', solve(list(range(N+1)), N, 'push', N+1), (list(range(N+2)), N+1))
for repetition in range(N):
check('repeat reload', solve(['a','b'], 1, 'reload', None), (['a', 'b'], 1))
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 |
|---|---|---|---|
| branch | [['a', 'b', 'x'], 2] | [['a', 'b', 'x'], 2] | Passed |
| replace | [['a', 'x', 'c'], 1] | [['a', 'x', 'c'], 1] | Passed |
| first back | [['a', 'b'], 0] | [['a', 'b'], 0] | Passed |
| back | [['a', 'b'], 0] | [['a', 'b'], 0] | Passed |
| last forward | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| forward | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| reload | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
| parameterized push depth | [[0, 1, 2], 2] | [[0, 1, 2], 2] | Passed |
| repeat reload | [['a', 'b'], 1] | [['a', 'b'], 1] | Passed |
SHA-256 / ae2d8629fe3d32dad11a0aff6c545e0bed36ad0e6822101b64aa837a9ba70618
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:17.914269+00:00.
Case digest / f2af55d639d950f55d47c5cd9ca0e06eb565b7d7dd294be60119efaacf71e937