Skip to content

feat(vq07): bounded depth-correct volumetric fog - #399

Closed
jonit-dev wants to merge 54 commits into
developfrom
feat/vq07-volumetric-fog
Closed

jonit-dev wants to merge 54 commits into
developfrom
feat/vq07-volumetric-fog

Conversation

@jonit-dev

@jonit-dev jonit-dev commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Bounded, depth-correct volumetric fog now ships as generated starter source in src/render/, with opt-in density, colour, overlapping bounds, height falloff, resolution and step controls. The default stays off. Directional shadows and an explicitly unshadowed finite-range point-light subset contribute independently of extinction. Scene depth occludes the medium; inactive, unsupported and zero-density paths allocate no fog targets. Owned targets/materials and scene-fog suppression are released through the existing graph lifecycle.

PRD-VQ-07 is complete and archived: six phase boxes and two acceptance criteria verified; label prd:100% — ready.

Validation at e87faa6f9669e85742db659a08a15ec5a8cd8ea5:

  • Full CI 37151307501 succeeded, including ci-required and native platform checks. Rain's initial adapter/device-loss failure passed on its exact-job retry.
  • Browser fog qualification: 29 arms, 392 in-arm and 13 cross-arm assertions; zero failures or console/network/runtime diagnostics. Artifact 11283674657, SHA256 dc6c332a…; Chromium WebGPU/SwiftShader, 640×400 screenshots.
  • Linux ARM64 native fog: 29 arms, 419 in-arm and 13 cross-arm assertions, 29 nonblank gates; zero failures. Both no-fog resize controls passed with zero fog targets. The lane rebuilt the host and executed compiled acquisition-status and actual GPU destination-pixel tests. Artifact 11285180012, SHA256 5a9d03ff…; llvmpipe, runtime 5a164cc2…, bundle b76f3417….
  • Zero density restores identical off pixels; resize, camera cuts, streamed occluders and repeated scene transitions match fresh references and restore the texture baseline. Overlap clears unchanged thresholds at 0.09386 changed channels / maximum delta43 against 0.05 /4. All artifact summaries and attempts identify this exact source.

Nonblocking integration failure: fluid consumers failed three executions with screenshot stability timeout, advance timeout, then SwiftShader device loss/blank capture and a failed maxSpeed observation (latest artifact 11285747559). No more retries or threshold changes were made. Independent review confirmed this PR changes no fluid simulation or capture-harness code; its output-graph APIs are unused by that browser fixture. The integration run therefore ends failed although both fog jobs passed. This is outside VQ-07's scope; branch rules require the passing ci-required check. No protection or required check is bypassed.

Qualification is software correctness only. GPU means retain sparse query coverage (browser4/30 answered, native4/30,4/30,3/30). No phone/hardware performance, default-tier admission, OS-window lifecycle or wider local-shadow claim is made.

Protected merge queue status

The PR remains unmerged. Merge-group CI 37156742265, attempt 2 passed RTS on its bounded retry, but required rain still failed: rain-simulation-advances observed zero frames because the WebGPU adapter request resolved null (TN_PLAYTEST_CAPTURE_PROVENANCE_MISSING). Its preceding scenarios passed assertions with software-device-loss warnings. ci-required correctly failed. No source, assertions, provenance requirements, timeouts, or branch protections were changed. Further blind retries stopped after the repeated adapter failure; queue runner WebGPU availability remains unresolved.

Rain software-quality correction at edd5e1d6eef2ef306234a615d6f392861b2ee0f8

Rain previously chose the software-safe built-in post chain but its UI still selected the expensive high study on wide windows. Scene loading now chooses the existing performance study before the first software-rendered frame; URL and player choices remain explicit overrides, and hardware retains its existing 700px window policy. The four-tier scenario explicitly chooses high through its existing quality menu, with every original assertion, transition and screenshot retained.

Validation: 87 focused tests, scoped scaffolder TypeScript, all 66 scaffold contracts and the normal pre-push lint/docs/agent/drift checks passed. Independent review found no blockers. A generated byte comparison reproduces both Rain scaffold hashes: exactly the four reviewed template files changed, with 108 files unchanged; every other template pin and the hash guard remain intact.

Matched local simulation runs on real SwiftShader passed the original 120-tick assertions on both baseline and candidate, with empty diagnostics. The candidate retained performance/32 cloud steps rather than baseline high/64. The corrected four-tier gate passed all eight original assertion results and retained six screenshots, with empty diagnostics; the labeled requested-high state observed high/64 steps before the original high checkpoint, followed by balanced/48, performance/32 and ultra/88. The initial unsupported resource-setup experiment failed before assertions because the engine state provider is read-only; its failure evidence was retained and that setup removed.

These runs establish the bounded quality-policy fix, but the healthy baseline does not establish the cause or resolution of the queue's adapter-null/device-loss failures. Fresh CI 37169021789 and integration 37169021686 are pending on this exact head. No blind retry, workflow/routing/runner change, merge or protection bypass was performed.

The fog implementation, qualification fixtures and completed VQ-07 PRD are byte-identical to e87faa6f in this correction. The fog acceptance evidence above remains tied to that original head; it is not presented as a fresh run on the new head. New-head fog and other selected integration checks remain subject to current CI.

Copy link
Copy Markdown
Contributor Author

Actual runtime screenshot progress: off baseline only

VQ07 off baseline: foreground wall, roof opening and lit room

  • Rendered source: 1bb878e033d29e084b912bc9266a15b72d6cbf16
  • Hosted run 36989192897, Chromium WebGPU, Google SwiftShader, 640 × 400
  • PNG bytes are unchanged and verified: SHA-256 fa3486dd2033281d2ec1db552cf46fba7971f4fbe0ab1cea731a5092e55a5935
  • Durable provenance

This is diagnostic baseline progress, not fog qualification. The run failed closed on one HTTP404 console error; fog-on variants did not execute. The image/component assertions passed, with no device-loss or runtime diagnostic. A fixture-only HTTP error log is now identifying the exact failed URL without suppressing the error. Native proof, fog-on review and hardware performance remain pending.

Copy link
Copy Markdown
Contributor Author

Actual fog-on runtime progress

Off baseline:

Off baseline

Bounded fog enabled:

Bounded fog enabled

Camera inside the volume:

Camera inside the fog volume

All nine unchanged captures and provenance · successful run 36990624761

Rendered source 4f8fe47b1801282827c9b5d0f0cba40b99c7c2a7, Chromium WebGPU / Google SwiftShader, 640 × 400. All nine variants passed with no diagnostics; off and zero-density pixels are identical. The foreground wall-center reference patch has zero changed pixels versus off. Full/half-resolution images differ by mean 0.0695/255. PNG bytes are unmodified and their checksums are recorded in the provenance file.

Still incomplete: the ownership receipt review finding, stronger isolated scattering/light checks, resize/repeated lifecycle qualification, native execution and hardware performance. Light toggles also change surface illumination, so their whole-frame differences are not yet an isolated volumetric-light measurement. These are actual software-rendered progress screenshots, not a merge-ready claim.

@jonit-dev jonit-dev added the prd:25% PRD phase 1 verified label Oct 2, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Contributor Author

Receipt-head runtime revalidation passed at 9b2bcd7a1e9db2aa181a34c2c7fd5a060724138a: run 36994760252, Google SwiftShader WebGPU, 640×400, all nine variants, empty diagnostics and exact zero-density identity. Every PNG is byte-identical to the previously attached captures; durable revalidation provenance records the exact source and artifact hash.

Actual fog after the receipt correction, unchanged PNG bytes

This is software-rendered correctness progress. The current head adds stricter black-surface scattering controls and actual repeated teardown/return-to-off scenarios; that new run is pending. Native, resize and performance qualification remain open. Root typecheck/lint pass; full test invocation is blocked before its phases by this executor's tsx Unix-socket EPERM.

Copy link
Copy Markdown
Contributor Author

Actual isolated-scattering progress at source 001b934008cbc6e3ab196678506ae9b14f751f1e, run 36997361343, Google SwiftShader WebGPU, 640×400. The four controls pass ordinary capture/runtime guards with empty diagnostics. Black unlit surfaces remove surface-lighting changes from this comparison; the calibration card lies outside the measured fog area.

Both fog lights:
Actual isolated fog scattering

Point light off, leaving directional scattering:
Actual directional scattering control

All four unchanged PNGs and provenance. Pinned ROI mean RGB deltas are 15.96/255 for the directional source and 48.78/255 for the point source. Black evaluation area and foreground-plate patch are exactly zero; calibration pixels match exactly across controls.

The overall run failed on a separate lifecycle setup-count mismatch, preserved in provenance. The new head now explicitly exercises four real fog targets with exact create/release/live assertions; that rerun is pending. These images establish software-rendered scattering progress, not completed lifecycle, native or performance qualification.

