FA-8291 / Viewport layout / Open access
Nearest-edge scroll reveal: Revealing a lower item scrolls it above the viewport · case 01
Revealing a lower item scrolls it above the viewport.
ROOT CAUSE
The trailing operation uses `elif end > offset + viewport: wanted = end` where the contract requires `elif end > offset + viewport: wanted = end - viewport`.
VERIFIED REPAIR
Implement the trailing operation as `elif end > offset + viewport: wanted = end - viewport`.
Unsuccessful approach: Aligning its start introduces unnecessary motion instead of nearest-edge reveal.
Case contract
Keep already-visible items stationary; reveal nearest edge; align oversized items at the start; clamp offset to the scrollable extent.
Why this case matters
A deterministic model of nearest-edge scroll reveal; 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(start, end, offset, viewport, extent):
if end - start > viewport: wanted = start
elif start < offset: wanted = start
elif end > offset + viewport: wanted = end
else: wanted = offset
return max(0, min(wanted, max(0, extent - viewport)))
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('oversized', solve(10, 40, 0, 20, 100), 10)
check('above', solve(10, 15, 30, 20, 100), 10)
check('below', solve(40, 45, 0, 20, 100), 25)
check('visible', solve(12, 15, 10, 20, 100), 10)
check('end clamp', solve(95, 105, 0, 20, 100), 80)
check('negative clamp', solve(-5, 0, 10, 20, 100), 0)
check('parameterized reveal distance', solve(10*N, 10*N+5, 0, 10, 100*N), 10*N-5)
for repetition in range(N):
check('repeat negative clamp', solve(-5, 0, 10, 20, 100), 0)
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 |
|---|---|---|---|
| oversized | 10 | 10 | Passed |
| above | 10 | 10 | Passed |
| below | 45 | 25 | Failed |
| visible | 10 | 10 | Passed |
| end clamp | 80 | 80 | Passed |
| negative clamp | 0 | 0 | Passed |
| parameterized reveal distance | 15 | 5 | Failed |
| repeat negative clamp | 0 | 0 | Passed |
SHA-256 / fa684abd73761246155d41542ee75068a26d8acd338d026800609226323812eb
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(start, end, offset, viewport, extent):
if end - start > viewport: wanted = start
elif start < offset: wanted = start
elif end > offset + viewport: wanted = start
else: wanted = offset
return max(0, min(wanted, max(0, extent - viewport)))
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('oversized', solve(10, 40, 0, 20, 100), 10)
check('above', solve(10, 15, 30, 20, 100), 10)
check('below', solve(40, 45, 0, 20, 100), 25)
check('visible', solve(12, 15, 10, 20, 100), 10)
check('end clamp', solve(95, 105, 0, 20, 100), 80)
check('negative clamp', solve(-5, 0, 10, 20, 100), 0)
check('parameterized reveal distance', solve(10*N, 10*N+5, 0, 10, 100*N), 10*N-5)
for repetition in range(N):
check('repeat negative clamp', solve(-5, 0, 10, 20, 100), 0)
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 |
|---|---|---|---|
| oversized | 10 | 10 | Passed |
| above | 10 | 10 | Passed |
| below | 40 | 25 | Failed |
| visible | 10 | 10 | Passed |
| end clamp | 80 | 80 | Passed |
| negative clamp | 0 | 0 | Passed |
| parameterized reveal distance | 10 | 5 | Failed |
| repeat negative clamp | 0 | 0 | Passed |
SHA-256 / 06cd81d1fd19bdbcbc9255187871cb10e2b46c94ec25dc1bfdeddcde3afd29f1
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(start, end, offset, viewport, extent):
if end - start > viewport: wanted = start
elif start < offset: wanted = start
elif end > offset + viewport: wanted = end - viewport
else: wanted = offset
return max(0, min(wanted, max(0, extent - viewport)))
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('oversized', solve(10, 40, 0, 20, 100), 10)
check('above', solve(10, 15, 30, 20, 100), 10)
check('below', solve(40, 45, 0, 20, 100), 25)
check('visible', solve(12, 15, 10, 20, 100), 10)
check('end clamp', solve(95, 105, 0, 20, 100), 80)
check('negative clamp', solve(-5, 0, 10, 20, 100), 0)
check('parameterized reveal distance', solve(10*N, 10*N+5, 0, 10, 100*N), 10*N-5)
for repetition in range(N):
check('repeat negative clamp', solve(-5, 0, 10, 20, 100), 0)
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 |
|---|---|---|---|
| oversized | 10 | 10 | Passed |
| above | 10 | 10 | Passed |
| below | 25 | 25 | Passed |
| visible | 10 | 10 | Passed |
| end clamp | 80 | 80 | Passed |
| negative clamp | 0 | 0 | Passed |
| parameterized reveal distance | 5 | 5 | Passed |
| repeat negative clamp | 0 | 0 | Passed |
SHA-256 / 6a5f0c7331a624886abbb02472a165ee031bb194fe054a1c783c6057aee33ed8
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.165182+00:00.
Case digest / 31618591e6b093aeae244d06c8cd7c0c4b78b8037e17ebb3e1c25fed23ed6cc4