docs(overhaul): contract issue 469 lighting ownership

This commit is contained in:
Erik 2026-09-05 03:29:21 +02:00
parent 2f1e625fea
commit 8098875240
3 changed files with 174 additions and 10 deletions

View file

@ -122,8 +122,8 @@ left no client. The separate #469 lighting-direction transition remains open.
## #469 — Atmospheric shadow-gate transition switches the whole outdoor lighting direction abruptly and can darken the world
**Status:** OPEN — found 2026-09-04 by the S5-c2 lead graphical gate; Campaign
OVERHAUL v2 renderer-solid/G4 scope. This predates S5-c2: exact parent
**Status:** IN FLIGHT — lead contract written 2026-09-05 in S5 packet §31;
Campaign OVERHAUL v2 renderer-solid/G4 scope. This predates S5-c2: exact parent
`5c106bcdf` and candidate `ef819eedf` reproduce the same dark re-enable.
**Evidence:** parent
@ -147,13 +147,12 @@ IA-24 records that this alignment was intentional, so the repair must preserve
the declared opt-in behavior or explicitly revise that deviation—not quietly
mix two incompatible directions.
**Bounded next step before G4:** write a focused pack-lighting contract that
keeps the pack-active receiver direction stable across shadow-work gate
transitions (or proves a better single-direction policy), pins meshes and
terrain together, preserves exact pack-off pixels/work, recompiles and verifies
the shader manifest, then repeats this exact off/on/dusk A/B. G4 cannot call the
renderer solid while this remains unexplained and visibly severe; alternatively
the owner may explicitly accept the transition as part of IA-24.
**Bounded repair before G4:** packet §31 restores retail's authored `uLights`
direction as the sole base-light direction in both atmospheric vertex
receivers, while preserving the selected celestial direction for the opt-in
shadow/volumetric projection and correcting IA-24 in the same implementation
commit. Production SPIR-V plus a real Vulkan mesh/terrain witness must
discriminate the old branch before this exact off/on/dusk A/B is repeated.
## #468 — Teleport to the Holtburg cottage doorway pose seats the player in the house-interior cell at a point outside its floor; the player falls through the world

View file