@jonit-dev jonit-dev added the prd:75% PRD phases in, acceptance open label Oct 2, 2026 — with ChatGPT Codex Connector
@jonit-dev jonit-dev removed the prd:25% PRD phase 1 verified label Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Actual browser target/depth resize and resource-accounting proof passed: run 37000862324, source 1505e018aa38630b91893ab8265c447833e99a51, Google SwiftShader WebGPU. All 17 cases pass with empty diagnostics. One fog controller/target follows 320×240 then 640×400, and restored pixels equal the original fog image. After teardown, renderer texture count returns to the independent off baseline of 5 after three observed stable render intervals.

Small render target (browser CSS capture remains 640×400):
Actual resized fog target

Restored target:
Actual restored fog target

Exact provenance, observations and limited workload/cost record. These are browser software correctness captures, not OS-window lifecycle or hardware-performance proof. Current head adds the independently reviewed native host route and measured render boundaries after every lifecycle transition; native execution remains pending.

Copy link
Copy Markdown
Contributor Author

Native screenshot progress: rendering and teardown pass; resize remains failing

Actual Linux ARM64 native host captures at source 1f73e559c7a8fa01740cc2b5b24ebec8dfc2f4e7, run 37005493900, Mesa llvmpipe WebGPU / 640×400 / device.screenshot. Software-rendered correctness only.

Fifteen pre-resize arms passed strict per-arm console/readiness/adapter guards, including inside/outside fog and actual four-target create/release cycles. Decoded actual PNGs also pass the pinned zero-density, restored-off and isolated-scattering metrics after artifact download; this recomputation is recorded separately because the hosted script stopped before its final metric phase. Final off returns to five renderer textures and zero live fog targets.

Actual native fog, resize qualification incomplete

Actual native isolated scattering control, resize qualification incomplete

The native run failed at resizeSmall: its report records TN_PLAYTEST_HOST_EXITED, wgpuSurfaceGetCurrentTexture validation “Surface image is already acquired”, then SIGABRT. No resize PNG or console file exists; the verifier's subsequent ENOENT is secondary and is not a pass. Native resize/restore and full acceptance remain open. The same source's browser gate passed all 17 cases.

Unmodified PNGs, host/bundle hashes, adapter, all accepted arms, pixel metrics and failure provenance. Draft retained; no default tier or hardware-performance claim.

jonit-dev and others added 15 commits October 3, 2026 09:19
…ad source

The starter shipped src/render/volumetricFog.ts and nothing called it, which
two template contracts reject: every module under src/render must be imported
by the game, and every exported render symbol must be called. Play.ts now
passes a per-graph `fog` factory to setupPost, which forwards the medium to
WorldEnvironment's existing baseColour hook and releases the previous one
before a tier change replaces the chain. MIST is off, so createVolumetricFog
returns before it allocates and the shipped picture is unchanged.

Also register the two temp-dir creators the guard rejected — both remove their
scratch root in a finally — and drop five retained fog PNGs that are
byte-identical to copies the authoritative 640c103 proof still carries.
…s, and let it own the air

Four reviewer findings on the fog source, plus the two red invariants the review surfaced
alongside them.

The authored mist was a `MIST` block in `src/scenes/Play.ts`, which puts a look decision in a
scene. It is now `STARTER_MIST` in `src/render/volumetricFog.ts`, and `Play.ts` only hands it the
live `ctx.renderer.kind` — the old block hardcoded "webgpu" while `threenative.config.ts` asks
for `preferWebGPU`, so the WebGL fallback would have built a medium the chain then silently
dropped. `STARTER_MIST` is typed `Omit<IVolumetricFogOptions, "renderer">`, so no scene can claim
a backend the renderer does not have.

It also declared `environment.sceneFog: false` while `sky.ts` installs the scene's `FogExp2`, and
the medium's own guard refuses to compose over a `scene.fog`. Turning the advertised single flag
on would therefore have thrown. `createVolumetricFog` now takes the scene, takes its fog over for
its own lifetime and restores it on disposal: one flag is enough, the air is never counted twice,
and disabled stays allocation-free and side-effect-free. `environment.sceneFog` is deleted rather
than left as a field that can only be false. There is no automatic sun — the generated source and
the template instructions now say the mist is lit by `ambient` until a `sun` with an initialized
shadow map is passed.

`verify-volumetric-fog.spec.ts` uses `test-support/temp-dir.ts` again, so its temp-dir-guard
allowlist entry is gone instead of justified. The `fog` lane in `integration.yml` gained the paths
this repair touches, so fog qualification reruns when the shipped wiring changes; develop's lanes
and the single job/stage pair are untouched.

