Skip to content

v1.2.0

Choose a tag to compare

@ZviBaratz ZviBaratz released this 21 Jul 12:26
95188b9

Added

  • A runnable fresco screensaver CLI (cmd/fresco). fresco is now directly
    runnable, not only importable: go install github.com/ZviBaratz/fresco/cmd/fresco@latest
    builds a full-screen terminal screensaver around the pure Render engine. It
    auto-sizes to the terminal and re-renders on resize (SIGWINCH on Unix, a size
    poll where there is none), animates in the alternate screen so scrollback is
    preserved, and takes single-key controls (q/Ctrl-C quit, space next variant,
    p pause). The terminal is restored on every exit path — normal end,
    Ctrl-C/SIGTERM, error, and panic — through a LIFO teardown stack behind a
    deferred restore, so the screensaver can't wedge the terminal. Flags cover the
    variant (a name or cycle/all), palette (presets or five custom hex anchors,
    validated through Palette.Validate), fps, seconds-per-variant, focal-row,
    lum-range, colour profile, duration, --size, --once, and --list;
    NO_COLOR/FORCE_COLOR are honoured, and a non-TTY stdout degrades to a single
    frame so a pipe or CI never hangs on a size query or spews control codes. The
    fresco package gains no new dependency and no impurity — all terminal I/O,
    the clock, and signals live under cmd/, and the logic is factored into a pure,
    TTY-free-testable core (flag/profile resolution, frame composition, the variant
    schedule) plus a thin impure driver exercised through a fake Console.

  • galaxy_figures_test.go makes the galaxy's shipped figures executable. Every
    quantitative "because" in the galaxy's comments is backed by a measurement, but
    those measurements lived only in prose, which rots — the #60/#61 work alone quoted
    three figures that had already gone stale (118.5 → 135.5, the ruler "odd → even",
    "~3% → ~0.7%"). The new test asserts the shipped figures the compiled renderer
    produces — whole-pane/arm clipping (1.36% / 0.92%), nucleus glyph contrast
    (0.430), core/arm/outskirts bead density (58.4 / 135.5 / 67.3), core/mid
    colour-stop density (11.46 / 6.13), and the lumRange 0.75 → 0.60 arm-annulus
    A/B (93.1 → 135.5) — each within ±5%, measured through the existing helpers and
    the public Options.LumRange override, with no twin of the renderer's
    internals
    . It passes on main and fails on a deliberate galBulgeAmp tweak;
    each assertion names the prose that quotes it. It does not assert the ridge/gas
    ratio (243.8 / 26.8), which is defined on the raw arm value the point function
    never returns and so cannot be measured without such a twin — that stays a
    tuning-probe finding in prose. SKILL.md §7 gains the tuning-probe (throwaway) vs
    figures-test (permanent) distinction. No rendered-byte change; an unparam
    nolint on two shared test helpers (now called from a second file) is the only
    edit to existing code.

  • rain_figures_test.go makes the rain's shipped figures executable, the second
    application of that convention — and the one it earns hardest, since rain is the
    field whose figure already rotted on screen: the layer cascade shipped pinned in
    raw field units, upstream of the smoothstep contrast curve, and rendered 3.9 L*
    apart against the 16.2 its comment claimed (fixed in [1.1.0]). The new test
    measures the cascade on the side of the curve the eye sees, two ways: it pins the
    layer head cascade (81.9 / 65.7 / 47.4 / 29.1, separations 16.2 / 18.3 / 18.3)
    and the per-layer head-outshines-tail steps (28.2 / 36.6 / 30.4 / 18.1) through
    rainScreenStopFor — the real smoothstep and stop quantization applied to each
    layer's shipped bright, read off the real ramp — and it anchors those with two
    rendered-byte figures: the lit fraction at rain's quoted 96×30 pane (27.0%,
    guarding rainDensity) and the rendered proof that the mid layer's heads land in
    the L* 60–69 band, which must dominate the 70–79 band they vacated. All within ±5%
    (reusing the galaxy file's requireFigure), passing on main and failing on the
    pre-fix rainLayers mid bright 0.64 → 0.72, which inverts the rendered bands
    exactly as [1.1.0] describes. It does not assert the one-off histogram counts
    (239 → 53, 50 → 193), which do not reproduce without the demonstration's
    unrecorded pane/frame span — their robust relation is the test, the counts stay
    prose — and there is no lumRange A/B, since lumRange is a dead lever for rain
    (pinned at 1). SKILL.md §7 gains the rain refinements (post-curve + rendered-byte
    anchor; demonstration-count-vs-relation; the unparam dodge). No rendered-byte
    change, and this time no edit to existing code at all — the shared rainStopGrid
    helper is called at a pane distinct from its other caller, so unparam stays quiet
    without a nolint.

  • tunnel_figures_test.go makes the tunnel's fog geometry executable, the third
    application of the convention. The tunnel already carries a thorough invariant
    suite, but its one quantitative geometry claim — how deep the fog's black core
    reaches — lived only in prose. The test pins it from both sides: the analytic
    half-lit radius the shipped fog constants imply (0.5·(tunFogA/tunRefD)/(tunFogGain − 0.5) = 18.4% of maxD, so it fails the moment tunFogA, tunRefD or tunFogGain
    drift under the quoted figure), and the rendered half-peak crossing of the
    radial luminance profile (≈15% of maxD), asserted to be the same curve across
    96×30 / 160×44 / 240×60 / 300×80
    — the tunnel's defining scale invariance — and to
    sit inside the analytic 18.4%. Within ±5% (reusing requireFigure), passing on
    main and failing on a tunFogGain tweak. Measuring it corrected a stale prose
    figure: the profile crosses at ≈15% (13.9–15.4%), not the 16% the comment
    claimed, so tunnel.go and the test now agree. It does not assert the
    ring-spacing product — tunnel.go quotes a good value of 400 against the shipped
    tunDepthK·tunFreqU = 70, a genuinely stale figure, but rendered ring spatial
    frequency
    has no single value to pin (it varies as r² by design), so the
    discrepancy is surfaced here rather than tested. One new file plus the two prose
    fixes; no rendered-byte change.

  • ripple_figures_test.go makes the ripple's packet-shape figures executable, the
    fourth application of the convention — and ripple is the field that proves why the
    gap matters: its row-pitch capture comment carried a stale 87.3% for three PRs
    after rippleCyc moved 1.5 → 1.8, because the figure was folded to a literal
    cos(0.15pi) that outlived the constant it came from, and the 75% floor guarding it
    never noticed. The new test pins the shipped packet shape on the compiled
    rippleDropWave: the worst row-pitch capture (82.8%, the anti-blink margin), the
    packet trough as a share of its crest (54% at the shipped cyc, only floored at 30%
    before) and where that trough sits (x = 0.48), the ring-open fraction
    (rippleHueOpen = 0.38) and a lone crest's amplitude (0.65 = rippleAmp, asserted
    under the clamp so two rings adding have headroom to read as constructive). Each
    within ±5% (reusing requireFigure), passing on main and failing on the pre-1.8
    rippleCyc 1.8 → 1.5, which drifts the capture back to exactly the stale 87.33%.
    It does not re-run the rippleCyc sweep (15/29/41/54/61%) — that is a tuning
    probe, so only the shipped point is pinned — nor the candidate-skip distribution
    (49.7 / 43.7 / 6.6%), an internal branch statistic the point function never
    exposes, which stays a prose measurement like galaxy's ridge/gas. One new file, no
    edit to existing code, no rendered-byte change.

  • aurora_figures_test.go makes the aurora's tuning figures executable, completing
    the roster (all five variants now guard their shipped figures). It pins the two
    numbers aurora is actually tuned around: the drift-trap Nyquist figure — the
    finest fBm octave sits at auroraFreqX·2^(auroraOct−1) = 0.40 cycles/cell, below the
    0.5 limit, so no octave crawls sideways as the curtains drift (a fourth would land
    at 0.80 and alias) — and the fBm window placement: measured on the compiled
    auroraFBM, its median is ~0.50 and its 90th percentile ~0.67, and the curtain
    window must straddle the upper third (auroraLo just above the median, auroraHi
    near the 90th percentile). Within ±5% (reusing requireFigure), passing on main
    and failing on auroraFreqX 0.10 → 0.15 (finest drifts to 0.60, past Nyquist) or
    auroraHi 0.70 → 0.80 (off the fitted p90). Measuring corrected two stale prose
    numbers: the fBm clusters around 0.50 (not 0.53) and tails to ~0.79 at the 99th
    percentile (not "near 0.82") — aurora.go now matches. One new file plus that prose
    fix; no rendered-byte change.

    With this the executable-figures convention is applied across the whole roster
    (galaxy, rain, tunnel, ripple, aurora), and SKILL.md §7 documents it as the standing
    practice for a shipped figure.

Changed

  • fresco.Tunnel's ring-spacing comment (tunDepthK) corrected to match the
    shipped product, resolving the discrepancy the tunnel figures test surfaced. The
    comment quoted a good product of 400 against a bad 72, but the shipped
    tunDepthK·tunFreqU is 70 — at the "bad" end. That framing predated the octave
    stack and the per-octave mip: 70 is the coarsest octave's ring spacing,
    deliberately coarse (tunFreqU is low for the dead-zone reason its own comment
    gives), and the five-octave stack plus the mip carry the rings out to the rim, not a
    single high product. Verified before rewriting — the wall's texture variance is flat
    at the mip-quieted centre and carries out into the pane (already pinned by
    TestSplashTunnelMipQuietsTheVanishingPoint), the opposite of the "coloured haze"
    the old comment feared. Comment only; no code or rendered-byte change.

Removed

  • cmd/fresco-demo is retired, superseded by the new cmd/fresco CLI above
    (#72). The old command was a fixed-size demo loop wired for the vhs recording;
    the vhs demo tape now builds cmd/fresco, which subsumes and surpasses it.
    Breaking: go install github.com/ZviBaratz/fresco/cmd/fresco-demo (shipped
    through v1.0.0 and v1.1.0) no longer resolves — install
    github.com/ZviBaratz/fresco/cmd/fresco instead, which auto-sizes, animates in
    the alternate screen, and takes flags for the size and duration the demo hard-coded.