@ -694,7 +694,7 @@ Update immediately when a slice changes state. Chat is not the ledger.
| S5-c3 | **LANDED + REVIEW-CLOSED 2026-09-04** at `c673f767e` (reviewed scratch `01e5a15d0`; packet §§1721). | **C3 SCOPE SELF-GATE PROVISIONAL PASS; whole-renderer finding #470 OPEN. G4 UNPASSED.** | OpenAI retail pass 3/10 PASS and production narrow re-review pass 5/10 PASS. Fix round 3 added ordinary landblock-lifetime ownership for every unique nonzero ladder GfxObj, rearmed walk-frame miss requests, and made the one-tick-before-BeginFrame proof discriminating. Fresh clean campaign: Release 0W/0E; focused 101/101; hermetic 16,811/16,811; InstalledDat 469 pass / the unchanged documented 10 fail / 1 skip; manifests 30/30. Self-gate `logs/selfgate-20260904-223345-s5c3-building-degrade` produced five PNGs, exited 0/gracefully, and left no client. The selected building shells are complete; the Holtburg frame also exposed pre-existing atmospheric ordered-draw sidecar defect #470, which is not a c3 regression and blocks renderer-solid/G4 until repaired. |
| S5-c4 | **LANDED + REVIEW-CLOSED 2026-09-05; LEAD GRAPHICAL GATE PROVISIONAL PASS.** Campaign stack `75664805f` -> `15ed57a1e` -> `d5cfd1c91` -> `03a108ffa`; reviewed scratch tip `db8136448`; packet §§2226. | G4 UNPASSED | Retail/material pass 3/10 PASS. Full production pass 4/10 found one classic/private detail-off regression; fix round 3 restored the prior AlphaBlend/coalescing path, and narrow production pass 5/10 PASS reproduced all three mutations. Fresh campaign Release 0W/0E, App 245/245, Content 71/71; scratch hermetic 16,971/16,971 and InstalledDat 469/10/1 with both manifests 32/32. Full recipe-10 bake: 2,237,865 keys, zero failures, SHA `4E0FA6C5…29B59B`. Gate `logs/selfgate-20260905-020703-s5c4-onepass-detail`: 13/13 PNGs, exit 0, graceful, no client left; visual PASS provisional. #471 DONE; #470 narrowed to local-sidecar indexing. |
| S5-#470 | **LANDED + REVIEW-CLOSED 2026-09-05; LEAD GRAPHICAL A/B PROVISIONAL PASS.** Campaign implementation stack `15a796c3a` -> `7506e5f14` -> `b333edb4f`; route `19b44e5e3`; reviewed scratch `51f974da4` -> `2cad9c84` -> `98c004aa7`; packet §§2730. | G4 UNPASSED | Retail/behavior pass 2/10 and production pass 4/10 closed the two evidence-only findings. Fresh campaign Release 0W/0E and focused 48/48; exact scratch hermetic 16,976/16,976 and canonical InstalledDat 386/10/1, manifests 30/30. Pinned gate `logs/selfgate-20260905-032132-s5-470-pinned-shadow-ab-r1`: retail/off -> High -> retail/off, 3/3 PNGs, exit 0, graceful, no client; visual PASS provisional. The stale recipe-8 pre-route launch is excluded and recorded in §30. |
| S5 | IN FLIGHT — c1c4 plus #470 landed/review-closed/provisionally self-gated; #469, c5, closeout, and G4 remain | G4 | Packet §§7 and 1230 are binding. Next: bound, implement, review, and graphically gate #469's lighting-direction repair; then c5 cleanup, closeout, and G4. Never merge main before G4. |
| S5 | IN FLIGHT — c1c4 plus #470 landed/review-closed/provisionally self-gated; #469 contract written; c5, closeout, and G4 remain | G4 | Packet §§7 and 1231 are binding. Next: implement, sequentially review, land, and graphically gate §31's #469 authored-light repair; then c5 cleanup, closeout, and G4. Never merge main before G4. |
---

View file

@ -2687,3 +2687,168 @@ frame. High retains the separately registered #469 lighting-direction shift;
that known blocker is neither waived nor attributed to #470. #470 changes no
retail-visible policy and requires no divergence-register row. Next is #469,
then S5-c5, closeout, and G4. Nothing has merged to `main`.
## 31. S5-#469 contract — keep retail world lighting stable across the opt-in shadow gate
### 31.1 Lead-recovered retail and binary boundary
Issue #469 is not an ambiguous art-direction choice. Retail owns exactly one
outdoor directional-light channel, authored by `SkyTimeOfDay`; the atmospheric
pack's visible sun/moon choice is an acdream-only shadow-projection input and
must not replace that lighting channel.
The lead re-read the named retail decomp and its verbatim type header before
writing this contract:
- `SkyTimeOfDay` contains `dir_bright`, `dir_heading`, `dir_pitch`, and
`dir_color` (`acclient.h` lines 5312453137).
- `SkyDesc::GetLighting @0x00500A80` interpolates those fields between the two
surrounding authored time-of-day records, constructs one directional vector,
and returns one directional colour.
- `LScape::set_landscape_lighting @0x005054D0` copies that vector and colour to
`LScape::sunlight` and then `Render::world_lights.sunlight`; it has no shadow-
gate or celestial-mesh selection input.
- `PrimD3DRender::UpdateLightsInternal @0x0059AED0`, specifically
`0x0059B4ED0x0059B5CE`, derives the D3D sunlight colour and direction from
that same `Render::world_lights.sunlight`. It does not replace the direction
when any drawing feature is enabled or disabled.
The paired executable was independently verified again with
`tools/pdb-extract/check_exe_pdb.py`: `C:\Users\erikn\Downloads\acclient.exe`
is PE32 v11.4186, whole-file SHA-256
`006FFEADC5D679C871497112A5BD1F87714D0E273E2166BAE5052DDE369297B1`, CodeView
GUID `{9E847E2F-777C-4BD9-886C-22256BB87F32}`, age 1, and matches
`C:\Users\erikn\source\repos\acdream\refs\acclient.pdb`. Exact function-range
SHA-256 anchors are:
| Function | File range | Bytes | SHA-256 |
|---|---:|---:|---|
| `SkyDesc::GetLighting` | `0x00100A80..0x00100CDF` | 608 | `9D82E8EDDBD66C52DBD3F08D07D661482DB545C4F513E81AB4F16E4EDF410188` |
| `LScape::set_landscape_lighting` | `0x001054D0..0x0010565F` | 400 | `DF3FD816845AE0F6E2423442A325CE43A44A8204E1B857D7674BBB8F4640D0CB` |
| `PrimD3DRender::UpdateLightsInternal` | `0x0019AED0..0x0019B5DF` | 1,808 | `E18FD7AD9A8EB819AB9602D25DE5D1BB99FADD1D439B35140E443EB1E0437F84` |
This agrees with the pre-existing static source study
`docs/research/2026-08-22-dereth-celestial-shadow-sources.md`: celestial meshes
supply only the opt-in shadow **direction**; colour and energy remain retail's
single authored channel; existing retail scene lighting remains driven by
`SkyStateProvider`.
The current atmospheric receiver shaders violate that declared boundary.
When shadow flag bit 0 is clear they use the plain pipeline's authored
`-uLights[].dirAndRange.xyz`; when it is set they abruptly use normalized
`uShadowLightDirectionAndSource.xyz`. Shadow strength is blended later, so this
binary vertex-light switch produces the whole-world relight captured in both
the exact parent and S5-c2 candidate A/Bs. It is not absent shadow work and it
is not caused by S5-c2.
### 31.2 Bounded production repair and IA-24 correction
Restore one stable lighting owner in both atmospheric vertex receivers:
1. `mesh_atmospheric.vert` computes every outdoor directional-light `Ldir`
with the exact plain-mesh expression `-uLights[i].dirAndRange.xyz` in every
shadow-gate state. Preserve its unnormalized value and its per-light loop.
2. `terrain_atmospheric.vert` computes `surfaceToLight` with the exact plain-
terrain expression `-uLights[0].dirAndRange.xyz` in every shadow-gate state.
Preserve `MIN_FACTOR`, authored colour/energy, and the split directional
varying used by the fragment receiver.
3. Delete the obsolete `shadowGatedOff` branches and replace their comments
with the retail ownership above.
4. Keep `uShadowLightDirectionAndSource` unchanged for cascade projection,
receiver depth/bias/PCF, and atmospheric volumetrics. The optional shadows
may therefore be geometrically directed at the selected visible celestial
source while the receiver's base lighting remains the authored retail
direction. That separation is deliberate and was already the original
IA-24 research boundary.
5. Recompile the committed shader set and update only the generated atmospheric
vertex SPIR-V and manifest/hash entries required by those source changes.
6. Amend IA-24 in the **same implementation commit**: remove its statement that
receiver lighting switches to the celestial direction while shadows render;
state instead that authored `uLights` remains the sole base-light direction
in every gate state, while the selected celestial source drives only the
opt-in shadow/volumetric projection. Explicitly record the possible visual
light/shadow-angle separation as the cost of preserving retail lighting and
eliminating the binary relight. This is the required deviation-register
update; add no second row.
Do not change `SceneLighting`, `SkyStateProvider`, the celestial-source
resolver or its sun/moon priority, shadow strength/fades, cascade matrices,
shadow caster selection, receiver binding/descriptor ABI, fragment shadow
lookup, PCF/bias, volumetric policy, render-pack selection, plain shaders,
materials, fog, tone mapping, colour/energy, terrain `MIN_FACTOR`, indoor
lighting, point/spot lights, visibility, geometry, package recipe, or any
unrelated renderer. Do not normalize the authored direction, blend the two
directions, invent another runtime state owner, hide the switch behind a
threshold, or add per-frame work/allocation. If any wider production change is
needed, stop and return the exact dependency before expanding scope.
Allowed production scope is the two atmospheric vertex shader sources, their
regenerated SPIR-V/manifest pins, and the IA-24 row. Tests may add only the
smallest structural and real-shader proof below. The implementer changes no
packet, plan, issue, package, gate artifact, architecture text outside IA-24,
or campaign memory.
### 31.3 Discriminating proof, mutations, and return
Permanent proof must establish both halves of the boundary rather than merely
matching a copied CPU formula:
1. compile and inspect the committed production atmospheric vertex SPIR-V and
prove mesh and terrain take their diffuse-light direction only from the
corresponding authored `uLights` member, with the exact unnormalized plain-
shader expressions and no shadow-flag/celestial-direction selection;
2. exercise the committed production atmospheric receiver shaders in a real
offscreen Vulkan pixel witness for both mesh and terrain. Holding authored
light/material/geometry constant while toggling only shadow flag and
celestial direction must leave the unshadowed base directional-light result
invariant; choose inputs for which the pre-fix branch gives a different
pixel. The witness is explicitly `Lane=Vulkan`, uses the existing dedicated
lavapipe/local lane, and fails rather than skips when that lane lacks Vulkan;
3. prove the committed fragment receiver and volumetric shaders still consume
`uShadowLightDirectionAndSource` for opt-in shadow projection/bias/visibility,
so the repair cannot silently disable or redirect shadows;
4. prove active and inactive receiver states still select/bind the same
atmospheric/plain pipelines and descriptors as before;
5. pin that neither plain shader source/SPIR-V nor any pipeline-selection or
renderer source changed from the contract parent; and
6. read the live IA-24 row and fail if it again claims celestial direction owns
base receiver lighting or omits the explicit light/shadow separation.
Apply and independently restore at least these mutations, recording the first
discriminating failure for each in the implementation commit body:
1. restore the shadow-flag/celestial-direction branch in
`mesh_atmospheric.vert`;
2. restore it in `terrain_atmospheric.vert`;
3. normalize either authored vertex-light direction;
4. redirect a fragment shadow/volumetric use from the celestial source to the
authored light, or remove its celestial-source read; and
5. restore IA-24's old assertion that pack-active base lighting follows the
celestial source.
Return one clean implementation commit atop this contract; exact changed-file
and line counts; all mutation first failures; both `git diff --check` forms;
exact shader compiler command and generated hashes; the dedicated physical
`Lane=Vulkan` result; focused atmospheric shader/receiver/manifest/source-
resolver tests; Release solution build with zero warnings/errors; official
hermetic lane; and canonical-inclusive InstalledDat with every accepted
nonpassing identity named. Recipe 10 and prepared content are unchanged, so no
bake is required. No graphical client launch.
Review is sequential. Retail/deviation pass 1/10 first verifies the three
named-retail functions and paired bytes, the stable authored-light rule, IA-24
truth, pack-off preservation, and that the pixel/structural tests actually fail
on both old branches. Only after PASS does production/gate-honesty pass 2/10
inspect the complete source-to-SPIR-V-to-pipeline path, run the real Vulkan
witness, reproduce at least mutations 14, and rule on portable/dedicated-lane
ownership and full gate sufficiency. A failed pass receives one bounded fix
contract. The owner-authorized ceiling is ten review passes. Nothing lands or
launches graphically before both lenses pass.
After landing, the lead repeats the exact fixed-pose retail/off -> High ->
retail/off plus dusk transition used to file #469, with Release green, a clean
tree, UDP/client preflight, one background command, and graceful self-owned
shutdown. PASS requires no whole-world base-light jump as shadow work gates,
while pack-active shadow direction/visibility still changes and the final
retail frame restores. Record exact PNG paths; the result remains provisional
until owner inspection.