refactor(frame): dissolve RenderFrameSettings — passes read from state + ctx#360
Merged
Conversation
Adds the approved design spec and TDD implementation plan for removing the per-frame RenderFrameSettings bag (passes read from state + ctx), plus the backlog entry folding the GPU-handle nullability follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
No pass or encode* read deps.catalogs / deps.famousMeta — the thumbnail
subsystem reads state.data.galaxies.{catalogs,famousMeta} directly. Pure
deletion of the dead fields from RenderFrameInput, PassDeps, the renderFrame
deps assembly, the runFrame input assembly, and the test fixtures that fed
them (plus the now-orphaned makeCloud helpers + imports).
Phase 0 of dissolving RenderFrameSettings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Additive Phase 1 of dissolving RenderFrameSettings: the two genuinely per-frame-derived values gain a home on ctx. visibleSourceMask is set at construction (passed into deriveFrameContext from masks.draw); focus is seeded to the at-rest ZERO_FOCUS sentinel and overwritten by runFrame at the existing ctx.focusBlend site — still exactly one produceFocusUniforms tick per frame. Nothing reads the new fields yet; RenderFrameSettings still carries them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tings bag The heaviest RenderFrameSettings consumer now sources every PointDrawSettings field from its real home: state.settings.galaxyCatalogs/bias, ctx.visibleSourceMask, state.selection.select, and the PROCEDURAL_DISK_FADE_* constants. The settings param stays in the draw signature (renamed _settings) until the Phase 3 sweep. Byte-identical render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nabled Re-sources the Milky-Way gate off the settings bag onto its real home. The settings param stays in the signature (renamed _settings) until the Phase 3 sweep. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d,intensity} Re-sources both the enabled gate and the draw intensity off the settings bag. The settings param stays in both signatures (renamed _settings) until the Phase 3 sweep. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both texturedDisksPass and proceduralDisksPass gate on the real thumbnails setting instead of the settings bag's galaxyTexturesEnabled. The settings param stays in both signatures (renamed _settings) until the Phase 3 sweep. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mes.enabled Re-sources the volume-upsample gate off the settings bag. The settings param stays in the signature (renamed _settings) until the Phase 3 sweep. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…talogs.sizePx Re-sources the selection-ring radius off the settings bag. The settings param stays in the signature (renamed _settings) until the Phase 3 sweep. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bled Re-sources the volume master gate off the settings bag. Also migrates the three renderFrame integration fixtures (renderFrame, timing, split-baseline) to derive a full nested state.settings + state.selection from each fixture's flat settings bag — these integration tests drive every pass through the real pipeline, so they need the state shape the passes now read directly (Tasks 3-8 moved those reads off the bag). The flat bag stays the single fixture knob; all overrides and assertions are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The three reads renderFrame itself makes now source from their real homes: the focus uniform write takes ctx.focus, and postProcess.draw's exposure + curve come from state.settings.tonemap. The settings bag still rides on RenderFrameInput until the Phase 3 sweep removes it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 3 sweep: the per-frame RenderFrameSettings bag is gone. Pass.enabled /draw and the four encode* functions no longer carry a settings parameter — every pass now reads from state/ctx/constants. RenderFrameInput drops the settings field; runFrame drops the bag-assembly literal (and its now-dead PROCEDURAL_DISK_FADE_* imports); RenderFrameSettings.d.ts is deleted. Mechanical care: settings sat 4th-of-5 in Pass.draw and encodeVolumePrepass, so deps / timingService shift left a slot — all 13 pass signatures and every call site updated in lockstep. Test fixtures keep their local settings bag as the derivation source for state.settings and drop it from the input object. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pers Final-review tidy: these per-pass test makeDeps() literals still built the catalogs/famousMeta keys that this branch deleted from PassDeps. They were inert (an `as PassDeps` cast suppressed the excess-property error). Removing them finishes the dead-key deletion across all fixtures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
DoD audit PASS: full suite 2978 green, typecheck clean (both tsconfigs), all 11 task checkboxes ticked, no unowned TODOs, no comment-style smells, visual-parity smoke test confirmed this session, whole-branch review APPROVE_WITH_MINOR (both Minor findings fixed). Relocates the plan + spec to completed/. Deferred (documented): selector/useSettings unification and the labels.declutterEnabled feature (next PR); GPU-handle nullability follow-up stays in BACKLOG. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Deletes the per-frame
RenderFrameSettingsbag — a 16-field struct assembled each frame inrunFrame.tsand threaded as asettingsparameter through every renderPass.enabled/drawand the fourencode*functions. It fused four provenances (user settings, selection, per-frame-derived values, compile-time constants) into one place where a reader couldn't tellsettings.x's origin. This finishes the half-done D.2 migration (statewas already plumbed into passes "so they could read engine-side data without a RenderFrameSettings field for every consumer") and removes the bag.Each value now flows from its real source:
state.settings.<path>state.selection.selectvisibleSourceMask,focus) →ctx(ReadyFrameContext)PROCEDURAL_DISK_FADE_{START,END}_PXconstantsAlso deletes two long-dead fields (
catalogs,famousMeta) fromRenderFrameInput/PassDeps— nothing read them (the thumbnail subsystem readsstate.data.galaxies.*directly).Behaviour neutrality
Pure refactor: every byte delivered to every renderer is identical — only the delivery path changed. No settings-shape change, no new toggle, no render-order change. Whole-branch review verified the field→source mapping consumer-by-consumer (including the
toneMapCurve→tonemap.curve,realOnlyMode→realOnly,pointSizePx→sizePxrename traps) and that the once-per-frameproduceFocusUniformstick is preserved.Verification
npm run typecheckclean (bothsrc+toolstsconfigs)Notes
Executed via subagent-driven development (11 tasks). Spec + plan moved to
docs/superpowers/{specs,plans}/completed/.Deferred (documented): selector/
useSettingsunification; thelabels.declutterEnabledfeature (the next PR, first consumer of this clean read surface); the GPU-handle nullability follow-up (BACKLOG, now unblocked).🤖 Generated with Claude Code