Files
EscapistsReintroduced/docs/prison-approach-reliability.md
T

101 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Prison approach reliability audit
Read-only comparison of three immutable ordinary-game captures. No retries, input,
engine launches, gameplay changes or relaxed limits were used for this audit.
The approach policy hash recorded in all three input reports matches the current
`tools/prison_approach_proof.py`. The 19:39 and 19:41 captures also share the exact
input-helper hash; 19:17 used an earlier helper. This is a small diagnostic sample,
not a reliability rate or performance benchmark.
| Archive | Approach outcome | W pulses / yaw requests | Native observed duration | Recorded W hold min / median / max | Largest stopped displacement | Final target error |
| --- | --- | --- | --- | --- | --- | --- |
| [19:39:24](evidence/game-2026-09-19-193924-approach-stopping-reserve/input-proof.json.txt) | Stopping-reserve refusal | 8 / 14 | 25.899 s | 241.581 / 247.062 / 313.187 ms | 0.906973 m | 0.982344 m |
| [19:41:28](evidence/game-2026-09-19-194128-gate-context-unselected/input-proof.json.txt) | Approach completed; later alignment refused | 10 / 14 | 28.456 s | 240.434 / 247.307 / 261.644 ms | 0.572014 m | 0.475079 m |
| [19:17:50](evidence/game-2026-09-19-191750-prison-approach/input-proof.json.txt) | Approach completed | 9 / 14 | 27.199 s | 244.823 / 247.146 / 264.882 ms | 0.585235 m | 0.490408 m |
Durations use the first and last native samples retained by the approach report;
key holds use the actual helper key-down/up event timestamps. Paths were
4.246073, 4.760125 and 4.741409 m respectively. The failed approach still had
6.164 s of its original 35-second approach allowance: it did not time out.
The successful approaches left 3.633 and 4.734 s. None proves gate operation.
## What caused the refusal
The policy ends only at target error `r <= 0.75 m`, but permits another pulse only
when `r > largest_stop + 0.25 m` (`perform_approach`, lines 255–268). Therefore any
`largest_stop > 0.50 m` creates an unreachable decision interval:
`0.75 < r <= largest_stop + 0.25`.
For 19:39 the interval was `(0.75, 1.156973] m`, width 0.406973 m. Pulse 7 moved
0.906973 m, leaving 1.420035 m. Pulse 8 was correctly permitted at that point,
moved 0.438292 m and left 0.982344 m: outside the completion radius but inside the
refusal interval. Waiting cannot change this while fully stopped. The earlier
large stop is correctly retained; dropping it merely to allow another pulse would
remove evidence from the safety decision.
Both successful runs also had a smaller decision interval, but their final
pulses crossed it: 19:41 moved from 1.046375 to 0.475079 m; 19:17 moved from
1.062121 to 0.490408 m. Their success does not prove the policy can always finish.
## Input timing versus native movement
The policy currently sleeps 50 ms after W-down, **then runs the complete private
ownership/focus guard while W remains held**, and finally sends W-up
(`perform_approach` lines 229–245, 276–281). The helper's `Guard.check()` validates
display binding, window/process identity, native arguments, focus/mapping and a
second display binding. Those checks must remain intact.
Measured down-to-up durations were approximately 240–265 ms in both successful
runs. Thus the nominal 50 ms sleep is not the actual pulse duration: roughly
190–215 ms was spent in the release path and scheduling. The largest failed-run
pulse lasted 313.187 ms, leaving 263.187 ms beyond the requested sleep. This is
consistent with extra guard/IPC or OS scheduling latency. The archives do not
contain guard start/end or XTest timing breakdowns, so they cannot identify which
operation caused that excess. All recorded holds remain below the 400 ms cap.
The large stop is physical, not just a helper distance calculation. In the
[19:39 console](evidence/game-2026-09-19-193924-approach-stopping-reserve/console.log.txt),
pulse 7 spans samples 240–252. Sample 240 at 57,156 ms is stopped at
`6090.89,211.331,7156.87`. Native forward is positive at samples 241–243;
movement input is positive at 242–243. At sample 244 (57,653 ms), forward and
movement input are already zero, but velocity is approximately 2.149 m/s and the
body is at `6091.44,211.323,7156.50`. It travels another **0.244 m** before the
stopped position `6091.64,211.319,7156.36`, first zero-velocity sample 247.
Thus native momentum after observed release contributes materially. Sparse
100–138 ms samples cannot locate the exact engine receipt of W-up.
Comparable holds also produce different stops: 19:41's 240.434 ms pulse moved
0.568595 m, while its 261.644 ms pulse moved 0.432666 m. A linear duration-to-distance
model is not justified. Every accepted pulse retained both positive native input
acknowledgement and at least 0.05 m physical movement/progress; full-stop observation
was required afterward.
## Smallest next improvement, still unqualified
First record bounded monotonic guard-entry/return, W-up request and final native
stop timestamps in a future experiment. This isolates release latency without
changing input or authority. A small subsequent algorithm candidate is to perform
the **same full release guard during the initial 50 ms hold interval**, rather
than always adding it afterward. If that guard returns before 50 ms, wait the
remainder and recheck it immediately before W-up. If it already consumed 50 ms,
release immediately after its successful return. Keep emergency cleanup and the
1.5-second hard key lease unchanged; never release from a stale cached guard.
This could remove the unconditional extra 50 ms when validation already takes
~200 ms, without weakening the 0.75 m target, 0.25 m reserve, 400 ms actual-hold
cap, positive native input/0.05 m movement acknowledgement, full stop, original
35-second approach allowance or 45-second native lifetime. It is only a bounded
candidate: shorter pulses may be missed by native sampling and must then refuse;
extra pulses could exhaust the existing count or time budget. A slow guard can
still dominate the hold. Tests must cover fast/slow/refused guards, real elapsed
hold, release cleanup, missing native acknowledgement and unchanged reserve.
There is **no source-proven safe completion fix for an already reached deadzone**
under the current maximum-stop rule. Do not substitute the latest smaller stop,
ignore the outlier, silently reset the maximum for a shorter pulse, cross the
reserve, enlarge the target or extend the lifetime. Any future shorter-pulse
strategy needs its own measured conservative stopping bound before it can safely
address that remaining limitation. No such bound or improved runtime outcome is
claimed here.