Red-green first: the scene-fog take-over test failed against a medium that only restored the fog
on dispose, and the two new source regressions failed against the pre-repair files. Fog and fixture
suites pass 30/30, temp-dir-guard with the verifier 15/15, scaffold plus template contracts 104/104,
root and package typecheck pass, the doc-link/budget/CI-structure/CI-needs/mirror selection 230/230,
and `pnpm lint` exits 0 with 1042 warnings.

Two gates the review did not name were failing and are fixed here. `docs/verification` measured
72.7 MB against its 72 MB cap — the previous commit claimed 71.9 MB without measuring it — so the
retained images are now the two authoritative fog frames plus the 2.5 KB black control, every
`provenance.json` stays with its per-arm SHA256, and the six checkpoint paragraphs that linked a
deleted image name the run, artifact id and digest instead; `pnpm budgets` now reports ok at a
measured 71.9 MB. And the starter's CLAUDE.md mirror had crossed the 100-line scaffold limit, so
the fog instruction is merged into the existing `setupPost` paragraph.

Fresh hosted browser and native fog qualification plus the full repository CI are still required
before any box moves; the 640c103 proof stays source-scoped to its own tree.
The fog lane used (?:...) non-capturing groups, which grep -E does not
support, so the lane never matched and the integration fog job stayed
false. Plain groups keep the same alternation under POSIX ERE.
…mist

Disposal restored the captured scene.fog unconditionally, so a fog the game
authored while the medium lived was silently clobbered on scene teardown. The
medium owns the slot only while it holds it: restore the captured fog when
scene.fog is still null, and leave a later authored fog as the live one.

Red: the new case failed with the unconditional restore (expected the later
FogExp2, got the captured one).
…it exposed

The sweep ran every browser arm green on an nvidia/turing adapter at the
pre-repair source c364558, with the cost arms separating transport pixels,
ray steps and host frame distributions and refusing any hardware claim. It is
recorded as source-scoped evidence, not as qualification of the current head:
the standalone fixture imports the fog source this branch just changed.
The strict supersession detector reads the calibration card's visible=false as
the pattern prewarm replaces. Keeping it visible at zero opacity is not an
option here: the lifecycle and cost arms assert renderer draw and texture
counts, so an always-submitted card would move the baseline they read. The
card is a hidden reference the scattering controls alone reveal, which is what
the annotation now says.
…e source

The branch's native presentation and status-test additions moved the source
digest, so the budgets gate failed closed against a record last measured on
develop. Re-measured through native:coverage on the downloaded dependency
tree: 44 declared contract targets instead of 42, and TOTAL line coverage
78.77% from 78.72%. No floor, threshold or cap moved.
The half arm never asserted the resolution it asked for, the summary recorded
hardcoded transport pixels and ray steps, the overlap arm proved only an authored
flag, and shadowOutside echoed the mode name rather than the light's actual
shadow-map coverage.

The wall question needed no new proof: fogLightPixelMetrics already requires the
wall patch to be exactly black in all four scattering arms while the same arms
show a real scattering response, which is depth-correct occlusion with the same
camera and lights.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…itted ratio

The first overlap gate used a channel-ratio floor picked above the real measurement
and failed the actual 29-arm run. Replace it with two independent physical floors —
a channel delta above 8-bit dithering and a positive signed mean, because added
extinction can only brighten — so a darker or noisier overlap frame cannot pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The overlap gate goes back to the values it was first pinned at — five
percent of channels changed by more than two levels, and a four-level
maximum channel delta, both absolute differences. The signed-mean clause
added in b339f89 is dropped: added extinction adds in-scattering along
the ray, and a generally lit composite is not obliged to get brighter.

The fixture's control was the defect, not the bar. The second bound sat
where the wall, the pillar and the ceiling beams hid it, and fell off
faster in height than the primary bound, so the measured effect was
0.03733 changed channels against a 0.05 floor. It is now pinned to the
room's whole lit interior, Box3(-4.2, 0, -9.2)..(4.2, 3, 2.6) at density
0.28, baseHeight 0.5 and heightFalloff 0.32 — nested inside the unchanged
primary bound, chosen and recorded before the capture. Two real browser
WebGPU arms measure 0.09383 changed channels and a maximum delta of 43.
The synthetic guard still fails identical frames and a nine-level delta
on one of two pixels.

