Commit graph

4431 commits

Author SHA1 Message Date
Erik
51c6bfcd96 docs(render): ledger — S3 chunk 2 landed (verdicts, gates, self-gate); chunk 3 dispatched
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 08:02:18 +02:00
Erik
434a7df289 fix(render): S3 chunk 2 review follow-ups
- delete the ACDREAM_PROBE_CATHEDRAL_SKIP_SEALS discriminator (member, read
  site, launch-options row): its investigation is closed by the retail
  axiom, and the review found it had silently gained a second effect through
  the seal count (a skipped seal also suppressed the next depth clear);
- the interior PView's draw_landscape is now wired explicitly (RenderDeviceD3D::Init
  0x0059efb0), so the two-PView pin asserts wiring, not a default;
- the two backend seam comments name retail's clear gate;
- the counter doc states the Collect/Replay consume/re-arm split and why it
  has no retail analogue.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 08:01:37 +02:00
Erik
4c364412f0 tools(selfgate): add the Holtburg terrain-leak pose (owner-supplied) to the route
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:55:00 +02:00
Erik
2f5373c740 docs(render): driver type doc — state the ov>0 gate precisely
Comment-only: the landscape, flush, gated clear and seals run only when
outside_view.view_count > 0; the flood cells are unconditional.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:50:34 +02:00
Erik
bbe41d5993 docs(render): S3 chunk 1 contract — transcript kinds, fixtures, print-only emitter
Runs after chunk 3 (LC/SC need per-cell terrain). One print-only flag,
the FW0 parser extended for the OH kinds, the five captures as fixtures
in the existing still-frame conformance harness, and an offline signature
diff as the transcript gate. No validator, no canonical format.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:49:56 +02:00
Erik
542b049b15 docs(render): import the five retail capture transcripts as S3 fixtures
Walk (5 frames with LC/SC), parts (3) and alpha-depth (5) per pose from
the paired 2013 client, plus the recon log and the owner's retail
screenshot of the cathedral leak. logs/ is ignored; these copies are the
durable record S3 chunk 1's parser consumes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:47:33 +02:00
Erik
be9b4c1f29 feat(render): S3 chunk 2 — gate the interior turn on the real outside-view count
RetailFrameWalk.DrawInside now passes _interiorPView.OutsideView.ViewCount
into IWalkEventSink.OnInteriorFloodDrawTurn. WalkFrameDriver's own
implementation reproduces PView::DrawCells @0x005a4840's exact gating
(0x005a4852-0x005a49eb, all inside `if (outside_view.view_count > 0)`):
the landscape flush (retail FlushAlphaList(0f) @0x005a4872 plus the
pre-clear dynamics hook), the device-stamp advance @0x005a4886, a GATED
depth clear (pc:432731-432732), and the exit-portal seals
(pc:432785-432786) — all four skipped entirely when outsideViewCount == 0.

The depth clear is gated on a new driver field, PortalsDrawnCount, which
models retail's D3DPolyRender::portalsDrawnCount (uint16 @0x008719b4):
read-then-zeroed at the interior root's own flood turn
(@0x005a489c-0x005a489e), and re-armed at Replay by the count
IWalkFrameLeafRenderer.DrawExitSeals now returns (the SAME portal
enumeration RetailPViewPassExecutor.DrawPortalDepthWrite already performs
— OtherCellId==0xFFFF, >=3 vertices). The field persists across frames
(never cleared by BeginFrame/AbortFrame/EndFrame/Replay), reproducing
retail's documented quirk: a fresh driver's first ov>0 frame never clears;
every later ov>0 frame clears because the previous frame's own seals armed
the counter.

_skyDrawnThisFrame — the proxy for outside_view.view_count != 0 that used
to gate the stamp re-arm — is deleted; its "second Landscape turn in one
frame" fail-loud guard moves to a frame-scoped counter
(_landscapeTurnsThisFrame). RetailPViewRenderer.ClearWalkInteriorDepth
splits into FlushWalkLandscape (pre-clear dynamics + FlushLandscapeAlpha)
and ClearWalkInteriorDepth (the Z clear only), both wired through the new
IWalkFrameLeafRenderer.FlushLandscape leaf and the WalkLeaf production
adapter.

