Skip to content

refactor(frame): dissolve RenderFrameSettings — passes read from state + ctx#360

Merged
rulkens merged 14 commits into
mainfrom
refactor/dissolve-render-frame-settings
Jun 21, 2026
Merged

refactor(frame): dissolve RenderFrameSettings — passes read from state + ctx#360
rulkens merged 14 commits into
mainfrom
refactor/dissolve-render-frame-settings

Conversation

@rulkens

@rulkens rulkens commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What & why

Deletes the per-frame RenderFrameSettings bag — a 16-field struct assembled each frame in runFrame.ts and threaded as a settings parameter through every render Pass.enabled/draw and the four encode* functions. It fused four provenances (user settings, selection, per-frame-derived values, compile-time constants) into one place where a reader couldn't tell settings.x's origin. This finishes the half-done D.2 migration (state was 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:

  • user settings → state.settings.<path>
  • selection → state.selection.select
  • the two genuinely per-frame-derived values (visibleSourceMask, focus) → ctx (ReadyFrameContext)
  • the two fade thresholds → PROCEDURAL_DISK_FADE_{START,END}_PX constants

Also deletes two long-dead fields (catalogs, famousMeta) from RenderFrameInput/PassDeps — nothing read them (the thumbnail subsystem reads state.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 toneMapCurvetonemap.curve, realOnlyModerealOnly, pointSizePxsizePx rename traps) and that the once-per-frame produceFocusUniforms tick is preserved.

Verification

  • npm run typecheck clean (both src + tools tsconfigs)
  • Full suite 2978 tests green
  • Manual visual-parity confirmed on the dev server (points, thumbnails, every per-pass toggle, selection ring, focus fade all identical)
  • Whole-branch review: APPROVE_WITH_MINOR (both Minor findings — leftover dead keys in two test fixtures — fixed)

Notes

Executed via subagent-driven development (11 tasks). Spec + plan moved to docs/superpowers/{specs,plans}/completed/.

Deferred (documented): selector/useSettings unification; the labels.declutterEnabled feature (the next PR, first consumer of this clean read surface); the GPU-handle nullability follow-up (BACKLOG, now unblocked).

🤖 Generated with Claude Code

rulkens and others added 14 commits June 21, 2026 01:55
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>
@rulkens rulkens merged commit 0f7b3ee into main Jun 21, 2026
1 of 2 checks passed
@rulkens rulkens deleted the refactor/dissolve-render-frame-settings branch June 21, 2026 01:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant