
Evidence
Built directly, not by the squad: every squad agent in this session was blocked at the permission layer before it could read a file. Every number below came out of Playwright/Chromium with --use-gl=swiftshader, in a reducedMotion: 'reduce' context, so each state is ONE frame at t = 3.0 — the same instant, differing only in the sky. The harnesses are beside this file: probe-df.mjs (the distribution), probe-tide.mjs (the four phases).
The shared mechanism
The ephemeris publishes window.MN_EPHEMERIS — {date, phase, illum, phaseName, seed, seedHex, hourOfDay, planet, mansion, figure} — and dispatches mn:ephemeris on every date change. The field reads it each frame. Nothing in the object is new information; every field is already printed in the ephemeris ledger. It adds reach, not claims.
Identity: a page with no ephemeris is bit-identical to neutral
none (no MN_EPHEMERIS) hash 1027496998
neutral (illum 0.5, phase 0) hash 1027496998 → identical
Defaults of u_tide = 0.5 and u_wax = 0 reproduce the unbound field exactly.
The four phases, one instant
Warm energy = Σ max(R−B, 0), cold = Σ max(B−R, 0) over the 1440×660 field.
| state | illum | phase | warm | cold | warm/cold |
|---|---|---|---|---|---|
| neutral | 0.5 | 0.00 | 4,863,612 | 4,019,431 | 1.21 |
| new moon | 0.0 | 0.00 | 3,747,185 | 16,402,316 | 0.23 |
| full | 1.0 | 0.50 | 17,962,129 | 3,675,821 | 4.89 |
| waxing (first quarter) | 0.5 | 0.25 | 6,717,058 | 2,573,279 | 2.61 |
| waning (last quarter) | 0.5 | 0.75 | 3,163,532 | 6,358,907 | 0.50 |
- New moon cold-led, full warm-led: true.
- Waxing warmer than waning at the same illumination: true (2.61 vs 0.50) — the asymmetry is the quarter, not the light.
- Lit-cell count varies by <1% across states: the moon moves hue, not density.
What the measurement found that nobody had looked for
The first run bound the moon and passed identity, new and full — and returned byte-identical hashes for waxing and waning. The asymmetric thresholds had no effect because the disagreement palette had never fired.
probe-df.mjs wrote |df| to a channel and read 15,147 cells at 1440×900:
p50 0.0088 p72 0.0147 p85 0.0201 p95 0.0265 max 0.0500
cells with |df| > 0.055 (the smoothstep start): 0
cells with |df| > 0.10 (the threshold): 0
The canon's 0.10 / 0.055 belong to p5's Perlin; this shader's value-noise never reaches half of the lower one. So "warm leads a rising contour, cold trails a falling one" — documented in §09 and in every evidence file since — was not the behaviour on screen. Every tint came through the agreement path, and at neutral it was warm-biased (old warm/cold 4.48) because the WARM/COLD midpoint reads warm under R−B.
Thresholds are now the measured p85 (full disagreement) and p72 (agreement ends), the percentile method the 1-bit solid uses for occlusion. The constants carry the measurement in a comment. After the change, at neutral:
warm/cold 4.48 → 1.21
Page-level
console errors 0 · pageerrors 0 · contrast failures 2 (the exempt disabled buttons)
review.mjs: two faces, weights 400/500, radius only on pills, sigil never a fill
Not established
- Real-GPU rendering. Software GL only.
- That the p85/p72 choice is the right percentile pair rather than a defensible one; the 1-bit solid's precedent is the reason, not a measurement of legibility across choices.
-
Whether the diagnostic uniform
u_probecosts anything on hardware that does not eliminate a dead branch; it is a single compare per fragment.