Tests: flipped the ov==0 pin to expect no landscape-flush/clear/seals at
all (T1); added the two-frame first-frame-no-clear / armed-clear pin plus
a no-exit-portal-never-clears pin (T2); added a look-in-neither-arms-
nor-consumes-the-counter pin (T3); added RetailFrameWalk's two-PView
draw_landscape wiring pin and a WalkPView.ConstructView reset pin (T4);
updated every direct OnInteriorFloodDrawTurn caller to pass the
outsideViewCount it models (T5). The four per-category leaf-contract pins
(whole-once shell, Boolean sphere admission, portal-polygon-only clip,
local-player repeated submission) already existed and needed no additions
(B4).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:46:11 +02:00
Erik
51d5323208 docs(render): record foundry-deep; the retail capture session is complete
All four kit poses plus the extra cathedral-leak pose have walk (with
LC/SC), parts and alpha-depth transcripts from the paired 2013 client.
S3 chunk 1 is unblocked.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:43:20 +02:00
Erik
09db7f943b docs(render): terrace-edge record — the vista building draws every complete frame, set identical to FW0
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:40:00 +02:00
Erik
6e1042b568 docs(render): record the terrace-edge retail capture (S3 §6b)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:39:37 +02:00
Erik
c36488dfb1 docs(render): record the holtburg-doorway-still retail capture (S3 §6b)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:36:54 +02:00
Erik
4bc9c796b4 docs(render): S3 chunk 4 contract draft — the deletions
Retail CPU-clips only portal polygons, punch fans and exit seals
(polyClipFinish); ordinary meshes, shells, terrain, particles and the
weather are never view-clipped. Inventory at edb32783: keep the seal and
punch clips (with equivalence pins), delete the per-slice weather loop,
the sky-post-scene particle clip slot, the dead cell-shell clip routing,
the slot-list shape of the part classifier, and the seven
ProbeCathedral* discriminators with their launch-option rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:31:25 +02:00
Erik
edb3278370 docs(render): chunk 3 R5 — the second sky pass is retail's weather pass
GameSky::Draw 0x00506ff0 arg2==1 is the weather pass gated on
SmartBox::is_player_outside 0x00451e80, already modeled by RenderWeather;
chunk 3 only has to keep it after the last land cell.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:29:55 +02:00
Erik
887f221674 docs(render): ledger — S3 chunk 3 contract written; S4 notes the order-only punch hypothesis
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:28:43 +02:00
Erik
296bfd8d48 docs(render): S3 chunk 3 contract -- the landscape interleave
Verified against the two cathedral transcripts and the decomp: DrawBlock
0x005a17c0 draws LandCell then SortCell per land cell (alwaysDrawObjects=1,
flush=0.75 makes the per-cell alpha flush inert); the ported ring order,
closest-cell table and ring-to-LOD mapping reproduce every captured LC/SC
sequence at both poses with zero mismatches once LOD cell ids are read as
x*8+y+1 in LOD coordinates; one land cell's terrain is arithmetic on the
existing cell-major 384-index landblock mesh. The interleave is expected to
remove the Holtburg terrain-punch leak by draw order alone (S4 hypothesis);
LScape::draw draws the sky twice (before and after the blocks).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:28:10 +02:00
Erik
fa217bc6c7 docs(render): record the retail land-cell draw order from the cathedral captures (S3 chunk 3 oracle)
Frame 2 of both cathedral transcripts: one LS, then LC/SC in strict
per-cell alternation, blocks far-to-near with the diagonal interleave
from the Chebyshev-10 ring inward, far blocks at one cell per block, and
SC for all 64 cells of a near block while LC fires only for in-view
cells. This is the interleave chunk 3 ports and the transcript pins.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:18:36 +02:00
Erik
5c64679b11 docs(render): S3 chunk 2 contract -- exact PView state
Decomp-verified during the capture session: PView::DrawCells 0x005a4840
keeps the landscape flush, stamp advance, gated Z clear and exit seals
inside outside_view.view_count > 0; the clear is gated by the persistent
D3DPolyRender::portalsDrawnCount (0x008719b4), which only exit seals feed
in the building path (pass 1 punches pass TRUE; forceClear is never
written). acdream's unconditional clear/seals and the _skyDrawnThisFrame
proxy are the divergence chunk 2 retires. The captures' second PView is
outdoor_pview's look-in flood (RenderDeviceD3D::Init 0x0059efb0).

Also: the cathedral floating-stairs scene row now expects retail's
exterior-slab leak (retail axiom), the retail screenshot is saved at
logs/oh-capture/cathedral-leak.retail.png, and the S3 ledger row moves to
chunk 2 in progress.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:14:39 +02:00
Erik
c1b24ec0c0 docs(render): record the cathedral-arrival retail capture (S3 §6b)
Walk (5 frames), parts (3) and alpha-depth (5) transcripts captured from
the paired 2013 client at the owner's cathedral-arrival pose. The live DI
was f4180108 (stair chamber), not the f4180106 the kit README expected
from FW0's still; recorded as-is. A second PView (009d4530, ov=0) draws
f4180112-14 each frame with no DI of its own -- flagged for chunk 2.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 07:00:24 +02:00
Erik
cebc9f6af9 docs(render): cathedral-leak pose — owner's retail screenshot described beside the transcript
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:54:55 +02:00
Erik
9c0709d4b7 docs(render): S3 packet — capture session progress, cathedral-leak retail oracle
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:52:49 +02:00
Erik
6d5afcccde fix(render): S2 chunk 6 review round — one particle turn per cell per stamp, cheap empty cells, dead owner-set stub deleted
Retail-lens review of chunk 6 (no blocking finding). Fixed:
- a cell that gets two object-list turns in one frame (a chamber reached
  through two portals) submitted its emitters twice; retail's particle parts
  sit in the same shadow_part_list as every other part and CPhysicsPart::Draw's
  frame stamp suppresses the second draw, so the walk now dedupes the particle
  turn with the same frame-scoped set that dedupes the cell shell;
- every visited land cell paid the full per-cell draw setup even with no
  emitter; DrawForCell now returns after the cell lookup, retail's own cost
  (DrawPartCell 0x005a07a0 `num_shadow_parts > 0`);
- CopyRenderableEmittersInCell maintains LastRenderScopeEmitterVisitCount;
- the OutdoorSceneParticleEntityIds / outdoorOwnerIds stub chain (permanently
  empty, never read) is deleted through IWorldSceneRenderer,
  WorldScenePViewRenderer, IWorldScenePasses and the composition root;
- AD-117 item 4 names the two behavioral residuals (owner-cell substitution;
  no per-emission AddPartToShadowCells);
- ParticleHookSinkTests pins that an emitter's draw cell is its owner's pose
  cell and survives the projection-visibility switch across the per-frame
  view pass.

Gates: Core 4,988/4,988 (Vfx 108/108), App hermetic 6,760/6,760, Runtime
1,884/1,884.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:52:28 +02:00
Erik
7969c2e6ad tools(walk-oracle): parts capture guards null part-array slots (cdb aborted the PD/DM action on a null gfxobj)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:40:35 +02:00
Erik
b62dbf035c tools(walk-oracle): capture the per-land-cell draw order (LC/SC lines) for S3 chunk 3
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:31:54 +02:00
Erik
e7b6dc03c5 docs(render): OVERHAUL ledger — G2 PASSED by the owner, S2 closed
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:30:29 +02:00
Erik
924652626b docs(render): OVERHAUL ledger — S2 chunk 6 landed, haze verified, handoff addendum
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:28:39 +02:00
Erik
f6b4584bf3 feat(render): S2 chunk 6 — particle emitters draw by their own cell (add_particle_shadow_to_cell)
Owner G2 finding: the purple cloud around an arriving character no longer
drew. The server keeps the player Hidden until acdream sends LoginComplete at
reveal completion (retail-correct); the Hidden-state script's emitters spawn
in the arrival cell and are view-eligible when the world appears, but the
walk drew an owner's emitters only through the owner's registry rows, and a
hidden owner's shadow is suspended. Retail's
CPhysicsObj::add_particle_shadow_to_cell (0x00514a70) gives an emitter one
shadow in its OWN current cell, drawn at that cell's turn regardless of the
parent's hidden state (add_shadows_to_cells 0x00514aed skips the flood for
state & 0x1000).

Port: ParticleSystem keeps a per-pass cell -> renderable-handles index
(maintained at every renderable/OwnerCellId change) and
CopyRenderableEmittersInCell; ParticleRenderer.DrawForCell; the walk draws
particles BY CELL at the existing turns (interior CellParticles, landscape
LandscapeCellParticles), the events fire for every visited cell, and every
owner-union particle path is deleted (UnionOwners/UnionNewOwners for
particles, the outdoor drawn-owner dedupe, the executor's owner
classification sets, the context ParticleOwnerIds members). The post-replay
per-cell pass double-submitted the root flood's emitters and is deleted: an
emitter draws once, at its cell's replay turn. AD-117 item 4 becomes a port
note (the index lives in the particle system; an emitter is not a physics
object in acdream). The temporary [pes-spawn]/[pes-vis] traces are removed
and the ACDREAM_DUMP_PLAYSCRIPT row restored.

Verified: timed arrival route logs/selfgate-20260903-062522-haze-chunk6,
frame h02-arrive-400ms shows the cloud at the character in Facility Hub.
Gates (Release): Core 4,987/4,987; Content 214/214; Runtime 1,884/1,884; App
hermetic lane 6,760/6,760; App InstalledDat 217 pass / 2 pre-existing #383.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 06:28:09 +02:00
Erik
2d20ee917b checkpoint(render): portal-haze root cause — emitters need own-cell membership (S2 chunk 6 contract)
Instrumented arrivals show the Hidden-state cloud's emitters spawn in the
arrival cell, become view-eligible when the world appears, and are never
drawn: the walk draws an owner's emitters only through the owner's registry
rows, and a hidden owner's shadow is suspended. Retail's
CPhysicsObj::add_particle_shadow_to_cell (0x00514a70) gives an emitter one
shadow in its own cell, drawn at that cell's turn regardless of the parent's
hidden state. S2 chunk 6 (packet §10) ports that: per-cell emitter draw
membership, owner-union particle path deleted. Route timing fixed so the
arrival screenshots anchor on the reveal.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 05:49:45 +02:00
Erik
7ec72765d7 checkpoint(render): G2 owner findings — terrain punch assigned to S4, portal-haze probe
Owner G2 check at 4b0b29e4: Facility Hub PASS, Holtburg house PASS,
cathedral leak unchanged (S3/S4). Two new findings:
- doorway-sized fragments of houses on the terrace below show through
  the hill in Holtburg: PortalDepthMaskRenderer draws every visited cell's
  exit-portal fan with depth compare Always + write, so a doorway behind
  terrain still punches far depth through it. Pre-existing; S4 owns the
  punch (ledger row updated).
- the purple UnHide haze (script type 0x75, played on the retail
  Hidden->visible physics-state edge) no longer shows on the local player
  after a portal. Under investigation: temporary print-only traces
  [pes-spawn]/[pes-vis] under ACDREAM_DUMP_PLAYSCRIPT=1 (launch-options row
  amended; both die with the investigation) and a timed arrival route
  tools/overhaul-selfgate/route-portal-haze.txt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 05:32:18 +02:00
Erik
4b0b29e4cd docs(render): AD-117 item 1 retired — the render-only destination-cell move is retail's own zero-sphere find_cell_list
CObjCell::find_cell_list (0x0052b4e0) with num_sphere == 0 adds only the
current cell — interior CELLARRAY::add_cell at 0x0052b563, outdoor
CLandCell::add_all_outside_cells (0x00533630, the arg2 <= 0 branch:
adjust_to_outside + gid_to_lcoord + add_outside_cell) — and skips the
portal transit walk (`arg4 != 0 && arg2 != 0` at 0x0052b576). So a shapeless
object's transition cell array is its destination cell alone, exactly what
RefreshPositionRows publishes. Not an adaptation; the register row keeps
its three residual readings, the S3 packet drops the capture request, and
the registry/test comments cite the verified function.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 01:18:50 +02:00
Erik
3597c90446 docs(render): OVERHAUL ledger — connected nine-stop soak PASS on the final S2 build
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 01:13:26 +02:00
Erik
31465a0ece docs(render): OVERHAUL S3 ownership packet (draft, pre-capture)
s3-walk-ownership-map.md: the decomp-verified retail table for the walk
(views, stamps, DrawCells order, DrawBuilding sequence, landscape
far-to-near interleave), the current acdream owners with the S2-era
assessment, the four bounded chunks (transcript emitter blocked on the
owner's capture; exact PView state; landcell interleave; deletions), the
two review lenses, the automated gate, and the three exact traces to ask
for at the capture session. Ledger S3 row flipped to PACKET DRAFTED /
blocked on the capture; the G2 handoff points at it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 01:06:16 +02:00
Erik
78068b2cfe docs(render): OVERHAUL ledger — S2 code-complete, G2 provisional PASS, morning handoff
§13: S2 row records chunk 5 + closeout `c94a1a40`, the review fix batch, the
gate counts, every self-gate run (the chunk-5 FAIL on the Facility wall
panels and the candidate PASS), the membership-probe run and the chunk-4
connected soak; the gate table names the six S2 commits and the revert rule.
The G2 morning handoff gives the owner the candidate build, the checklist,
the PNG paths and the automated-gate summary; G2 stays provisional until the
owner double-checks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 01:03:26 +02:00
Erik
c94a1a407e feat(render): Campaign OVERHAUL S2 chunk 5 + closeout — registry is the only render membership owner
Chunk 5 (consumer cutover): WalkProductionWorldData's per-cell views are
borrowed from ShadowObjectRegistry.GetRetailPartEntriesInCell and resolved
through RenderSceneQuery.TryGetByLocalEntityId; every render-side sweep,
bucket, parent-cell and root-position fallback is deleted (AD-116 for the
one-frame registry→scene window, counted in UnregisteredRenderMembershipCount).
A live entity with visual parts but no collision geometry registers
render-only (LiveEntityCollisionBuilder computes the part array before the
empty-shapes gate).

Closeout fixes found while landing it:
- RefloodOwnerForLandblock forwards the retained part array — a reflood is
  retail's recalc_cross_cells over the SAME CPartArray; without it every owner
  touched by a landblock replacement commit lost its render membership.
- Non-colliding DAT statics register render-only from BOTH publishers
  (LandblockPhysicsPublisher.PublishStaticEntity,
  LandblockPhysicsContentBuilder.RegisterRenderOnlyStatic). The G2 self-gate
  pixel diff caught them vanishing (Facility Hub wall panels): retail floods
  every object regardless of collision (CEnvCell::init_static_objects
  0x0052c350, add_shadows_to_cells 0x00514ae0).
- S2 dual review fix batch (arch + retail lens, lead-verified):
  Suspend clears the retail product (remove_shadows_from_cells 0x00511230 is
  one transaction); AttachChild/DetachChild advance the mutation revision so
  a prepared SetPosition cannot clobber a child's rows; an attached child
  never floods on its own re-registration; RemoveLandblock and the non-rooted
  RetireOwnerFromLandblock prune retail rows (render-only statics end with
  their landblock); a render-only owner's no-cell-array commit republishes at
  its destination cell (AD-117); an empty non-null part array is treated as
  null; per-move closures/LINQ replaced by index loops; EnvCell shells stay
  out of the scene's LocalEntityId index (payload-less records); the index
  predicate compares the id; the dead per-cell scene indices are deleted.

Register: AD-116 (chunk 5), AD-117 (four residual Contract A/B readings).
Evidence: s2-membership-ownership-map.md §8 (chunk 5) and §9 (closeout).

Gates (Release): Core 4,984/4,984; Content 214/214; Runtime 1,884/1,884;
App hermetic lane 6,760/6,760; App InstalledDat lane 217 pass / 1 skip /
2 pre-existing #383 layout-fixture failures; App Windows lane 1/1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 01:01:47 +02:00
Erik
f30039d3d9 docs(render): ledger - connected R6 route passes on the chunk-4 build
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 00:01:10 +02:00
Erik
b58d64c5f1 docs(render): ledger - chunk-4 self-gate run recorded, R6 soak started
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:40:28 +02:00
Erik
6717a3e509 docs(render): ledger - S2 chunk 4 landed, chunk 5 in progress
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:37:35 +02:00
Erik
75ea269d35 feat(physics): S2 chunk 4 - movement publishes from the transition's cells; children inherit at registration
Movement: CommitSetPosition's RefreshPositionRows/ReplacePositionRows and
the staged apply publish the retail render product from the exact cell
list collision just used, the transition's cell_array retail feeds
add_shadows_to_cells in CPhysicsObj::SetPositionInternal @0x00515330
(pseudo-C 283526-283539); the separate move-path bbox recompute is deleted.
calc_cross_cells @0x00515230 stays the distinct full-recompute path
(PhysicsShadowCommitAction.Recalculate).

Children (Contract B recursion): ShadowObjectRegistry.AttachChild/DetachChild
give an attached object the root's current cells as part entries only,
republished whenever the root's array changes, detached at withdrawal and
cascaded from the root's Deregister; nested attachment resolves to the root
with a bounded, cycle-safe chain. EquippedChildRenderController attaches at
realization (FromSetupRenderParts over the child's Setup) and detaches at
its single removal funnel. WalkProductionWorldData's dynamic sweep reads
TryGetRetailCellArray directly; the 64-hop parent-chain walk and its
FindParentLocalId plumbing are deleted. CollisionWorldState.Clear now
also clears the retail products.

Gates (implementer's isolated worktree at identical content): Release
build 0/0; Core 4,970/4,970; App hermetic 6,761/6,761; targeted
walk/child/live-entity/placement/comparator 166/166; Runtime 1,884/1,884.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:37:34 +02:00
Erik
706fc49397 docs(render): ledger - self-gate baseline and chunk-3 runs recorded
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:18:24 +02:00
Erik
ea546f381b tools(render): self-gate - list screenshots recursively, no plugins in gate sessions
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:16:31 +02:00
Erik
b7e6ec7769 docs(render): ledger - S2 chunk 3 landed, chunk 4 in progress
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:03:50 +02:00
Erik
afbd241016 feat(physics): S2 chunk 3 - one flood per registration feeds collision rows and render entries
ShadowObjectRegistry computes the CELLARRAY once per registration under
Contract A (cylsphere route from the Setup's collision cylspheres, else the
bbox route over the whole visual part array) and derives BOTH products from
it: the collision rows (_entityToCells/_cells, CShadowObj per cell via
add_shadows_to_cells @0x00514ae0) and the per-part render entries
(AddPartsShadow @0x00517e40). The second, independent collision flood is
gone. A caller that supplies no part array floods from its collision shapes
exactly as before, so every legacy expectation holds byte-for-byte.

The staged SetPosition pipeline now carries the retail part array, cell
array, route, and entries through TryCaptureOwnerState/InstallOwnerState
and publishes them beside the collision cell replacements, honoring the
keep-when-empty rule (SetPositionInternal num_cells gate, pc:283540) for
both products together; two new tests pin a cross-cell move and the
keep-when-empty case. Behavior change, retail-exact: an object with
decorative non-BSP parts now has its collision shapes registered in every
cell those parts reach (pinned by a two-cell fixture); all-BSP objects are
unchanged. Movement paths still take collision cells from the transition
and recompute the retail product separately; chunk 4 unifies them on the
transition's array as retail does. No particle emitter reaches this registry.

Gates (implementer's isolated worktree at identical content): Release
build 0/0; Core 4,961/4,961; App hermetic 6,760/6,760; collision/InstalledDat
fixtures 63/63; Runtime 1,884/1,884; Content 213/213.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 23:02:47 +02:00
Erik
d79058cec4 docs(render): ledger - S2 chunk 2 landed, chunk 3 in progress
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 22:32:54 +02:00
Erik
707d2803a4 feat(render): S2 chunk 2 - render statics borrow the registry's retail cell array
WalkProductionWorldData no longer floods; its indoor and outdoor static
sweeps read ShadowObjectRegistry.TryGetRetailCellArray (retail's
calc_cross_cells_static @0x00515160 -> AddPartsShadow @0x00517e40
CELLARRAY, computed once at registration). The App-owned render flood
(ResolveStaticRenderCells, its fingerprint cache, the primitive-Setup
special case) and Core's ComputeStaticRenderCells are deleted. The one
remaining fallback, an entity the physics publisher has not registered yet
while the projection journal already published it, buckets to the authored
parent cell and is counted per frame (UnregisteredStaticRenderFallbackCount)
for chunk 5 to judge on the connected route.

The Facility stair pin now registers at the projection's own entity id
(the old pure-function test never carried identity) and reads the retail
array; the installed-DAT comparator compares retail against collision.

Gates (run in the implementer's isolated worktree at identical content):
Release build 0/0; Core Physics 2,202/2,202; App hermetic 6,760/6,760 (the
two added WalkProductionWorldData tests); installed-DAT walk/flood/stair
family 24/24; Runtime 1,884/1,884.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 22:31:46 +02:00
Erik
2b40c0bb38 tools(render): self-gate kit - session config, teleport route, runner
Lead-run visual gate: direct character login through a session config,
the owner-supplied /teleloc poses (cathedral floating stairs, Facility Hub
stairs, Holtburg house), one screenshot per pose into the automation
artifact directory, graceful close-client. The runner refuses to start
while any AcDream.App process exists and never hard-kills a client.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 22:08:56 +02:00
Erik
7adbffcb6a docs(render): record owner-supplied self-gate poses
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 22:05:51 +02:00
Erik
5a2792d689 feat(physics): S2 chunk 1b - callers supply the visual part array; installed-DAT comparator
Every production registration now hands ShadowObjectRegistry the object's
whole visual part array beside its collision dispatch: static publication
(App LandblockPhysicsPublisher and the headless Content twin) through
ShadowShapeBuilder.FromStaticRenderParts, live entities (Runtime
LiveEntityCollisionBuilder) through the new FromSetupRenderParts, which walks
every Setup part with the same physics-sphere-else-drawing-sphere and
part-box rule from the PhysicsDataCache Runtime already reaches. Nothing
consumes the retail products yet; the App hermetic lane still passes
6,758/6,758.

The Lane=InstalledDat comparator registers five real fixtures through the
real publication inputs and prints retail CELLARRAY, collision cells, and
the old render cells side by side: Facility Hub stair Setup 0x02000623
(7 cells incl. 0x8A02015F/015E), cathedral ramp 0x020009A2 (3 cells, the
genuine multi-part case), the #334 Neftet formation (25 cells), and a
landblock-edge crosser (6 cells, 2 in the neighbor block). All three
answers agree for BSP-bearing objects, as the shared primitive predicts;
the divergence chunk 3 expects appears only for decorative non-BSP parts.

Core Physics 2,202/2,202; Runtime 1,884/1,884; App hermetic 6,758/6,758;
comparator + stair pin 5/5; solution Release build 0 warnings / 0 errors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 21:52:35 +02:00
Erik
059b8883ab feat(physics): S2 chunk 1a - retail cell array and per-part entries beside the collision flood
Campaign OVERHAUL S2 chunk 1 (Core half). ShadowObjectRegistry accepts the
object's whole visual part array as an optional registration input and
computes retail's CELLARRAY from it as a retained side product:

- route per CPhysicsObj::calc_cross_cells_static @0x00515160: cylsphere
  (CObjCell::find_cell_list @0x0052b9f0 over the Setup's authored
  cylspheres, carried as the Cylinder shapes of the COLLISION dispatch) when
  (state & 0x10000) == 0 and a cylsphere exists, else the bbox route
  (find_bbox_cell_list @0x00510fc0 via CellTransit.BuildShadowCellSetFromParts
  over every visual part: physics sphere else drawing sphere, part box);
- per-cell part entries in array-then-part order for every part
  (CPartArray::AddPartsShadow @0x00517e40), clip planes required iff the
  array has more than one cell;
- Deregister clears everything (remove_shadows_from_cells @0x00511230);
  UpdatePosition/CommitSetPosition recompute; ReplaceMultiPartPayload swaps
  the part array without re-flooding.

_entityToCells and _cells are untouched; no production caller passes the
part array yet (chunk 1b), so this is a zero-behavior change. The lead
corrected the implementer's route decision, which had inspected the visual
part array for cylinders; retail's GetNumCylsphere reads Setup collision
data. Core Physics 2,202/2,202.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 21:20:40 +02:00
Erik
015b660d0f test(render): pin cell-shell batch-to-index-segment pairing under reorder
Uploads a cell-shell mesh whose storage order is the reverse of its surface
order and asserts each uploaded batch's FirstIndex reads back its own
indices from the arena. Guards the G1 regression fixed at 8c6563ca.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 21:10:16 +02:00
Erik
e7ad25a705 docs(render): S2 plan packet - membership ownership map and revised chunks
Read-only trace of every production owner of cell membership (render and
physics), the retail transaction they must collapse into (Contracts A/B),
and the five S2 chunks re-cut on that evidence: the two static floods are
one CellTransit walk with different part inputs; retail uses the whole
part array once and registers every part in every array cell; children
inherit at registration; topology consolidation moves to S3.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 20:57:04 +02:00
Erik
75873886f3 docs(render): close S1 at G1 PASS; open S2
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 20:43:51 +02:00