PURPOSE

Flat declarative registry of every tunable parameter exposed by the playground UI. One KnobDef per slider/toggle/dropdown/color control. The knobStore reads this at init to populate defaults and current values, and downstream apply logic uses applyGroup to route changes to the correct MissionHandle method group.

OWNS

  • KnobControl type alias ('slider' | 'toggle' | 'dropdown' | 'color').
  • KnobDef interface — id, label, category, control, optional min/max/step, default, applyGroup.
  • KNOB_REGISTRY — the canonical ordered list of all knob definitions grouped by category (Ship Stats, Spawner, VFX Lighting, VFX Fog, Physics, Level Gen, Game Flow).
  • KNOB_MAPRecord<string, KnobDef> lookup built from KNOB_REGISTRY via Object.fromEntries.
  • Private constructor helpers slider(...) and toggle(...) that build KnobDef objects with the appropriate control field set.

READS FROM

Nothing. This module is a pure data/type definition file with no imports.

PUSHES TO

Nothing directly. Consumers (knobStore, playground apply layer) import KNOB_REGISTRY, KNOB_MAP, KnobDef, and KnobControl.

DOES NOT

  • Does not apply knob values to game state — it only describes them.
  • Does not store current values — that lives in knobStore.
  • Does not render UI — the playground screen does.
  • Does not validate min/max ranges at runtime.
  • Does not define dropdown or color control entries despite the KnobControl union allowing them — only slider and toggle helpers exist and only those two control types appear in the current registry.
  • Does not provide a dropdown(...) or color(...) helper.

Signals

None. No events emitted, no observers, no callbacks. Pure data export.

Entry points

  • KNOB_REGISTRY — primary import for any consumer that needs to enumerate all knobs (e.g. store init, UI rendering).
  • KNOB_MAP — primary import for any consumer that needs O(1) lookup by knob id.
  • KnobDef / KnobControl types — imported by consumers that type-check against knob shapes.

Pattern notes

  • Data table, not code. Every tunable parameter is one row; logic lives elsewhere. Aligns with the “content in data tables, behavior in code” rule.
  • Flat array of records, no nesting. Categories are a string field on each row rather than a nested grouping structure; UI groups by category at render time.
  • applyGroup is the routing discriminator. Each knob declares which MissionHandle method group consumes it (shipStats, worldKnobs, lighting, fog, postProcess, physics, levelConfig, direct), so the apply layer can dispatch without per-knob switch statements.
  • id uses dotted namespacing (ship.hpMax, vfx.fogBelow, spawner.spawnRate) — first segment matches the category prefix.
  • default is typed as number | string | boolean to support all control types, even though current rows only use number and boolean.
  • KNOB_MAP is derived from KNOB_REGISTRY at module load — single source of truth, no risk of drift between list and lookup.
  • slider(...) and toggle(...) helpers exist purely for readability of long literal rows; they collapse the positional arguments into a uniform call site so the registry reads like a table.
  • postProcess appears in the applyGroup union but no current row uses it — reserved for future post-processing knobs.