74 KiB
Campaign OVERHAUL v2 — S5 consumers, material, and closeout packet
Status: S5-c1 and S5-c2 LANDED + lead graphical gates PROVISIONAL PASS;
S5-c3 CONTRACTED 2026-09-04, implementation pending.
Branch: claude/campaign-w-retail-frame-walk.
Gate: G4 remains unpassed. Nothing merges to main before G4.
This packet decomposes plan S5 into bounded chunks. The lead writes each contract, one bounded OpenAI implementation agent changes only that contract, the lead verifies every retail claim against the named pseudo-C and the paired executable/PDB, and independent sequential OpenAI review lenses run before landing. Per the owner's 2026-09-04 overrides, no remaining campaign step uses Claude Code, Anthropic models, or Anthropic credentials, and a chunk may receive at most ten review passes. Each code finding still receives a bounded contract; documentation-only findings may be corrected directly by the lead. The chunk stops before an eleventh review. Every surviving deviation is entered or corrected in the divergence register in the same implementation commit.
1. Current boundary after S4
S4-c3b is landed and the lead G3 matrix is a provisional PASS; owner inspection and the owner-only G3 rows remain. S5 must not reopen the green walk, portal depth, or two-FIFO alpha ports without new evidence.
The landscape half is already present and exact:
WalkLandscape.CheckBlocks/LandCellCheckportLScape::draw_check_blocks @0x00505F80andLScape::landcell_check @0x005050A0;WalkVisibilityMathowns the portedget_clip_height/block_checkmath;WalkFrameDriver.VisitedLandscapeCellIdsis populated by the same one walk that emits the retail-ordered terrain/object stream.
S5-c1 therefore changes the consumers and deletes the competing fallback. It does not rewrite the landscape calculation.
2. Retail facts for S5-c1 (lead-verified 2026-09-04)
The executable is C:\Users\erikn\Downloads\acclient.exe. Its CodeView record
is GUID {9E847E2F-777C-4BD9-886C-22256BB87F32}, age 1, matching
refs/acclient.pdb.
2.1 ShouldDrawParticles is distance AND the cell virtual
Named pseudo-C at CPhysicsObj::ShouldDrawParticles @0x0050FE60 reads:
if examination: true
if CYpt > degrade_distance: false
if cell == null: false
if cell->IsInView() == 0: false
true
The paired bytes are the same: fld [ecx+0x24], fcomp [esp+4], the x87
test ah,0x41 gate, null-check of [ecx+0x90], then the virtual call through
vtable slot +0x68. ParticleEmitter::UpdateParticles @0x0051D180 calls that
function at 0x0051D1A1; false enters the SetNoDraw(1) / degraded_out=1
arm, while true clears that state and updates/emits particles.
Preserve the existing x87-compatible comparison, including inclusive equality,
unordered admission, raw negative/zero/NaN/infinity authored distances, and the
deliberate AP-116 range multiplier (Retail=1, default Extended=2).
2.2 outdoor and indoor cells have different IsInView semantics
CLandCell::IsInView @0x00532CB0returns the 32-bit field at+0x104. The paired body is exactlymov eax,[ecx+0x104]; ret. Landscape drawing stamps that field, so particle update consumes the previous completed render frame's landscape answer.CEnvCell::IsInViewis the PDB-vtable slot at0x007C8D00, pointing to the ICF-folded body0x005269F0. The paired body is exactlymov eax,1; ret. Thus an indoor cell with a non-null owner is alwaysPARTIALLY_INSIDEfor the update-time check; its particle drawing remains separately controlled by the cell walk.
AC cell identity already has a production-pinned discriminator:
low = cellId & 0xFFFF; outdoor land cells have 0 < low < 0x0100, EnvCells
have low >= 0x0100, and zero is no cell.
2.3 point lights do not consume the camera walk
Retail collects point lights from the DBObj-load/flush-bounded resident
CEnvCell::visible_cell_table, not from the current camera portal flood.
Current LightManager.BuildPointLightSnapshot(playerWorldPos) likewise uses
the resident registry. RuntimeWorldFrameEnvironmentPreparation's
ObserveDrawableCells / ClearDrawableCells methods are now no-ops, while
AP-85 still describes the deleted last-frame filter. The methods and the stale
claim are tombstones, not behavior.
2.4 the null-root terrain reconstruction is not a retail answer
In-world retail has a viewer-cell root. acdream's null-root path is the AD-21
streaming-gap/debug safety draw. TerrainModernRenderer.CollectVisibleCells
manufactures 64 land-cell ids per retained landblock from camera-frustum AABBs
and publishes them through TerrainVisibleCellIds. That is the only remaining
AP-117 reconstruction. A safety draw with no walk product must publish no
outdoor IsInView answer; it must not invent one.
3. S5-c1 contract — typed IsInView consumers and fallback deletion
3.1 C1 — publish the landscape half explicitly
Extend the borrowed RetailPViewFrameResult with the exact landscape land-cell
set from WalkFrameDriver.VisitedLandscapeCellIds. Keep DrawableCells for
EnvCell shell preparation and keep the existing union VisibleCells only for
diagnostics that compare the two products. Do not re-filter, re-walk, sort, or
derive the landscape set from projection/entity ids.
Rename the particle handoff to make the type visible in the API, for example
MarkVisibleLandscapeCells. It accepts only outdoor land-cell ids and copies
them into the controller's building frame. Passing zero or an EnvCell id is a
contract violation, not something to silently reinterpret.
The completed frame remains the sole retained owner. AbortFrame preserves
the prior completed product, CompleteFrame publishes the new product, and
Reset removes both generations. The update thread continues to call Apply
before the next render, preserving retail's previous-frame timing.
3.2 C2 — evaluate the correct virtual by cell family
Change ParticleSystem.ApplyRetailView so a world-policy emitter is eligible
only when all of the following are true:
hasCompletedView
ownerCellId != 0
(owner is EnvCell OR exact completed landscape set contains ownerCellId)
retail x87-compatible distance predicate
EnvCell means low >= 0x0100; landscape means 0 < low < 0x0100.
Examination and dedicated-pass policies keep their existing bypass. This is an
update/degrade correction only: do not alter emitter-own-cell draw membership,
per-cell particle turns, cone admission, queue routing, alpha order, lifetime,
or tick order.
A completed null-root safety frame has an empty landscape set. EnvCell owners
still see their constant virtual result; outdoor owners fail closed. Login and
portal-space frames still carry hasCompletedView=false and reject ordinary
world-policy emitters.
3.3 C3 — delete AP-117's remaining reconstruction
Delete the complete TerrainModernRenderer.CollectVisibleCells route,
including _visibleCellIds, VisibleCellIds, BeginVisibilityFrame,
IWorldScenePassExecutor.TerrainVisibleCellIds, the null-root publication in
WorldSceneRenderer, and the reconstruction-only tests. The flat terrain draw
itself remains; only its fabricated visibility side channel goes.
After this deletion, AP-117 is retired: the walk path publishes the ported landscape product, and frames without that product publish none. Update AD-21 in the same commit so it no longer claims the login screen shows live sky and states that the safety draw cannot publish cell visibility.
3.4 C4 — delete the dead point-light feedback seam
Delete ObserveDrawableCells and ClearDrawableCells from
IWorldRenderFrameBuilder, IWorldFrameEnvironmentPreparation, their runtime
implementations, all calls, fakes, and tests. Keep point-light snapshot
selection exactly resident-registry based. Correct AP-85 in the same commit to
the code that actually remains: one resident, player-nearest 128-cap pool
instead of retail's separate 7-dynamic/40-static pools and DBObj-granular
residency. AP-68's owner-approved always-lit-interior policy is unchanged.
3.5 Explicit non-changes
S5-c1 must not change:
WalkLandscape,WalkVisibilityMath, block/cell order, landscape event order, terrain draws, membership, portal flood, depth, alpha, shaders, RHI, DAT/package code, or streaming ownership;- point-light capacity, sort anchor, curves, cell/object selection, or AP-68;
- directional-shadow selection (S5-c2 owns that consumer and its retained topology/per-frame visibility design);
- building degrade/complete-body selection (later S5 chunk);
- translucent-detail material combine/AP-232 (later S5 chunk);
- Facility probe and broader cleanup inventory (later S5 cleanup chunk).
No graphical client is launched from the implementation or review worktree.
4. Allowed files
Production changes are limited to the directly affected files:
src/AcDream.Core/Vfx/ParticleSystem.cs;src/AcDream.App/Rendering/Vfx/ParticleVisibilityController.cs;src/AcDream.App/Rendering/RetailPViewRenderer.cs;src/AcDream.App/Rendering/WorldSceneRenderer.cs;src/AcDream.App/Rendering/WorldScenePassExecutor.cs;src/AcDream.App/Rendering/WorldRenderFrameBuilder.cs;src/AcDream.App/Rendering/TerrainModernRenderer.cs;- comment-only truth correction in
WalkFrameDriver.csif required.
Tests may change in the directly affected Core/App VFX, renderer, frame-builder,
and terrain-visibility files, plus compile-fallout fakes for the deleted
interfaces. Documentation is limited to this packet, the plan ledger,
acdream-architecture.md, oh1-construction-landscape-contract.md, and the
divergence register. If implementation requires another production owner or a
new deviation, stop and return the fact before expanding scope.
5. Tests and mutation evidence
Extend production-facing tests to prove:
- an outdoor emitter is admitted only by the exact completed landscape set;
- an EnvCell emitter remains update-eligible at authored range even when no indoor cell is in that set;
- zero cell and no completed world view reject both cell families;
- inclusive/unordered/raw-distance behavior and AP-116 Retail/Extended multipliers remain unchanged;
WorldSceneRendererhands onlyRetailPViewFrameResult's landscape set to the particle owner, never the EnvCell set or diagnostic union;- abort/complete/reset preserve the previous-frame transaction;
- no production
CollectVisibleCells,TerrainVisibleCellIds,ObserveDrawableCells, orClearDrawableCellssymbol remains; - point-light snapshots still include resident lights regardless of the removed feedback set;
- the warmed production particle-view path allocates 0 managed bytes.
Every new pin gets a real sabotage and exact first failure in the implementer commit body. At minimum mutate independently and restore exactly:
- make EnvCell eligibility depend on set membership;
- make outdoor eligibility constant true;
- feed the union instead of the landscape set at the renderer call site;
- restore one
CollectVisibleCellsproduction symbol; - restore one
ObserveDrawableCellsproduction symbol; - invert or exclude the inclusive authored-distance boundary.
6. Automated return and reviews
Implementer return:
git diff --check;- Release solution build, 0 warnings / 0 errors;
- focused Core VFX and App particle/frame/renderer/terrain tests;
- the real warmed 0-B particle-view pin;
- official hermetic lane;
- InstalledDat lane with exactly the documented global failure/skip set and no new failure;
- one clean commit, exact files/counts, and all mutation first failures.
Sequential review 1 — retail fidelity: re-check the named pseudo-C and paired bytes above, the CEnvCell vtable/ICF identity, previous-frame timing, cell-id discriminator, and every preserved x87/AP-116 edge. Review 2 — architecture, production, and gate honesty: prove one retained product, typed call-site reachability, no reconstructed/null-root answer, no point-light behavior change, reset/abort/lifecycle correctness, 0-B steady state, allowed scope, all register prose, all gate counts, and at least three mutation claims. A failed lens receives one bounded fix contract; a third fix round stops the chunk.
7. Remaining S5 decomposition after c1
- S5-c2: exact landscape visibility consumption by directional-shadow caster selection without creating a second set or rebuilding retained topology on every camera-only change.
- S5-c3: retail
DrawBuildingdegrade selection and complete-body null gate. - S5-c4: translucent detail single-stage framebuffer equivalence; retire AP-232.
- S5-c5: delete Facility probes, production
PortalVisibilityBuilderresidue, obsolete fallbacks/flags/tests/claims; add architecture guards. - S5 closeout: full automated/lifecycle/performance program, G4 owner matrix,
documentation closeout, then and only then merge to
main.
8. Pre-review gate correction — retired-row count
The first official hermetic lane is retained as a failed artifact: 16,759 of
16,760 tests passed. The only failure is
WalkStaticStreamPopulatorTests.WorldAlphaCyptDocumentationAndRegister_PinPerCellTruthAndThreeResiduals:
its literal expected 162 active AP rows, while this chunk correctly retires
AP-117 and leaves 161. This is a coupled documentation-test correction, not a
renderer finding and not a review fix round.
The bounded correction may change only
tests/AcDream.App.Tests/Rendering/Walk/WalkStaticStreamPopulatorTests.cs,
replacing the stale active-row count with 161. Do not add a fabricated register
row and do not change the three AP-241/AP-242/AP-243 assertions. Run the exact
failed test first, then a fresh official hermetic lane under a new artifact
name and the required InstalledDat lane. Preserve the original failed artifact
and record both identities in the implementer return.
9. S5-c1 implementation result — 2026-09-04
The bounded implementation publishes WalkFrameDriver.VisitedLandscapeCellIds
as the typed landscape product, retains it transactionally in the particle
visibility owner, and applies the retail cell-family virtual: membership for
land cells, constant true for non-null EnvCells. The null-root terrain
reconstruction and the dead point-light drawable-cell feedback chain are
deleted. AP-117 is retired; AP-85 and AD-21 now describe the surviving code.
The real warmed allocation pin initially exposed that enumerating the retained
SortedSet<int> of world-simulation handles allocated on every Apply. The
owner is now a sorted List<int> maintained at lifecycle mutation time, so the
production Apply loop preserves stable handle order and measures 0 B without
changing queue, router, draw, or particle tick behavior. This is an
implementation-mechanism correction, not a retail behavior deviation.
Focused returns before the official lanes: Core VFX 111/111, App particle /
frame / renderer / terrain 146/146, and the real warmed production allocation
pin 1/1 at 0 B. Release built with 0 warnings / 0 errors. The first official
hermetic artifact, artifacts/s5-c1-hermetic-20260904, is deliberately
preserved at 16,759/16,760: its sole failure was the stale 162-row test literal
after AP-117's retirement. Section 8 authorized only that coupled test
correction; the exact failed pin then passed 1/1 with the truthful 161-row
header and physical count. The one-shot corrected official lane at
artifacts/s5-c1-hermetic-corrected-20260904 then passed 16,760/16,760,
0 skipped, across 14 assemblies. The inclusive InstalledDat lane at
artifacts/s5-c1-installed-20260904 produced the documented global set:
385 passed, 10 failed, 1 skipped. The failures are TowerAscent, the two
#383 layout sweeps, #458 Oh_doorway_still_first_frame_diff, and the six
AlphaFlushCounts_* transcript Facts; the skip is
Sweep_the_lookin_gate_decodes_against_the_street_fixture. No new failure or
skip identity appeared.
Independent mutation ledger (each mutation restored exactly before the next):
- EnvCell eligibility made set-dependent:
ApplyRetailView_UsesLandscapeMembershipButEnvCellConstantVirtualfirst failedAssert.True, expected true / actual false, atParticleSystemTests.cs:553. - Outdoor eligibility made constant true: the same test first failed
Assert.False, expected false / actual true, atParticleSystemTests.cs:559. - Renderer fed the diagnostic union:
PViewWorld_PublishesOnlyLandscapeCellsToParticleVisibilityfirst failed the HashSet equality atWorldSceneRendererTests.cs:279, expected[16842755], actual[16843008, 16842755]. - A production
CollectVisibleCellssymbol was restored:Production_source_has_no_reconstructed_particle_visibility_feedbackfirst failed atTerrainParticleCellVisibilityTests.cs:37, namingTerrainModernRenderer.cs. - A production
ObserveDrawableCellssymbol was restored: the same source guard first failed at line 37, namingWorldRenderFrameBuilder.cs. - The inclusive boundary was changed from
<=to<:ApplyRetailView_UsesOwnerVisibilityAndInclusiveAuthoredDistancefirst failedAssert.True, expected true / actual false, atParticleSystemTests.cs:519.
10. Sequential review 1 — retail lens and fix round 1
The retail lens found no behavioral retail-fidelity defect. It independently
matched the paired executable/PDB identity and bytes for
ShouldDrawParticles, UpdateParticles, both cell-family virtuals, the
previous-completed-frame transaction, the low-word discriminator, examination
bypass, x87 distance edges, AP-116, the exact landscape handoff, and unchanged
particle draw/queue/tick behavior. The lens returned FAIL on comment truth only:
ParticleVisibilityController.UseWorldViewstill says an outdoor fallback can publish the authoritative product, although S5-c1 deleted it.WalkFrameDriver.CopyVisibleCellsTostill calls the diagnostics union the completeCObjCell::IsInViewanswer and says particles, lights, and shadows consume it. Particles now consume only the landscape half, EnvCell particle eligibility is constant true, point lights use the resident registry, and directional shadows remain S5-c2.ParticleSystemcalls the sorted-list lifecycle insertion/removal cost binary even though only the insertion search is binary and list shifts / removal are linear. Its adjacent blanketO(log E)lifecycle sentence must remain scoped to theSortedSetindexes rather than the new list.
Fix round 1 is comment-only. It may change exactly
ParticleVisibilityController.cs, WalkFrameDriver.cs, and
ParticleSystem.cs, plus this packet's result section. Do not change behavior,
tests, register rows, architecture prose, or any other file. Correct the three
descriptions to the surviving ownership/cost model, run git diff --check and
the same focused retail-review classes (47 Core particle tests, 38 App
visibility/terrain/frame/renderer tests, and 3 AP-116 settings/live-object
tests), commit once, then return to a narrow retail comment-truth re-review.
The production/gate-honesty lens remains undispatched until that re-review
passes. A third fix round still stops the chunk.
10.1 Fix-round-1 implementation result
The three stale descriptions are corrected without behavior or assertion
changes. CopyVisibleCellsTo describes a diagnostic union and names the
distinct particle, point-light, and future directional-shadow consumers.
ParticleSystem scopes the logarithmic lifecycle statement to its SortedSet
indexes and records the sorted list's binary-search plus linear-shift insertion
and linear search/compaction removal costs. Focused gate results: Core
ParticleSystemTests 47/47, App visibility/terrain/frame/renderer 38/38, and
AP-116 settings/live-object 3/3; git diff --check is clean. The first narrow
re-review found the UseWorldView result sentence still misstated null-root
transaction state; fix round 2 below supersedes that sentence.
11. Retail narrow re-review — fix round 2 (last allowed)
The narrow retail re-review passed the four-file scope, behavior/test/register
invariance, diagnostic-union wording, sorted-list cost wording, diff check, and
the focused 47 + 41 tests. It found one remaining MINOR comment-truth error:
ParticleVisibilityController.UseWorldView and §10.1 say the null-root safety
draw omits/excludes the completed product. Production begins visibility before
root resolution and calls UseWorldView for every non-login built frame, so a
null-root safety frame completes hasCompletedView=true with an empty landscape
set. Login/portal frames carry hasCompletedView=false. This distinction is
already the bound §3 behavior: null-root invents no fallback cells.
Fix round 2 is the last allowed round and is prose-only. It may change exactly
the UseWorldView XML comment in ParticleVisibilityController.cs and this
packet's result prose. State that non-login world frames participate in the
completed transaction; the retail walk publishes its exact landscape set when
present, while null-root completes an empty set without reconstruction. Do not
change code behavior, tests, register/architecture prose, or any other file.
Run git diff --check, Core particle 47/47, and the combined App/AP-116 41/41;
commit once and return to the same narrow retail lens. Any further finding that
would require a third fix round stops S5-c1 and is written up.
11.1 Fix-round-2 implementation result
UseWorldView now states the production transaction exactly: every non-login
world frame participates; a PView walk contributes its exact landscape set,
while a null-root safety frame completes hasCompletedView=true with an empty
set and no reconstructed fallback. Login and portal-space frames retain
hasCompletedView=false. No behavior or assertion changed. Core particle tests
passed 47/47, the combined App visibility/terrain/frame/renderer plus AP-116
lane passed 41/41, and git diff --check is clean.
12. Owner-authorized documentation/evidence exception — 2026-09-04
The final production/gate-honesty lens found no production-code or test defect but returned FAIL after fix round 2 on two correction-worthy truth gaps:
- architecture and AD-21 say null-root publishes no cell-visibility answer,
while production completes
hasCompletedView=truewith an empty landscape set; and - the official lane summaries identify dirty bases, but the packet does not
independently bind those dirty source deltas to implementation commit
9aadc917a.
Per the campaign rule, S5-c1 stopped and the campaign branch recorded that stop
at efb075619. The owner then explicitly authorized a
documentation/evidence-only exception: "correct docs and continue." The
stop and both failed-lens results remain in history.
The exception is bounded to:
- truth-correcting the null-root sentence in
docs/architecture/acdream-architecture.md; - truth-correcting AD-21 in
docs/architecture/retail-divergence-register.md; - recording this exception and its evidence in this packet; and
- updating only the S5-c1/S5 ledger rows in
docs/plans/2026-09-01-campaign-overhaul-world-solidity.md.
No production code, tests, other register row, architecture section, or prior artifact may change. The correction must state that every non-login world frame participates, a walk contributes its exact landscape set, and null-root completes an empty set without reconstruction; login/portal remain false.
After the documentation correction is committed, create fresh official evidence from that clean exact commit (not a dirty pre-commit tree):
artifacts/s5-c1-exception-hermetic-20260904— hermetic lane;artifacts/s5-c1-exception-installed-20260904— InstalledDat lane.
Both summaries must record the correction commit and WorktreeDirty=false;
their manifests must verify completely. The older dirty-base artifacts remain
preserved as historical evidence but are superseded for landing provenance.
One narrow independent production/gate-honesty re-review verifies only the
authorized documentation diff, exact clean artifact identity/counts/hashes,
and absence of code/test changes. PASS permits landing and the graphical gate;
any behavioral change or further correction-worthy finding stops again.
12.1 Exception implementation result — clean evidence complete
The authorized documentation correction aligns the architecture and AD-21
with production's existing transaction without changing code or tests: every
non-login normal-world frame participates, the walk contributes its exact
landscape set when present, and null-root completes
hasCompletedView=true with an empty set and no reconstruction; login and
portal-space retain hasCompletedView=false.
The pre-exception official artifacts remain preserved as historical evidence,
including their dirty-base identities. They do not become clean commit-bound
evidence by prose assertion. Both replacement lanes ran from exact correction
commit d6592d3ac56bc400bfdaab7cff59306319b5b96d with
WorktreeDirty=false and now supersede the older dirty artifacts for landing
provenance:
artifacts/s5-c1-exception-hermetic-20260904— PASS, 16,760 passed, 0 failed, 0 skipped across 14 assemblies. Its 32-entry SHA-256 manifest verifies with zero missing or mismatched files.artifacts/s5-c1-exception-installed-20260904— 385 passed, the same 10 documented failures, and the same 1 documented skip across 14 assemblies. Its 30-entry SHA-256 manifest verifies with zero missing or mismatched files.Compare-Objectover every non-passing TRX identity against the historical inclusive artifact returned zero differences.
The first clean InstalledDat invocation omitted
ACDREAM_RUN_INSTALLED_DAT_TESTS=1; 97 live-DAT tests therefore self-skipped
with their explicit opt-in message. That invalid evidence is preserved at
artifacts/s5-c1-exception-installed-invalid-missing-env-20260904
(291 passed / 8 failed / 97 skipped) and is not used for acceptance. The
canonical invocation pinned both ACDREAM_RUN_INSTALLED_DAT_TESTS=1 and
ACDREAM_DAT_DIR=C:\\Turbine\\Asheron's Call; it produced the exact documented
identity above without a product change or product retry.
Production and tests remain byte-identical to the authorized contract parent. The plan ledger therefore advances to clean evidence complete, with only the narrow independent production/gate-honesty review pending before landing and the graphical gate.
13. S5-c1 landing and lead graphical gate — 2026-09-04
S5-c1 is LANDED. The mandatory stop remains in campaign history at
efb075619; the owner-authorized continuation was not used to rewrite it.
Reviewed scratch commits 9aadc917a → afaebcad6 → 74a2e4c48 →
ed8200664 → a28384d80 → b7a7eb9e2 → d6592d3ac → b2d56f9e3
map to campaign commits 94a6b5ef3 → 282fe87fb → 4d1110812 →
3f17c9131 → 6bbb9e117 → 36569c0b0 → ad115141a → 1718832e2.
The integrated tree is byte-identical to reviewed scratch tip b2d56f9e3.
The one narrow independent exception re-review returned PASS with no
finding. It verified the exact four-document authorized scope, the corrected
architecture/AD-21 transaction, no src/ or tests/ diff, both clean summary
identities and counts, hermetic 32/32 plus InstalledDat 30/30 manifest
verification, zero non-passing-identity difference from the historical
inclusive InstalledDat artifact, and honest exclusion of the missing-opt-in
attempt.
Fresh campaign verification at 1718832e2: Release solution build PASS with
0 warnings / 0 errors; Core VFX 111/111; focused particle-visibility/frame
38/38; warmed production particle-view allocation plus AP-116 settings/live
object 4/4. The worktree was clean before launch.
The lead graphical gate is PROVISIONAL PASS pending owner inspection.
Before launch, ACE was listening on UDP 9000 as PID 13340 and neither acdream
nor retail client was running. One Release client ran
tools/overhaul-selfgate/route-portal-haze.txt from clean 1718832e2, exited
0, confirmed graceful logout, and left no client process. Evidence root:
logs/selfgate-20260904-171137-s5c1-particle-visibility.
All ten PNGs were captured:
artifacts/screenshots/h00-before.png;- Facility sequence:
h01-arrive-0ms.png,h02-arrive-400ms.png,h03-arrive-1000ms.png,h04-arrive-2000ms.png,h05-arrive-4000ms.png; - Holtburg sequence:
h11-arrive-0ms.png,h12-arrive-400ms.png,h13-arrive-1000ms.png,h14-arrive-2000ms.png.
Lead inspection: both arrival sequences show the authored magenta
materialization particles at 400 ms, the particle effect clears normally by
the later frames, and Facility/Holtburg geometry and actors remain intact with
no obvious visibility regression. This is not owner acceptance. G4 remains
unpassed, nothing may merge to main, and S5-c2 is next.
14. S5-c2 contract — exact landscape visibility for the opt-in shadow pack
14.1 Retail and deviation boundary (lead-verified 2026-09-04)
This chunk ports one retail input, not a retail shadow-map algorithm. Retail has no cascaded real-time directional shadow map; acdream's selected atmospheric pack is the explicit IA-24 deviation. Pack-off remains the retail path and must not build, select, upload, or draw directional-shadow work.
The retail input is the completed landscape in_view product:
- named
LScape::draw_check_blocks @0x00505F80writes a non-OUTSIDEblock result and callsLScape::landcell_check @0x005050A0; the latter stamps eachCLandCell::in_viewfrom the same portal-view interval walk; - named
CLandCell::IsInView @0x00532CB0returns that field at+0x104; - the paired Sept-2013 executable is SHA-256
006FFEADC5D679C871497112A5BD1F87714D0E273E2166BAE5052DDE369297B1. Its CodeView GUID{9E847E2F-777C-4BD9-886C-22256BB87F32}, age 1, matches the PDB, and its relevant bytes are8B 81 04 01 00 00 C3at0x00532CB0;landcell_checkbegins55 8B EC 83 EC 1C 53 56at0x005050A0. The ICF body used by theCEnvCell::IsInViewvtable remainsB8 01 00 00 00 C3at0x005269F0.
Because the directional-shadow prepass runs after enhanced-world preparation but before the current frame's PView walk, it consumes the previous successfully completed landscape product, exactly as S5-c1's retained owner already exposes to update-time consumers. An aborted frame preserves that product; completion replaces it; reset removes it. A first/login/portal-space frame has no completed world view. A completed null-root safety frame has an empty set and may not manufacture a resident/frustum fallback.
IA-24 must be amended in the implementation commit to state this selection adaptation plainly: the opt-in non-retail shadow map borrows retail's prior completed landscape visibility and exact S2 object membership. That amendment does not make the shadow map retail behavior and does not authorize a new fallback or a pack-off change.
14.2 C1 — borrow the one completed visibility product
Publish a typed one-frame RetailLandscapeVisibilityFrame (name may vary only
to fit existing conventions) from the existing completed visibility owner. It
contains:
- the exact completed
HashSet<uint>/IReadOnlySet<uint>by reference, with no copy, union, sort, reconstruction, or second retained set; and - the completed-world-view flag needed to distinguish an authoritative empty answer from no answer.
WorldRenderFrameBuilder captures that borrowed fact before the current frame
can complete and attaches it to WorldRenderFrame as a pack-only input. The
reference remains valid through the shadow prepass and is not retained after
the prepared world is consumed/cancelled. Do not rename the product into a
current-camera claim: on camera-only movement it is deliberately one completed
frame behind.
The membership side of the selector borrows S2's existing
ShadowObjectRegistry.TryGetRetailCellArray; do not copy the registry rows
into the frame and do not add a render-owned cell dictionary. A narrow typed
read seam over that owner is allowed so tests need not construct PhysicsEngine.
14.3 C2 — exact terrain and object selection
Build one reusable, allocation-free per-frame selection over the retained shadow topology:
- If
HasCompletedWorldViewis false, select zero terrain commands and zero world casters. An authoritative empty landscape set also selects zero. - A loaded terrain slot is selected iff at least one of its authored 8x8
outdoor land-cell ids occurs in the exact completed set. Scan the borrowed
set/slot facts directly; no visible-landblock
HashSetis permitted. - A non-building caster is selected iff its non-empty retail CELLARRAY from
TryGetRetailCellArray(LocalEntityId)contains at least one outdoor land cell in the exact completed set. A missing/empty registry product fails closed.ParentCellId,EffectCellId, render bounds, origin cell, resident landblock, and camera frustum are not substitutes. - Building shells are intentionally absent from
ShadowObjectRegistryin retail's building channel. Select a shell by its exact outdoor placement cell,RenderSourceMetadata.EffectCellId; do not test its EnvCellBuildingShellAnchorCellId. Zero/non-land placement fails closed. - Multi-cell objects select once, stable retained caster order is preserved, and a visibility-only change does not touch membership, render-scene registration, caster classification, material classification, mesh lookup, or transform-journal ownership.
Reusable bool/generation-mark arrays keyed by existing caster/terrain slots
are selection scratch, not a second visibility answer, and are allowed.
Another HashSet<uint>, dictionary keyed by cell, LINQ materialization, or
per-frame collection allocation is not.
14.4 C3 — project visibility without rebuilding retained topology
DirectionalShadowCasterFrame.BuildSequence and the prepared
material/mesh-topology DirectionalShadowPreparedDraws.BuildSequence remain
keyed only by their existing scene/mesh/fade topology inputs. A camera-only
visibility change must leave both sequences unchanged and report zero topology
classification/mesh-resolution work.
Project the selection into reusable active draw products instead. For world
draws, arbitrary selected/unselected instances inside one prepared material
group must be represented exactly. A permitted implementation keeps the
retained transform array and emits allocation-free contiguous selected runs
with adjusted BaseInstance/InstanceCount, duplicating the already-classified
batch metadata for split runs. Equivalent retained-index/mask machinery is
acceptable only if GPU tests prove unselected instances cannot reach the
depth map. Merely changing one group's prefix count while leaving interleaved
unselected instances addressable is incorrect.
The active command/batch/run product gets its own per-frame selection sequence
for GPU publication. Rebuilding or re-uploading that bounded indirect product
is not a topology rebuild; re-running TryBegin classification, mesh lookup,
or changing the topology build sequence is. Preserve the one N.5 transform
address space and all existing dynamic-transform journal/replay semantics.
Terrain may rebuild its bounded indirect command list from selected retained
slots each frame, but must not rebuild/upload terrain geometry or slot
topology.
Diagnostics must distinguish resident/prepared topology counts from active selected caster/instance/command counts. Existing celestial direction, cascade fit/quality, day/night/indoor/portal gates, cutout/translucency/fade, foliage wind, transform churn, and two-frame topology-deferral policy remain unchanged.
14.5 Allowed files and explicit non-changes
Production changes are limited to the directly affected owners:
Rendering/Vfx/ParticleVisibilityController.cs;Rendering/WorldRenderFrameBuilder.csand composition compile fallout;Rendering/Scene/DirectionalShadowCasterFrame.cs(selection only; existing topology admission and revision semantics stay fixed);Rendering/Wb/WbDrawDispatcher.DirectionalShadows.cs;Rendering/TerrainModernRenderer.DirectionalShadows.cs;Rendering/DirectionalSunShadowRenderer.cs;- the built-in and declared directional-shadow pack graphs.
Tests may change only in the corresponding frame-builder, visibility,
directional-shadow caster/prepared/GPU/terrain/pack test files and compile-
fallout fakes. Documentation is limited to this packet, the S5 ledger row,
the architecture statement if its shared visibility-owner wording requires a
truth correction, and IA-24. If exact selection requires a production owner
outside this list, a shader/pipeline-layout change, a new divergence, or any
change to ShadowObjectRegistry, stop and return the fact before expanding.
Do not change WalkLandscape, PView ordering/products, terrain/world ordinary
draws, S2 membership mutation, render-scene indices, streaming, portal/depth/
alpha, particle/light behavior, shadow source/quality/cascade math, shader ABI,
RHI contracts, DAT/package formats, or any pack-off pixels/work. No graphical
client is launched from implementation or review worktrees.
14.6 Tests, mutations, automated return, and reviews
Production-facing tests must prove:
- the frame builder borrows the exact prior completed set reference and flag; current Begin does not turn it into a current-camera product;
- complete/abort/reset and first/login/portal/null-root cases have the stated transaction semantics;
- exact CELLARRAY intersection selects multi-cell outdoor static, dynamic, and child casters once, while missing membership and ParentCell-only impostors fail closed;
- a building shell selects by outdoor
EffectCellId, not its EnvCell anchor; - terrain selects only loaded slots reached by exact land cells;
- alternating visible/invisible instances in one material group produce only the correct active instance ranges and stable order;
- camera-only visibility changes alter active output while both retained topology build sequences, classification counts, mesh lookups, geometry, and dynamic-transform mappings remain unchanged;
- topology rebuild, transform journal refresh, fade/mesh-availability retry, generation reset, and the existing two-frame deferral still converge;
- built-in and declared packs consume the same typed selector; pack-off does no shadow work;
- the warmed production selection path allocates 0 managed bytes and retained scratch remains streaming-bounded.
At minimum sabotage and restore exactly: replace CELLARRAY with ParentCell;
select all resident terrain; use building anchor instead of effect cell; admit
missing membership; feed current building scratch instead of the completed
product; change a visibility-only frame so it advances the retained topology
sequence; and collapse an alternating group into a prefix InstanceCount.
Record each exact first failure in the implementer commit body.
Implementer return: git diff --check; Release solution build 0W/0E; focused
visibility/frame/shadow caster/prepared/GPU/terrain/pack tests; the real warmed
0-B pin; official hermetic lane; inclusive InstalledDat lane with exactly the
documented global failure/skip identities; one clean commit and exact file/
count/mutation report.
Sequential review 1 — retail/deviation fidelity: re-check §14.1 against the named decomp and paired executable/PDB, prior-completed timing, CELLARRAY and building-channel sources, IA-24 truth, and pack-off non-participation. Sequential review 2 — architecture/GPU/gate honesty: one borrowed set, no cell reconstruction, arbitrary-instance correctness, no topology rebuild on camera motion, transform/GPU flight safety, 0-B steady state, lifecycle/deferral, allowed scope, counts, and at least three mutation claims. A failed lens gets one bounded fix contract; a third fix round stops and is written up.
14.7 S5-c2 implementation result — clean evidence complete; fix round 1 implemented
The bounded implementation is complete for review. The selected atmospheric pack now borrows the existing visibility controller's exact prior-completed set and completed-view flag by reference. The frame captures that fact before the current transaction begins and borrows S2's retained CELLARRAY owner through a typed read-only adapter. No second visibility set, cell index, or fallback was added.
The retained caster and terrain products now have separate active-selection
projections. Ordinary casters intersect their non-empty retail CELLARRAY with
the completed landscape set; building shells use outdoor EffectCellId;
missing membership and no/empty completed views fail closed. The established
outdoor family remains low != 0 && low < 0x0100 (including 0x41), while a
terrain slot scans only its authored 1..64 cells. Arbitrary selected instances
inside one material command are emitted as exact contiguous
BaseInstance/InstanceCount runs. Active indirect publication advances its
own sequence; caster, prepared-draw, and terrain topology sequences remain
unchanged on visibility-only frames. Terrain snapshot publication also marks
an aborted build invalid so the next frame retries rather than accepting a
partially written snapshot.
Built-in and declared directional-shadow graphs call the same typed selector and pass the same prior product into terrain selection. The existing production pack-off integration remains unchanged and proves no active pack runtime, shadow resource, or shadow work. IA-24 now states the prior-view/S2 selection adaptation and keeps the shadow map explicitly non-retail.
Pre-commit automated evidence:
- Release solution build: PASS, 0 warnings / 0 errors.
- focused visibility/frame/caster/prepared/GPU/terrain/built-in/declared/ pack-off/long-cycle lane: 137 passed, 0 failed, 0 skipped;
- warmed production selection: caster selector, arbitrary-run projection, and terrain projection each measured 0 managed bytes while retained scratch and topology build sequences stayed stable;
git diff --check: PASS.
The required mutations were each built, run against the named production pin, and restored exactly. Their actual first failures were:
- CELLARRAY →
ParentCellId:PriorLandscapeSelection_UsesExactCellArrayAndBuildingEffectCell, firstAssert.Equalexpected[201, 202, 203, 205], actual[204, 205]. - Select every resident terrain range:
PriorLandscapeSelection_ScansExactAuthoredEightByEightCells, firstAssert.Singlefound 3 commands. - Building anchor → placement effect cell:
PriorLandscapeSelection_UsesExactCellArrayAndBuildingEffectCell, firstAssert.Equalexpected[201, 202, 203, 205], actual[201, 202, 203, 206]. - Admit missing membership:
the same caster pin's first
Assert.Equalexpected[201, 202, 203, 205], actual[201, 202, 203, 204, 205]. - Publish current building scratch instead of the completed product:
BorrowedLandscapeFrame_TracksOnlyCompletedTransactionsByReference, firstAssert.TrueexpectedHasCompletedWorldView=true, actualfalseafter the completed empty frame. - Advance retained caster topology during selection:
PriorLandscapeSelection_UsesExactCellArrayAndBuildingEffectCell, first topologyAssert.EqualexpectedBuildSequence=1, actual2. - Collapse alternating selection into one prefix instance count:
AlternatingCasterSelection_EmitsExactContiguousInstanceRuns, first active-command-countAssert.Equalexpected 3, actual 1.
The bounded implementation is commit
603d4bbb05ebc3e840b5d6e66a20a4c9d3cecc8a. All three official summaries
name that exact commit and record WorktreeDirty=false; their existing
SHA-256 manifests verify without a missing or mismatched file:
artifacts/s5-c2-hermetic-20260904— 16,768 passed, 0 failed, 0 skipped; manifest 32/32 present and matching.artifacts/s5-c2-installed-20260904— the first, deliberately preserved broader run used the literalLane=InstalledDatfilter and produced 468 passed, 10 failed, 1 skipped; manifest 30/30 present and matching. It is valid additional evidence, but it is not renamed or presented as the canonical comparison.artifacts/s5-c2-installed-canonical-20260904— the distinct canonical comparison used the same accepted S5-c1 project filter,Lane=InstalledDat&Purpose!=Diagnostic, and produced 385 passed, 10 failed, 1 skipped; manifest 30/30 present and matching.
Both S5-c2 InstalledDat artifacts contain the same 11 nonpassing TRX
identities as the accepted S5-c1 canonical artifact. The broad-versus-S5-c1
and canonical-versus-S5-c1 Compare-Object comparisons each returned zero
differences. Their different passing totals remain explicit because the two
intentional filters are not interchangeable.
Sequential retail/deviation review returned PASS without a production correction. Sequential architecture/GPU/gate-honesty review found the code, architecture, GPU-flight safety, lifecycle, allocation, and implementation scope otherwise passing, but returned FAIL because this result and the campaign plan still described clean evidence as pending and named only the broader InstalledDat run. Fix round 1 changes only those two evidence/status documents and is implemented pending narrow re-review. The stationary three-buffer per-frame publication is real, explicitly permitted by §14.4, and bounded by Vulkan's two-flight retirement fence; it is a performance note, not a correction and not the #350 mechanism.
15. S5-c2 production-review fix round 1 — evidence provenance only
Retail/deviation review passed the exact implementation commit
603d4bbb05ebc3e840b5d6e66a20a4c9d3cecc8a without a correction. The
subsequent architecture/GPU/gate-honesty review found no production-code,
test, lifecycle, allocation, GPU-flight, or scope defect. It returned FAIL on
one documentation-only truth gap: §14.7 and the plan still say clean evidence
is pending and name only the first, broader InstalledDat run, while two clean
InstalledDat artifacts now exist with different intentional filters.
This is fix round 1. It is bounded to evidence provenance and status text:
- Change §14.7's heading and tail from pending/future tense to the exact clean
results already on disk. Name the implementation commit and
WorktreeDirty=false. - Record the hermetic artifact
artifacts/s5-c2-hermetic-20260904: 16,768 passed, 0 failed, 0 skipped; SHA-256 manifest 32/32 present and matching. - Preserve and explain the first InstalledDat artifact rather than hiding,
renaming, replacing, or calling it canonical:
artifacts/s5-c2-installed-20260904ran the literal filterLane=InstalledDatand produced 468 passed, 10 failed, 1 skipped; manifest 30/30 present and matching. - Name the distinct canonical comparison artifact
artifacts/s5-c2-installed-canonical-20260904. It ran the same accepted project filter used by S5-c1,Lane=InstalledDat&Purpose!=Diagnostic, and produced 385 passed, 10 failed, 1 skipped; manifest 30/30 present and matching. - State that both S5-c2 InstalledDat artifacts have the same 11 nonpassing
identities as the accepted S5-c1 canonical artifact and that both exact
Compare-Objectcomparisons returned no differences. Do not collapse the two passing counts into one claim. - Record both sequential review outcomes honestly: retail PASS; production FAIL on this evidence-text defect only, with code/architecture/GPU-flight otherwise passing. The stationary three-buffer per-frame publication is real, explicitly permitted by §14.4, and bounded by Vulkan's two-flight retirement fence; it is a performance note, not a correction or #350 mechanism.
- Update only the S5-c2/S5 status text in the campaign plan to say fix round 1 is documentation-only and implemented/pending narrow re-review. Do not mark the chunk landed, review-closed, self-gated, or user-accepted.
Allowed files are exactly this packet and
docs/plans/2026-09-01-campaign-overhaul-world-solidity.md. No source, test,
register, architecture, artifact, manifest, filter, or client change is
authorized. Do not rerun a lane or launch the graphical client. Return one
clean docs-only commit, git diff --check, exact file/count report, and prove
every named artifact/manifest/count/filter directly from its existing files.
One narrow independent production/gate-honesty re-review then checks only the two corrected documents against the three clean artifact directories and the two recorded review verdicts. A new correction-worthy finding would be fix round 2; a third fix round still stops S5-c2 and is written up.
16. S5-c2 review closeout, landing, and lead graphical A/B — 2026-09-04
The narrow independent production/gate-honesty re-review returned PASS with no finding. It checked the two-document fix-round scope, all three clean artifact directories and manifests, both InstalledDat filters and counts, the two unchanged nonpassing-identity comparisons, and the recorded sequential review verdicts. No production or test file changed in fix round 1.
The reviewed scratch stack maps to the campaign branch as follows:
- implementation
603d4bbb05e->a4de2efc4; - lead fix-round contract
0025bb2c097->048027e71; - evidence/status correction
521f5edda54->ef819eedf.
The integrated campaign tree at ef819eedf is byte-identical to reviewed
scratch tip 521f5edda54. Fresh campaign verification passed: Release solution
build 0 warnings / 0 errors and the affected 137-test lane 137/137. The
official clean evidence remains §14.7's hermetic 16,768/16,768, broader
InstalledDat 468 pass / 10 documented fail / 1 skip, and canonical
InstalledDat 385 pass / the same 10 documented fail / 1 skip, with all
manifests and nonpassing identities verified.
The first graphical run at
logs/selfgate-20260904-182320-s5c2-shadow-selection captured all seven
transition PNGs and reached its checkpoint without a fatal log entry, but its
route omitted close-client. GLFW exposes no main-window handle to the runner,
so the runner's graceful external close could not succeed. The owner was away
from the computer and explicitly directed the lead to close it; after the
graceful path was exhausted, the lead terminated only the verified campaign
PID. This run is retained as visual evidence but its teardown is FAIL, not
the valid c2 gate.
The lead then added an out-of-tree A/B route with an in-client close-client
step and built exact parent 5c106bcdf in detached worktree
s5-c2-ab-parent (Release 0 warnings / 0 errors). Before each run ACE was UP on
UDP 9000 as PID 13340 and no graphical client was running. Exact evidence:
- parent:
s5-c2-ab-parent/logs/selfgate-20260904-183815-s5c2-parent-shadow-ab; - candidate:
logs/selfgate-20260904-183925-s5c2-candidate-shadow-abat cleanef819eedf.
Both runs produced all seven PNGs, exited 0, logged graceful logout confirmed, left no client process, and contained no fatal/unhandled/device-lost/validation match. Candidate metadata shows exact active selection rather than retained topology fallback: 2,500 selected casters on the first high frame and 3,087 after re-enable, with four cascades and 26 draws; pack-off reports zero pack work. Terrain, buildings, actors, UI, weather transitions, resize, and pack off/on recovery remain present. The lead verdict for S5-c2's own scope is PROVISIONAL PASS pending owner inspection.
The A/B also proves a conspicuous darkening on atmospheric re-enable is
pre-existing: exact parent and candidate both reproduce it. The receiver
shaders switch outdoor directional lighting from authored
-uLights[0].dirAndRange to uShadowLightDirectionAndSource whenever the
shadow flag becomes nonzero; the shadow-strength weight does not blend that
lighting-direction change. This is not an S5-c2 regression, but it is not
silently accepted as a solid-renderer result: issue #469 records it and IA-24
now names the gate-visible discontinuity. It must be resolved or explicitly
owner-accepted before G4. S5-c3 is next; G4 remains unpassed and nothing may
merge to main.
17. S5-c3 contract — exact building degrade selection and complete-body gate
This chunk is deliberately bounded to the building part-0 path named by S5.
It replaces the capture-specific fixed +0.99 selection, preserves the
selected GfxObj identity separately from its optional drawing BSP, draws that
selected shell, and makes the three already-authored Config preferences live.
It does not add generic entity LOD, change S5-c1 particle visibility, change
S5-c2 shadow selection, or implement the fixed-function material work reserved
for c4.
17.1 Lead-verified retail and paired-binary facts
The paired executable is C:\Users\erikn\Downloads\acclient.exe, SHA-256
006FFEADC5D679C871497112A5BD1F87714D0E273E2166BAE5052DDE369297B1.
Its CodeView record remains GUID {9E847E2F-777C-4BD9-886C-22256BB87F32},
age 1, matching refs/acclient.pdb. Fresh read-only Ghidra output was checked
against the named pseudo-C. Exact function byte ranges are:
| Function | VA / file offset / length | SHA-256 |
|---|---|---|
SceneTool::UpdateFPSCounter |
0x0043E510 / 0x0003E510 / 176 |
4B49B883F2F03284F08BAF70716F2AFFAA6591EAD4142D8D5A68879F79CA9DA2 |
CPhysicsPart::Draw |
0x0050D7A0 / 0x0010D7A0 / 192 |
965E1E6208DF662EE3466AA455CFF57BBDEA8AA3751E4DE2F5FD30C3842661FA |
CPhysicsPart::UpdateViewerDistance |
0x0050E030 / 0x0010E030 / 384 |
30F0EEA8829728497E1D00E0D9737DF9EB112CC6643A24ED6150F1350D29D49D |
GfxObjDegradeInfo::get_degrade |
0x0051E4B0 / 0x0011E4B0 / 400 |
E0FE4A2BC79F108985B84DDBA44460B8B80809AE81088779D02C2FEF6CCDD8B7 |
Render::SetDegradeLevelInternal |
0x0054C3C0 / 0x0014C3C0 / 240 |
9A59895EC901ABA75584EA5B059222C00CC9CF2B7AF54F5FB7C2A2CF444D83E4 |
Render::CalcDegLevel |
0x0054CAF0 / 0x0014CAF0 / 736 |
607DC8B8DBAAB9498C163241CE535E14751378A7EC06DFFD724BB68910C7BB08 |
RenderDeviceD3D::DrawBuilding |
0x0059F2A0 / 0x0019F2A0 / 177 |
0FEC14C65D32DACEA0344A9F347937A2588CE3D14694AC658607BDFE5ACDE125 |
RenderDeviceD3D::DrawBuilding @0x0059F2A0 always publishes the building's
outdoor portal list and calls UpdateViewerDistance(parts[0]). Its complete
body is gated only by
parts[0]->gfxobj[parts[0]->deg_level] != nullptr. Inside that gate retail
sets building/detail state, calls FlushAlphaList(0f), calls
CPhysicsPart::Draw(part0, 1) for the portal-only walk, sets the building
flag, calls CPhysicsPart::Draw(part0, 0) for the selected shell, clears the
flag, and clears detail state. A non-null selected GfxObj whose drawing_bsp
is null therefore still crosses the alpha barrier and draws its shell; only
the portal-only sub-walk naturally emits nothing. The current acdream
if (bsp is null) return conflates those facts and is wrong.
CPhysicsPart::Draw @0x0050D7A0 normalizes its local level to zero when the
part has no degrade descriptor or its stored level is outside the loaded Gfx
array, then indexes gfxobj[level]. A null selected GfxObj returns; a non-null
one reaches DrawMesh. UpdateViewerDistance @0x0050E030 measures from the
viewer to the base GfxObj's sort center after component-wise part scale, stores
CYpt and heading, selects level zero/mode one for a missing ladder or the
player, otherwise calls get_degrade(CYpt / gfxobj_scale.z), and calculates a
draw frame only when the selected GfxObj is non-null.
GfxObjDegradeInfo::get_degrade @0x0051E4B0 uses
max(0, abs(distance) - Render::s_rDegradeDistance). With automatic degrades
enabled it uses Render::deg_mul; otherwise it uses
Render::s_rUserSuppliedDegradeBias. For a nonnegative multiplier the strict
threshold is ideal - (ideal - max) * multiplier; for a negative multiplier
it is ideal + (ideal - min) * multiplier. The first strict effective < threshold match wins; equality advances; no match selects the last level.
degrades_disabled forces level zero and that level's mode; a forced level is
clamped to the last slot. This chunk has no production force-level or global
disable control, but its pure selector must keep those two explicit inputs so
the retail branches are pinned and no future caller must fork the algorithm.
The binary statics are s_rDegradeDistance=50, max_framerate=20,
min_framerate=8, ideal_framerate=10, auto_update_deg_mul=1, manual bias
0, and initial deg_mul=0. The Config UI's authored defaults are separately
automatic=false, bias=0, distance=50; production follows the persisted UI
preference, not a capture's transient multiplier.
SceneTool::UpdateFPSCounter @0x0043E510 sums the prior 20 frame-duration
slots, publishes FPS as zero when the sum is not strictly greater than
0.000199999995f, otherwise publishes 20/sum, then shifts the history and
inserts the just-finished duration. Preserve this retail one-sample ordering,
the 20-slot warmup contents, and single-precision behavior.
Render::CalcDegLevel @0x0054CAF0 first shifts its 30-slot candidate history.
With automatic degrades off it stores the unchanged current automatic
multiplier and returns. With automatic degrades on it evaluates retail's exact
five-weight piecewise formula from current FPS and the 8/10/20 rates, adds the
current multiplier, clamps to [-1,+1], and calls
SetDegradeLevelInternal(candidate) only after all 30 prior history slots are
within the strict retail abs(slot-candidate) < 0.01 band; it finally stores
the resulting current multiplier. Port this body as one testable pure routine
from the named function and paired bytes. A proportional controller, moving
average substitute, time-based debounce, modern clamp, or reordered history
is not equivalent.
Render::SetDegradeLevelInternal @0x0054C3C0 also derives retail object,
particle, static-light, and dynamic-light budgets. S5-c3 changes only the
building consumer of deg_mul: TS-15, AP-116, and AP-85 already own the
surviving non-building LOD, particle-range, and light-pool differences and
must be amended in the same implementation commit to name that uncoupled
adaptive-budget fact. Do not perturb those already-landed policies here.
Finally, CBuildingObj::makeBuilding @0x006B53A0 calls
InitPartArrayObject(model, 1). That path accepts either a direct GfxObj or a
Setup, but DrawBuilding still uses only parts[0]. A Setup-backed building
therefore resolves the existing SetupMesh.Flatten/Resting placement part
zero and its transform; it never flattens every Setup part into the building
shell draw. The installed-DAT census below contains no Setup building, so this
branch is a synthetic structural pin, not an installed-population claim.
17.2 Installed-DAT population pin
The lead scanned the installed land/cell/portal DATs through the legal
DatCollection reader before this contract. Record and reproduce these exact
facts in an InstalledDat test or an existing InstalledDat census surface:
- 1,639 landblocks contain 6,979 building instances across 398 distinct models;
- all 6,979 installed building models are direct GfxObjs; zero are Setup or another type;
- all 6,979 resolve part-zero GfxObj data; none are missing;
- 6,760 instances have degrade ladders, containing 27,859 level slots across 350 distinct ladder models;
- every one of those 6,760 ladders has exactly one zero-id slot and it is the final slot; no nonzero slot is missing and all 21,099 nonzero slots have a drawing BSP;
- level-count histogram: 2→196, 3→216, 4→4,964, 5→1,341, 6→43;
- there are no duplicate building-anchor groups.
Thus the complete-body null-selected-Gfx path is real and widespread, while the non-null-Gfx/null-BSP path requires a synthetic pin even though its retail behavior is unambiguous. Do not “repair” the authored final zero slots, clamp to the last nonzero slot, or use BSP presence as a body-existence proxy.
17.3 One typed selection, one shared degrade owner
Replace BSP-only selection with one value that carries at least the selected
GfxObj id, nullable drawing BSP, degrade level, and degrade mode. The base
direct-Gfx path carries its own GfxObj id even with no ladder. Ladder entries
carry the authored GfxObj id and mode as well as min/ideal/max and the optional
BSP. A selected GfxObj id of zero is the exact complete-body failure. A
nonzero id with null BSP is an admitted complete body with no portal walk.
HasGeometry, the fixed DefaultDegradeMultiplier=0.99, and the erroneous
default distance 100 are deleted, not retained as fallback truths.
Create one renderer-lifetime degrade owner, passed/borrowed through normal composition: no static mutable global, service locator, duplicate UI mirror, or second ticker. It owns the 20 frame-time slots, 30 candidate slots, current automatic multiplier, exact rolling FPS, and the current persisted settings view. It advances exactly once per accepted graphical render callback using that callback's real delta; world replacement/portal travel does not recreate or double-tick it. Settings changes are observed on the next frame:
- automatic=false → building selection and the FPS panel's DEG field use the
persisted manual
GraphicsPerformancebias; - automatic=true → they use the exact current automatic multiplier;
- both modes use the persisted
DegradeDistance; - the FPS panel's FPS field borrows this same retail rolling-FPS value, not a second cadence, while its authored show/hide option remains unchanged.
The controller must define and pin initial/warmup behavior, zero and tiny deltas, NaN/infinity input, settings toggle transitions, and exact float ordering. It may fail closed or sanitize only where the retail x87 comparison would do so identically; any modern safety divergence must receive a register row in this same commit. No allocation is permitted after warmup.
17.4 Exact building body, portal, and selected-shell execution
At DrawBuilding entry retain the unconditional BLD transcript event and
portal-list publication. Then select part zero once and use that same immutable
selection for every downstream action:
- selected GfxObj id zero: return after entry publication; no alpha barrier, portal walk, look-in draw, or shell;
- selected id nonzero: emit the existing alpha barrier first;
- if the selection's BSP is non-null, run the existing pass-1/pass-2 portal walk through each active view; if null, emit no portal work but continue;
- submit the shell after the portal walk using exactly the selected GfxObj id.
Thread the typed selection through OnBuildingShellTurn and the production
world/populator/dispatcher seam. Do not mutate the retained
RenderProjectionRecord, rebuild retained topology, clone a record per frame,
or silently keep the base shell's MeshRefs. Classification must preserve
the retained building's scene/lifecycle identity, root transform, material/
surface overrides, detail state, effect/anchor membership, and picking facts,
while replacing the part-zero GfxObj with the selected one. Direct-Gfx models
use identity part transform. Setup models use exactly the precomputed part-zero
placement/default-scale transform, and portal projection, sort-center distance,
and shell submission must agree on the same composed part-zero frame.
The building path submits exactly one selected part-zero mesh. If its render mesh is not resident, request/load that selected id through the existing asynchronous mesh seam and draw no shell for that frame; never fall back to the base GfxObj, block on DAT access, or query DAT from the renderer. Retry on the following frame through existing residency behavior. Zero retained shell records during a streaming boundary remains an empty shell turn; multiple matching retained shell records for one committed building is a fail-loud ownership error. No new dictionary, cell scan, or linear model search may run per building per frame.
17.5 Config and deviation truth
Render_AutomaticDegrades, Render_GraphicsPerformance, and
Render_DegradeDistance become live rows and must no longer receive
storeOnly:true or cite AP-198. Update the exact Config dim-set test and all
comments/counts that pin it. AP-198 narrows from its current residual set by
those three rows; do not disturb the already-live landscape-radius and
building-detail controls. Keep AD-78's count and description mechanically
consistent with the actual controller test.
Narrow TS-15 explicitly to non-building parts. Amend AP-85 to say its fixed
one-list light cap is not driven by SetDegradeLevelInternal's multiplier,
and AP-116 to say the explicit Retail/Extended particle-range choice is not
the adaptive multiplier's object/particle distance budget. Those existing
rows cover every intentionally uncoupled SetDegradeLevelInternal consumer;
add no duplicate row. If implementation discovers another surviving
deviation, add or correct its row in the same commit. The active-row total
must change only if a row is actually added or retired; narrowing does not
change it.
17.6 Allowed scope and explicit nonchanges
Allowed production scope is the existing building walk/factory/registry,
frame-driver world-data/populator/dispatcher classification seam, the one
renderer/frame-root composition seam needed for the shared controller, the
FPS retained-UI binding, DisplaySettings comments, and the Config row
dimming flags. One focused App-layer controller file may be added. Tests may
change only for those surfaces, the exact retail math, installed census,
composition identity, residency retry, lifecycle, and allocation. The only
authorized documentation file in the implementation commit is
docs/architecture/retail-divergence-register.md.
Do not change portal admission, BSP traversal, alpha FIFO routing, material blend/state, particle update/range, point-light selection, terrain/shadow selection, streaming radii, generic entity/scenery/creature LOD, DAT reader, RHI/shaders, login/network/runtime gameplay, self-gate scripts, artifacts, or this packet/plan. Do not add a base-shell fallback. No graphical client is launched by the implementer.
17.7 Required automated proof, mutations, and return
Focused tests must prove at minimum:
- direct base Gfx and ladder selections carry exact id/BSP/level/mode;
- positive and negative multiplier arms, strict threshold equality, last slot, disable, forced-level clamp, scaled sort-center/CYpt, zero/negative/ NaN/infinity inputs match a literal independent retail oracle;
- the prior-20 FPS ordering and the complete 30-slot
CalcDegLevelformula, stability gate, clamp, manual arm, warmup, and settings transitions match fixed expected sequences—not implementation self-comparison; - zero selected Gfx emits BLD only; nonzero/null-BSP emits BLD → alpha barrier → selected shell with no portal events; nonzero/BSP preserves BLD → barrier → portal passes/look-ins → selected shell;
- a far selected LOD changes the submitted GfxObj id while all retained ownership, transform, surface/detail, effect-cell, picking, and ordering facts remain exact; no base fallback occurs while the selected mesh is unavailable, and the same selection appears after residency succeeds;
- a synthetic Setup building draws only transformed part zero and uses the identical composed transform for distance, portal clip, and shell;
- Config's three rows are live-colored, persist exact values, and the one composed controller instance is borrowed by both renderer and FPS panel;
- publish/retire/revisit/reset and first/login/portal/null-root frames neither duplicate nor recreate the controller and leave existing building lifecycle behavior intact;
- the installed census equals §17.2 exactly; and
- the warmed selection/controller/classification path allocates 0 managed bytes and does not advance retained topology or materialize records.
Sabotage and restore at least these exact mutations, recording each first
failing test/assertion in the implementation commit body: use BSP-null as the
complete-body gate; clamp the final zero slot to the prior nonzero slot; use
the base GfxObj for shell submission; change strict < to <=; feed the
manual bias while automatic is enabled; update FPS after inserting the current
sample; allow one stable history slot instead of all 30; fall back to base when
the selected mesh is unavailable; and recreate the shared owner for the FPS
binding. Include an allocation sabotage that constructs or clones per
building and prove the 0-B pin catches it.
Implementer return: git diff --check; Release solution build 0W/0E; focused
building/walk/driver/dispatcher/settings/UI/composition tests; exact math and
0-B lanes; official hermetic lane; inclusive InstalledDat lane with the
campaign's accepted exclusions and explicit documented global identities;
one clean commit; exact file/count/mutation report; no client run.
Sequential review 1 — retail/deviation fidelity: re-check every §17.1 byte/ named fact, the §17.2 census, selection math, FPS/auto controller, complete- body gate/order, Setup part zero, selected shell, Config/register truth, and all mutations. Sequential review 2 — architecture/production/gate honesty: one shared owner/tick, one typed selection, no retained mutation/base fallback/ renderer DAT read/topology rebuild, async residency, transform/material/ 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:
SceneTool::UpdateFPSCounter @0x0043E510sums the 20 stored single-precision frame durations in x87 precision and divides before narrowing once at the published FPS store. Accumulating into a C#floatis not equivalent. Use a wider accumulator that exactly sums the 20 binary32 inputs, perform the division wide, then narrow once tofloat. Restore retail's physical history direction: shift old slots0..18to1..19, then store the just-finished binary32 duration at slot 0. The prior-20-before-insert order remains unchanged.Render::CalcDegLevel @0x0054CAF0evaluates 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 qword0.01, not0.01f. Keep the existing shift-before-evaluate and final current-multiplier store order.GfxObjDegradeInfo::get_degrade @0x0051E4B0stores the effective distance afterabs(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 tofloatbefore 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] × 10publishes bits0x43A6AAAB(333.333344f), not the candidate's0x43A6AAAC; CalculateCandidate(14f, 0f)publishes bits0x3BB2BC0A, not0x3BB2BC0B;- with ideal/max
24f/48f, multiplier0.0020020019728690386f, and effective distance24.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. Each further code finding receives its own bounded contract; S5-c3 stops before an eleventh review pass. Documentation-only findings may be corrected directly by the lead.