docs(overhaul): contract S5 c3 fix round 1

This commit is contained in:
Erik 2026-09-04 21:13:33 +02:00
parent e2f5385037
commit def7fd2119
2 changed files with 98 additions and 2 deletions

View file

@ -1234,3 +1234,99 @@ lifecycle identity, allocation, allowed scope, build/lane provenance, and at
least three reproduced sabotage claims. Reviews run sequentially. A failed
lens gets one bounded fix contract; a chunk needing a third fix round stops
and is written up.
## 18. S5-c3 fix round 1 — x87 store schedule and register truth
The first sequential OpenAI retail/deviation review returned **FAIL** on the
uncommitted scratch implementation: one MAJOR exact-arithmetic defect and one
MINOR pre-existing register-truth defect. Everything else in §17 passed. This
is the first bounded fix round; it does not reopen selection ownership,
building traversal, residency, Config wiring, or any S5-c1/S5-c2 behavior.
The reviewer independently re-confirmed the executable SHA, CodeView GUID/age,
all seven §17.1 byte-range hashes, the named-decomp semantics, the complete
§17.2 census, the complete-body order, Setup part zero, selected-shell identity
and surface preservation, no base fallback, scope, lifecycle wiring, the other
register edits, and every required mutation. Its clean focused return was
64/64, and the scratch state was restored exactly.
### 18.1 F1 — preserve retail's x87/store boundaries
The candidate currently rounds arithmetic too early in three places. Repair
only these exact boundaries, allocation-free:
1. `SceneTool::UpdateFPSCounter @0x0043E510` sums the 20 stored single-precision
frame durations in x87 precision and divides before narrowing once at the
published FPS store. Accumulating into a C# `float` is not equivalent. Use
a wider accumulator that exactly sums the 20 binary32 inputs, perform the
division wide, then narrow once to `float`. Restore retail's physical
history direction: shift old slots `0..18` to `1..19`, then store the
just-finished binary32 duration at slot 0. The prior-20-before-insert order
remains unchanged.
2. `Render::CalcDegLevel @0x0054CAF0` evaluates its five membership weights,
weighted numerator/denominator, addition, and clamp in x87 precision except
at the explicit binary32 stores visible in the named function. Re-express
the pure calculation with wide intermediates fed by the exact binary32
constants (`-0.150000006f`, `-0.02f`, `0.01f`, `0.1f`) and narrow only at
retail's candidate store. The stability comparison promotes each binary32
history slot and candidate and compares against the executable's qword
`0.01`, not `0.01f`. Keep the existing shift-before-evaluate and final
current-multiplier store order.
3. `GfxObjDegradeInfo::get_degrade @0x0051E4B0` stores the effective distance
after `abs(distance)-DegradeDistance`, but evaluates each positive/negative
threshold in x87 precision and compares the stored binary32 effective value
against that wide threshold. Do not round the threshold to `float` before
the strict comparison. Disable/force precedence, strict `<`, equality
advance, final slot, modes, and NaN/infinity behavior stay unchanged.
Add bit-exact independent assertions for all three proven witnesses:
- FPS history `[0.001f, 0.005f] × 10` publishes bits `0x43A6AAAB`
(`333.333344f`), not the candidate's `0x43A6AAAC`;
- `CalculateCandidate(14f, 0f)` publishes bits `0x3BB2BC0A`, not
`0x3BB2BC0B`;
- with ideal/max `24f/48f`, multiplier `0.0020020019728690386f`, and
effective distance `24.04804801940918f` (`0x41C06267`), retail's wide
threshold remains strictly greater and selects the first level.
Also pin the qword stability edge directly and the slot direction without
reflection-only self-comparison. Each of these changes needs a named mutation
and actual first failing assertion: restore float FPS accumulation; restore
float CalcDeg intermediates or `0.01f`; restore a rounded selector threshold;
reverse the FPS slot direction. Restore every mutation before return.
### 18.2 F2 — correct AP-198's already-live landscape radius
`AP-198` is stale independently of this chunk: `Render_LandscapeDrawDistance`
already feeds `RuntimeSettingsController`'s live far radius, and the Config
controller maps its persisted default 8 to the selected Medium entry. Remove
that control from AP-198, change every six-row statement to five, and delete
the obsolete no-highlight sub-note. Keep the actual Config dim set at 17/27;
S5-c3 still changes only Automatic Degrades, Graphics Performance, and Degrade
Distance from store-only to live. No row is added or retired, so active table
counts do not change. Add or update a truth pin that fails on the old six-row
wording or the obsolete no-highlight statement.
### 18.3 Scope, return, and review order
Production edits are limited to `BuildingDegradeController.cs` and
`Walk/WalkBuilding.cs`. Test edits are limited to their existing focused test
files plus the existing Config/register truth pin if required. The only
documentation edit in the implementation remains
`docs/architecture/retail-divergence-register.md`. Do not change controller
ownership/tick placement, selection/result shapes, building factory or
transforms, portal walk/order, shell classification, residency, materials,
surface overrides, UI wiring, RHI/shaders, DAT readers, or any other register
row. No graphical client.
Return the exact changed-file list; `git diff --check`; Release solution build
0W/0E; the bit-exact math/selector/controller and Config/register focused
lanes; the original S5-c3 focused lane; official hermetic lane; inclusive
InstalledDat lane with exactly the documented global identities; and the new
mutation ledger. Do not commit—the lead owns the reviewed landing commit under
the owner's OpenAI-only process override.
The same OpenAI retail lens narrowly re-reviews F1/F2 and regression evidence
first. Only its PASS unlocks the sequential OpenAI architecture/production/
gate-honesty review over the entire S5-c3 stack. A failed re-review receives
the one remaining bounded fix round; another failure after that stops S5-c3.