v1.2.0
Added
-
A runnable
frescoscreensaver 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 pureRenderengine. 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,
ppause). 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 orcycle/all), palette (presets or five custom hex anchors,
validated throughPalette.Validate), fps, seconds-per-variant, focal-row,
lum-range, colour profile, duration,--size,--once, and--list;
NO_COLOR/FORCE_COLORare 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
frescopackage gains no new dependency and no impurity — all terminal I/O,
the clock, and signals live undercmd/, 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 fakeConsole. -
galaxy_figures_test.gomakes 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 lumRange0.75 → 0.60arm-annulus
A/B (93.1 → 135.5) — each within ±5%, measured through the existing helpers and
the publicOptions.LumRangeoverride, with no twin of the renderer's
internals. It passes onmainand fails on a deliberategalBulgeAmptweak;
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 rawarmvalue 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; anunparam
nolint on two shared test helpers (now called from a second file) is the only
edit to existing code. -
rain_figures_test.gomakes 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 thesmoothstepcontrast curve, and rendered3.9 L*
apart against the16.2its 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, separations16.2 / 18.3 / 18.3)
and the per-layer head-outshines-tail steps (28.2 / 36.6 / 30.4 / 18.1) through
rainScreenStopFor— the realsmoothstepand stop quantization applied to each
layer's shippedbright, 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%,
guardingrainDensity) 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'srequireFigure), passing onmainand failing on the
pre-fixrainLayersmidbright 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, sincelumRangeis a dead lever for rain
(pinned at1). SKILL.md §7 gains the rain refinements (post-curve + rendered-byte
anchor; demonstration-count-vs-relation; theunparamdodge). No rendered-byte
change, and this time no edit to existing code at all — the sharedrainStopGrid
helper is called at a pane distinct from its other caller, sounparamstays quiet
without a nolint. -
tunnel_figures_test.gomakes 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 momenttunFogA,tunRefDortunFogGain
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% (reusingrequireFigure), passing on
mainand failing on atunFogGaintweak. Measuring it corrected a stale prose
figure: the profile crosses at≈15%(13.9–15.4%), not the16%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 of400against 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.gomakes 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 stale87.3%for three PRs
afterrippleCycmoved1.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% (reusingrequireFigure), passing onmainand failing on the pre-1.8
rippleCyc 1.8 → 1.5, which drifts the capture back to exactly the stale87.33%.
It does not re-run therippleCycsweep (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.gomakes 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 atauroraFreqX·2^(auroraOct−1) = 0.40cycles/cell, below the
0.5limit, so no octave crawls sideways as the curtains drift (a fourth would land
at0.80and alias) — and the fBm window placement: measured on the compiled
auroraFBM, its median is~0.50and its 90th percentile~0.67, and the curtain
window must straddle the upper third (auroraLojust above the median,auroraHi
near the 90th percentile). Within ±5% (reusingrequireFigure), passing onmain
and failing onauroraFreqX 0.10 → 0.15(finest drifts to0.60, past Nyquist) or
auroraHi 0.70 → 0.80(off the fitted p90). Measuring corrected two stale prose
numbers: the fBm clusters around0.50(not0.53) and tails to~0.79at the 99th
percentile (not "near0.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 of400against a bad72, but the shipped
tunDepthK·tunFreqUis70— at the "bad" end. That framing predated the octave
stack and the per-octave mip:70is the coarsest octave's ring spacing,
deliberately coarse (tunFreqUis 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-demois retired, superseded by the newcmd/frescoCLI above
(#72). The old command was a fixed-size demo loop wired for the vhs recording;
the vhs demo tape now buildscmd/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/frescoinstead, which auto-sizes, animates in
the alternate screen, and takes flags for the size and duration the demo hard-coded.