Skip to content

Color-by-temporal-change + colorize-last invariant (levers 3 & 9) - #37

Merged
tamirelazar merged 14 commits into
devfrom
feat/temporal-color
Jun 18, 2026
Merged

Color-by-temporal-change + colorize-last invariant (levers 3 & 9)#37
tamirelazar merged 14 commits into
devfrom
feat/temporal-color

Conversation

@tamirelazar

@tamirelazar tamirelazar commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Implements the temporal-color art-direction lever (#29) on top of the colorize-last invariant fix (#28). Closes #28, closes #29.

Global default OFF — a bare run, the Organic default, and all existing presets/saved-configs are byte-identical to before. The feature only activates when a user passes --temporal-color > 0 (or selects a future showcase preset).

What changed

Lever 9 — colorize-last invariant

  • Extracted palette::colorize_subpixel: a single shared colorize pass now used by every output (TUI frame buffer, GIF, WebM, headless print, frame capture, and PNG save).
  • Fixed interactive PNG save, which previously mapped colors with mapping = None and so skipped intensity-mapping (and would have skipped all new color levers). Saved stills now match the live look.
  • Added a module-level invariant doc and a PNG/render colorize-parity guard test.

Lever 3 — color-by-temporal-change

  • Sim maintains an EMA temporal_lag buffer and emits a raw signed diff = trail − lag (positive = growing front, ~0 = settled vein, negative = decaying tail). Allocated only when temporal is enabled.
  • The signed diff is average-pooled through downsampling into AuxCell.signed_diff (sign preserved), normalized by the white-point in the colorizer, then modulated:
    • hue mode — rotate the base OKLch hue by tanh(k·diff_norm)·max_shift (front/tail rotate opposite directions).
    • accent mode — blend toward the palette's hot end in OKLch (Bleuje-style; most dramatic).
  • Exposed as --temporal-color <0..1>, --temporal-lag <frames>, --temporal-mode <hue|accent>, plus RuntimeState fields and saved-config persistence (#[serde(default)] so old TOML loads unchanged).
  • Applies across TUI, GIF, WebM, frame-capture, print, and saved PNG.

Known limitation

Loading a saved config with temporal_color > 0 does not re-enable the sim computation live (temporal stays off until restart with the flag). This fails safe (base colors, never wrong) and mirrors the existing trail-age/delta/gradient CLI-only-at-startup behavior; the proper fix belongs with the config live-apply / cache-sync refactor, not this change.

Test plan

  • cargo fmt --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test (774 lib + integration + doc)
  • cargo test --test visual_regression — 47 pass; all 46 pre-existing goldens unchanged, 1 new temporal-on golden added
  • Default-off invariant traced end-to-end (buffers None → diff 0 → colorizer returns the legacy mapping); parity + seam tests lock it
  • Manual: -S --preset organic --temporal-color 0.8 --temporal-mode accent colors the growing front; --temporal-color 0 is unchanged
  • Manual: press g to save a PNG (with a non-default --intensity-mapping) and confirm it matches the screen
  • Manual: GIF export with vs without --temporal-color differs

@tamirelazar
tamirelazar merged commit 8fd28e8 into dev Jun 18, 2026
3 checks passed
@tamirelazar
tamirelazar deleted the feat/temporal-color branch June 18, 2026 13:24
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