fogInsideShadowMap sampled the volume's eight corners, which is false
`false`: a bounding volume can enclose the whole shadow box with no
corner of itself inside it. It projects the volume by the shadow
camera's own view-projection and intersects the conservative
clip-space AABB, reading the depth range from camera.coordinateSystem
because Three syncs the shadow camera to the frame camera's convention
(0..1 on WebGPU, -1..1 on WebGL). The new 40 cm map inside the room,
with no room corner inside the map, failed first and passes after; the
same map translated clear stays outside.

fogFrameCost reported gpuMs beside a thirty-frame window, reading as a
thirty-sample mean. The retained costFull console answers 4 of 30 with
26 stale, so the summary now carries gpuSamples and gpuStaleFrames and
names the coverage in its own qualification. No threshold moved and no
performance claim follows.
All 29 browser arms pass with zero diagnostics on the committed source
carrying both repairs. Phase 3's native box, both acceptance criteria
and every promotion claim stay open: the native audit still covers
a6a155e.
fogFrameCost read gpu.samples/gpuStale through Number(), so a malformed or
negative count reached the summary as NaN or a negative frame count, and a
gpuMs with no gpu block read as a mean over an invented zero frames.
parsePerformanceMarkers validates hitch and projection payloads only and
pushes budget windows unvalidated, so the check belongs in the verifier.
Both counts must be nonnegative integers within the measured window, and a
window reporting gpuMs must carry a positive sample count; a window with no
GPU query stays an explicit zero and unmeasured. Input validation only: no
threshold, rendering path or fixture moved.
Rename the generated FogMedium type alias and its imports; no runtime bindings change. Refresh only starter's measured scaffold digest. Root typecheck and lint pass, and the scaffold/fog selection passes all 90 tests.
All six phase items and both acceptance criteria are now verified at the
exact head b93944e, so the file moves to
docs/PRDs/done/ while its sibling batch PRDs stay active.

Evidence is recomputed from this run's downloaded artifacts, not carried
over from 640c103: hosted integration run 37147171365 passes 29 browser
WebGPU/SwiftShader arms (392 in-arm + 13 cross-arm assertions) and 29 Linux
ARM64 QuickJS/wgpu-native/Mesa llvmpipe arms (419 in-arm + 13 cross-arm + 29
authored 5% nonblank results), plus both no-fog resize controls, the compiled
acquisition status contract and the actual GPU destination-pixel test. Full CI
run 37147171521 is SUCCESS with 72 selected checks green and ci-required
passing.

Only starter's generated-tree digest moved, to d51d898f, for the type-only
IFogMedium -> FogMedium rename. No threshold, fixture, scenario or rendered
path changed, and no gate was weakened. The two inbound links that the move
broke are repointed; historical checkpoints stay as written.
@jonit-dev jonit-dev added prd:100% — ready PRD complete, ready to merge and removed prd:75% PRD phases in, acceptance open labels Oct 3, 2026
…ic-fog

Reconcile the merge GitHub reported as CONFLICTING/DIRTY before promotion.

Sole conflict is .github/workflows/integration.yml, where this branch's
fog/fog-native jobs and develop's new world-capture job were inserted at the
same point. Resolution keeps both sides verbatim: upstream's streaming,
virtual-shadow, resolution-scaler and world-capture world is untouched, and
both fog jobs, their path filter and their retained artifacts are unchanged.

The PRD's promotion line now says runtime qualified at b93944e and archive
commit b655f43, instead of claiming the archive happened at b93944e.

No fog source, shader, threshold, fixture, scenario or scaffold digest moved:
scaffold/fixture/verifier/native-proof specs pass 122/122 and CI
structure/needs/temp-dir-guard/primary-docs pass 214/214 on the combined tree,
with root typecheck, lint, budgets and check:docs green.
…ation

Appends the reconciliation evidence for merge 8431684 to the archived
PRD, after the run that produced it: the single integration.yml conflict and
its both-sides-kept resolution, the unchanged lockfile and scaffold digests,
the green local gates on the combined tree, and a fresh 29-arm browser WebGPU
requalification at 8431684 (nvidia/turing, private Xvfb 1600x900,
summary.json ac608e32, zero==off byte-identical, overlap 0.093828125 / 43).

Linux native is explicitly not carried forward from b93944e: only the
hosted fog-native lane can qualify it at this head, so the earlier native
proof stays source-scoped and the exclusions are unchanged. No box was moved
and no threshold relaxed; prd:progress still prints prd:100% — ready.
…ic-fog

Develop advanced again while the first reconciliation was in flight: 2c005f9
(#418) replaces the per-lane gh api + grep selection in the integration paths
job with scripts/ci-integration-scope.mjs, which is strictly fail-closed. A PR
that conflicts gets no pull_request run at all, so this merge is what lets the
fog lane execute again.

Sole conflict is the same file's lane-selection block. Resolution keeps
upstream's selector verbatim and registers this branch's fog lane in the new
TN_LANE_FILTERS inventory, because the script refuses to start when a paths
output has no filter or a filter has no root job. The fog pattern is the old
lane filter with the trailing integration\.yml clause dropped: upstream now
selects a lane for workflow edits by comparing each job and filter instead, and
the fog job plus fog-native dependency are unchanged.

This is a selection-mechanism port, not a gate change: the fog regex still
names exactly the files the lane's steps execute, and ci-integration-scope,
ci-structure, ci-needs and ci-template-selection pass 256/256 on the combined
tree. No fog source, shader, threshold, fixture, scenario or scaffold digest
moved.
…ualification

Appends the 2c005f9 reconciliation to the archived PRD after the run that
produced it: why a conflicting pull request gets no hosted run at all, why the
fog lane had to be registered in the new TN_LANE_FILTERS inventory or the
selector throws, and the measured selection result (this merge selects all
eight lanes as the shape change, a fog-source-only list selects fog alone).

Records a fresh 29-arm browser WebGPU requalification at 6701a80 with its own
arm digests and summary.json 9cd50fb3, since that is a new source. Linux native
at this head stays unticked and unclaimed until the hosted fog-native lane runs;
the b93944e native proof remains source-scoped. prd:progress still prints
prd:100% — ready, and no threshold, fixture or box moved.
…ic-fog

Develop advanced a third time (#419) while the second reconciliation was in
flight, consolidating docs/PRDs into contextual folders. That change conflicts
with this branch's archived VQ-07 PRD in a way that needs a decision rather
than a textual merge, so it is resolved on the docs' own rule: a finished PRD
is never un-filed or replaced by a fresh plan.

The consolidation moved the original PROPOSED planning copy from
docs/PRDs/batch-2026-10-01-visual-quality/ to docs/PRDs/rendering/, which put
a second, unticked PRD-VQ-07 next to this branch's completed, archived copy in
done/. The stale planning copy is deleted so exactly one VQ-07 exists and it is
the qualified one; its ticked boxes, evidence and landed commits stay. No
develop document links to that path (only VQ-08 names VQ-07 in prose), so
nothing is left dangling. The batch README row this branch had repointed at the
archive is gone with the folder, and no replacement index exists on develop.

Everything else is develop's: all thirteen other VQ PRDs and the rest of the
folder moves are preserved as upstream made them. This is a docs-only delta, so
no fog source, fixture, scenario, threshold or CI contract changed; root
typecheck and lint exit 0, the doc-links/evidence/mirror/primary-docs selection
passes 46/46, check:docs exits 0 and budgets reports evidence budget: ok.
@jonit-dev
jonit-dev added this pull request to the merge queue Oct 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 3, 2026
@jonit-dev

Copy link
Copy Markdown
Contributor Author

Superseded by #397 to keep related exposure/fog work on one coherent CI board. The published survivor head is c16786fe3ab506bd63379b6e082fafb659c2ad2a; GitHub's remote comparison confirms exact source head edd5e1d6eef2ef306234a615d6f392861b2ee0f8 remains an ancestor. All original archived PRDs, original checkpoint/checklist and proof links are retained in the survivor.

The frozen native dry-run repair is retained with a separately reviewed lint-only lazy-import split. All 84 native runner tests pass; timeouts and required scenarios are unchanged. The actual combined browser GPU evidence, including off/both screenshots and the preserved first failed lifecycle attempt, is linked in #397. Sailing first-height readback and fluid CI failures remain unresolved; this supersession is not a merge to develop or a green exact-head CI claim.

Closing this source PR only after verified publication and cross-links. Its branch is retained.

@jonit-dev jonit-dev closed this Oct 4, 2026
jonit-dev added a commit that referenced this pull request Oct 8, 2026
Auto exposure and volumetric fog are in review (#397, #399), tone gates
ship (PRD-341), GPU-driven culling and projected-size culling are
partial (PRD-386, PRD-390). Cells edited in the sheet XML so the
workbook keeps its conditional formatting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prd:100% — ready PRD complete, ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant