The instrumented capture (cottage-112-capture1.log) + dat replay pinned
the transparent-cottage mechanism end to end:
1. The A9B3 cottage's entry cell 0x104 is a 0.22 m-wide THRESHOLD band
(x 184.68->184.46 at y~82). A running player (~13-16 cm/tick at
30 Hz) can cross it BETWEEN two physics ticks - the tick where the
centre is inside 0x104 never happens.
2. Our outdoor-seed branch ran CheckBuildingTransit over a landcell
snapshot and STOPPED - building-admitted entry cells were never
expanded. The tick after the skip (centre in 0x100, a deep room not
building-portal-adjacent) found no containing candidate -> the pick
kept the outdoor landcell FOREVER (absorbing): the user walked the
whole interior classified outdoor (render faithfully drew an outdoor
frame = transparent walls), promoting only on touching
portal-adjacent 0x102's own volume minutes later (captured:
0xA9B3003C -> 0xA9B30102 with no transitions in between).
3. Retail cannot strand: CObjCell::find_cell_list (0x0052b4e0) runs ONE
growing-array walk for EVERY seed (0052b576-0052b5ab,
cells[i]->find_transit_cells vtable dispatch over the GROWING array)
- the landcell's building bridge admits 0x104 (the foot sphere still
overlaps the band one tick after the skip) and the walk expands
0x104's portals to 0x100 where containment wins. Recovery fires one
tick after any skip.
Fix: BuildCellSetAndPickContaining now runs retail's single growing
walk for both seeds with per-cell-type dispatch (landcells ->
CLandCell::find_transit_cells 0x00533800 -> CSortCell 0x00534060 ->
check_building_transit 0x0052c5d0; envcells -> FindTransitCellsSphere
with the straddle gate + once-per-walk outside add). The old indoor
branch behavior is preserved (seed at index 0, hysteresis, straddle-
gated outdoor pick); the outdoor branch gains the expansion + the
indoor branch gains the retail landcell bridge dispatch for
straddle-admitted landcells.
Pins (dat-backed, Issue112MembershipTests): tick-skip recovery one tick
past the threshold (RED pre-fix); run-speed entry replay across tick
phases never strands outdoor; threshold-gap outdoor-seed keeps outdoor
(over-fix guard); entry-walk replay diagnostic prints the full
promotion chain (0x3C -> 0x104 -> 0x100 -> 0x103 -> 0x100 -> 0x102).
Suites: App 246+1skip / Core 1438+2skip / UI 420 / Net 294.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The two remaining flagged workarounds retired, per the BR-7 plan +
the WF1 [MEDIUM] correction (re-gate, do NOT delete the outside-add):
1. A6.P5 hasExitPortal topology widening DELETED. Outdoor cells enter the
collision cell array ONLY on the retail straddle gate - |dist| <
radius + F_EPSILON against an exterior portal plane
(CEnvCell::find_transit_cells Ghidra 0x0052c820, gate 0052c9d6,
live-binary verified) - the same flag that already gated the
membership pick (#112 rider). The widening existed so outdoor-
registered doors stayed findable from indoor cells under the old flat
registry query; with per-cell shadow lists the door is found in the
straddle-admitted outdoor cell's own list (tick-13558 pin holds).
The hasExitPortal out-param + plumbing deleted from
FindTransitCellsSphere; the AddAllOutsideCells call in
BuildCellSetAndPickContaining re-gated on exitOutsideStraddle
(once-per-walk = retail CELLARRAY.added_outside).
2. #90 ResolveCellId sphere-overlap stickiness REMOVED (the 4ca3596
workaround, deferred-to-A6.P4 in the physics digest). It was dead
code: the method's only caller is FindEnvCollisions' cache-null TEST
fallback, and the indoor branch (where the stickiness lived) required
a non-null DataCache. Production membership flows exclusively through
the collide-then-pick advance whose ordered-array hysteresis (current
cell at index 0, interior-wins-break) is the retail mechanism the
workaround approximated. ResolveCellId reduced to the bare
prefix-preserving outdoor re-derive, documented test-only.
Test updates (pins of the deleted behaviors inverted to retail):
- A6P5_BuildCellSetFromIndoorStart_ReachesDoorOutdoorCell (asserted the
topology widening verbatim) -> DeepInteriorSphere_NoStraddle_
AddsNoOutdoorCells: a deep-interior sphere admits NO outdoor cells.
- A6P5_BuildCellSetFromAlcove... -> AlcoveSphere_StraddlesExitPortal_
ReachesDoorOutdoorCell (the captured alcove position genuinely
straddles - the retail-positive half).
- Issue112MembershipTests straddle pin + the second-sphere straddle test
updated to the single-flag signature.
Suites: Core 1416/0/2, App 225, UI 420, Net 294 - green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The oracle read the #112 residual was waiting on, settled against the
LIVE 2013 client (cdb attach, CEnvCell::find_transit_cells @ 0052c820;
BN pseudo-C was ambiguous and partly wrong per
feedback_bn_decomp_field_names - it invented portal_side tests in this
branch): retail admits outdoor transit cells from an indoor cell IFF a
path sphere STRADDLES an exterior portal polygon plane,
|dist| < radius + F_EPSILON(0.000199999995, @ 007c8c70). The flag at
[esp+18h] (set 0052c925, x87 decode fcompp/test ah,41h +
fcomp/test ah,5/jp) gates the add_all_outside_cells call (0052c9d6 je).
Graph reachability alone NEVER admits outdoor cells in retail.
Port (CellTransit):
- FindTransitCellsSphere: exitOutside now carries the retail straddle
semantics; new hasExitPortal out carries the old topology-only flag.
- BuildCellSetAndPickContaining: the collision cell SET keeps the A6.P5
topology widening on hasExitPortal (outdoor-registered doors must stay
findable from indoor cells until #99/A6.P4 ships per-cell shadow
lists - the 2026-05-25 door capture scenario), but the membership
PICK's outdoor branch is gated on the retail flag. Membership is now
retail-identical in both regimes: straddle -> outdoor candidates valid;
no straddle -> outdoor ignored -> retail keep-curr. This is what stops
deep-interior containment gaps in ANY house from demoting to outdoor
(the #112 transparent-interior shape) - the systemic protection the
user asked for, without house-by-house verification.
The at-doorway A9B3 gap demote is RETAIL-FAITHFUL (gap point is 0.23m
from 0x104s door plane < 0.48 foot radius -> retail straddles + demotes
+ self-heals inward): DocumentsResidual renamed to
...DemotesRetailFaithfully, expectation unchanged. New conformance pins:
deep-gap keep-curr (A9B3Cottage_GapBeyondStraddleDistance_KeepsCurrCell)
+ function-level gate semantics on real dat geometry
(FindTransitCellsSphere_ExitPortalStraddleGate_MatchesRetail).
Tests: Core 1391 green (+2) / App 224 / UI 420 / Net 294; pre-existing
4 #99-era failures unchanged; P1 membership goldens + A6.P5 door-set
tests explicitly green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Root cause (oracle: CLandCell::point_in_cell :316941 = terrain-poly only;
find_cell_list null-result keep-curr pc:308788-308825; CEnvCell::
check_building_transit :309827 = sphere_intersects_cell per portal-adjacent
cell): retail KEEPS curr_cell when nothing contains the centre — including
inside a house's containment gaps. Our 6dbbf95 escape hatch instead demoted
any hydrated indoor claim the sphere no longer overlaps to the outdoor
column; at the A9B3 hill cottage's real interior gap this stranded the
player outdoor-classified deep indoors, where re-promotion is portal-
adjacent-only (retail-identical) -> the outdoor flood rendered the interior
transparent (the user's "sometimes transparent" walk).
The hatch's actual target - poisoned (cell, position) SAVES - has been
handled at the SNAP by PhysicsEngine.Resolve's AdjustPosition validation
since #107/#111, so the per-tick pick reverts to retail semantics:
1. lateral recovery first - when the sphere no longer overlaps the claim,
search the claim's stab list for a containing cell (retail
find_visible_child_cell :311444, the same recovery AdjustPosition uses);
the #111 adjacent-claim shape now self-heals laterally (dat-backed test:
pick(seed 0x172) at a 0x171-interior point -> 0x171);
2. else KEEP curr_cell (retail null-result).
Two old tests asserting the hatch demote rewritten to the retail semantics
(tests-can-codify-bugs); P1 retail-golden conformance gates explicitly green
(FindCellListConformance + ThresholdPortalCrossing + CottageDoorway +
CameraCornerSeal = 11/11). New Issue112MembershipTests: the lateral-recovery
fact + a DocumentsResidual fact pinning the remaining at-doorway gap demote
(via the NORMAL outdoor-candidate path; open oracle read = retail's
add_all_outside_cells gate in CEnvCell::find_transit_cells pc:317499 -
sphere-proximity vs graph-reachability). Core 1383 + 4 pre-existing #99
failures + 1 skip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>