re(ui): the rest fallback fires on 2 elements, and "last keyframe" wins there
Scored candidate rest-pose rules by rendering and correlating instead of
arguing, and both results correct something I had published.
First, the exposure. The guessing fallback is reached only by an element
that is plateau-less AND multi-keyframe -- a single-keyframe element
short-circuits at `match len { 1 => first }`. Per screen:
title (4) 24 elements 2 plateau-less 0 reach the fallback
main menu (5) 16 5 0
EXTRAS (6) 18 5 0
publisher splash (10) 3 2 1
developer splash (11) 7 2 1
So on the three screens the port cares most about, rest() never guesses.
That is why three different rules render builds 4/5/6 to identical
correlations -- the code is unreachable there, which I nearly read as
"the choice does not matter".
Second, where it does fire, the last keyframe is markedly better:
publisher splash dwell +0.9600 last +0.9982 maxalpha +0.9600
developer splash dwell +0.9643 last +0.9758 maxalpha +0.9643
That refutes my own earlier refutation. I had killed the last-keyframe
rule by arguing it makes palogo_anima_eff invisible while its two
siblings stay lit, which looked like an artefact. The capture says
otherwise: making it invisible is what improves the match. The sibling
symmetry was my expectation, not evidence.
Caveat kept in front: both captures are single frames of a transient
animation, so this fixes which pose matches THOSE frames, not which is
canonically at rest. Default unchanged -- better on both screens where it
fires and identical on the other three, but it would move 2 305 elements
disc-wide on two measurements. Reachable via SYLPHEED_REST_RULE=last.
Also confirmed: all 195 zero-scale rest poses are inside the corrected
2 305 ambiguous population; none is a single-keyframe element.
METHOD: score a rule where it can differ, or you measure nothing; and an
argument from symmetry is a prediction, not a refutation.
This commit is contained in:
@@ -190,6 +190,26 @@ impl Element {
|
||||
0 => None,
|
||||
1 => self.keyframes.first(),
|
||||
n => {
|
||||
// ⚠️ EXPERIMENT GATE, default off. Both published alternatives to
|
||||
// the longest-dwell fallback died by argument rather than by
|
||||
// measurement, and `compose` can score a rule against the live
|
||||
// captures — so they are reachable here to be tested.
|
||||
// SYLPHEED_REST_RULE=last -> the final keyframe
|
||||
// SYLPHEED_REST_RULE=maxalpha -> the most opaque keyframe
|
||||
match std::env::var("SYLPHEED_REST_RULE").as_deref() {
|
||||
Ok("last") => return self.keyframes.last(),
|
||||
Ok("maxalpha") => {
|
||||
let mut best = (0usize, 0u32);
|
||||
for (k, f) in self.keyframes.iter().enumerate() {
|
||||
let a = (f.fade >> 24) & 0xff;
|
||||
if a >= best.1 {
|
||||
best = (k, a);
|
||||
}
|
||||
}
|
||||
return self.keyframes.get(best.0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let mut best = (0usize, 0u32);
|
||||
for k in 0..n - 1 {
|
||||
let (Some(t0), Some(t1)) =
|
||||
|
||||
@@ -404,8 +404,18 @@ authored version can be deleted.
|
||||
and it is unambiguously their rest. Of the real 2 305, **195 get a degenerate
|
||||
`scale = 0 %` pose**, and the two
|
||||
candidate rules agree only **50.2 %** of the time.
|
||||
✅ **This does not block you.** On the five screens the port needs, 14 elements
|
||||
are affected and the candidate rules **agree on 13**. The single disagreement
|
||||
✅ **This does not block you — your exposure is TWO elements, both on the
|
||||
splashes.** The fallback is reached only by an element that is plateau-less
|
||||
*and* multi-keyframe; a single-keyframe element short-circuits. Title, main
|
||||
menu and `EXTRAS` reach it **zero** times, which is why three different
|
||||
fallback rules render them to identical correlations. The publisher and
|
||||
developer splashes reach it once each — and there, `SYLPHEED_REST_RULE=last`
|
||||
(the final keyframe) scores **+0.9982** and **+0.9758** against the current
|
||||
rule's +0.9600 and +0.9643. ⚠️ Measured against single frames of a transient
|
||||
animation, so it fixes which pose matches *those* captures, not which is
|
||||
canonically at rest. Default unchanged — it is better on both screens where it
|
||||
fires and identical on the other three, but it would move 2 305 elements
|
||||
disc-wide on two measurements. The single disagreement
|
||||
is `palogo_anima_eff.t32` on the developer splash, and the current answer is
|
||||
the defensible one there — see below. Still worth flagging plateau-less
|
||||
elements in an export rather than silently inheriting our guess; it is one pass
|
||||
|
||||
@@ -762,3 +762,15 @@ agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the
|
||||
It died the moment the rule was used to change a rendering, because the result
|
||||
was visibly worse. If a measurement implies an action, take the action on
|
||||
something you can score.
|
||||
* **Score a rule where it can actually differ, or you will measure nothing.**
|
||||
Three rest-pose rules rendered builds 4, 5 and 6 to *identical* correlations —
|
||||
not because they agree, but because the code they change is unreachable on
|
||||
those screens. The signal was on the two splashes, the only builds whose
|
||||
elements reach the fallback at all. Identical results across variants is a
|
||||
clue that the variant is not being exercised, not evidence that the choice does
|
||||
not matter.
|
||||
* **An argument from symmetry is a prediction, not a refutation.** I killed the
|
||||
last-keyframe rule because it treats one of three sibling glows differently,
|
||||
which felt like an artefact. Measured, it is the better rule on both screens
|
||||
where it applies. Aesthetic expectations about how authored data "should" look
|
||||
are worth stating as hypotheses and worth nothing as verdicts.
|
||||
|
||||
@@ -538,3 +538,13 @@ neighbourhood, not just the line.
|
||||
unambiguously its rest. 1 502 of the 3 807 are those; the genuinely ambiguous
|
||||
population is **2 305 (14.88 %)**.
|
||||
[`ui-resting-pose.md`](structures/ui-resting-pose.md)
|
||||
* "`rest()` for a plateau-less element should be the last keyframe → refuted by
|
||||
the sibling argument" → **that refutation is itself refuted, this time by
|
||||
measurement.** Rendering under the rule and correlating against the live
|
||||
captures: publisher splash +0.9600 → **+0.9982**, developer splash +0.9643 →
|
||||
**+0.9758**. Making `palogo_anima_eff` invisible *improves* the match; the
|
||||
sibling symmetry was my expectation, not evidence.
|
||||
* "the port's exposure to the rest-guessing defect is 14 elements" → **two.** The
|
||||
fallback needs an element to be plateau-less **and** multi-keyframe; title,
|
||||
main menu and `EXTRAS` reach it **zero** times, the two splashes once each.
|
||||
[`ui-resting-pose.md`](structures/ui-resting-pose.md)
|
||||
|
||||
@@ -431,3 +431,63 @@ The same flaw is in the census this page published:
|
||||
|
||||
So the guessed-rest population is **2 305, not 3 807** — the published figure
|
||||
overstated it by **65 %**. The defect is real and smaller than reported.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Where the fallback actually fires — and "last keyframe" wins there
|
||||
|
||||
**2026-08-29.** Two things fell out of scoring rules by rendering instead of
|
||||
arguing about them.
|
||||
|
||||
### The port's exposure is TWO elements, not fourteen
|
||||
|
||||
The guessing fallback is reached only by an element that is plateau-less **and**
|
||||
has more than one keyframe — a single-keyframe element short-circuits at
|
||||
`match len { 1 => first }`. Per screen:
|
||||
|
||||
| screen | elements | plateau-less | **reach the fallback** |
|
||||
|---|---|---|---|
|
||||
| title (4) | 24 | 2 | **0** |
|
||||
| main menu (5) | 16 | 5 | **0** |
|
||||
| `EXTRAS` (6) | 18 | 5 | **0** |
|
||||
| publisher splash (10) | 3 | 2 | **1** |
|
||||
| developer splash (11) | 7 | 2 | **1** |
|
||||
|
||||
On the three screens a port cares most about, **`rest()` never guesses at all**.
|
||||
That is why three different fallback rules render builds 4, 5 and 6 to *identical*
|
||||
correlations (+0.9500 / +0.9460 / +0.9440 for every rule) — the code is
|
||||
unreachable there.
|
||||
|
||||
### On the two splashes, the last keyframe is markedly better
|
||||
|
||||
Rendering under each rule (`SYLPHEED_REST_RULE=last|maxalpha`, default off) and
|
||||
correlating against the live captures:
|
||||
|
||||
| splash | dwell (current) | **last** | maxalpha |
|
||||
|---|---|---|---|
|
||||
| publisher | +0.9600 | **+0.9982** | +0.9600 |
|
||||
| developer | +0.9643 | **+0.9758** | +0.9643 |
|
||||
|
||||
`maxalpha` is indistinguishable from the current rule; **`last` gains +0.038 and
|
||||
+0.012**, and 0.9982 is very close to exact.
|
||||
|
||||
### 🔴 This refutes my own refutation
|
||||
|
||||
I had killed "rest = the last keyframe" by argument: on the developer splash it
|
||||
makes `palogo_anima_eff` invisible while its two siblings stay lit, which looked
|
||||
like an artefact. **The capture says otherwise** — making it invisible is what
|
||||
improves the match. The sibling symmetry was my expectation, not evidence.
|
||||
|
||||
⚠️ **The caveat that keeps this honest:** both captures are *single frames of a
|
||||
transient animation*. They fix which pose matches **these reference frames**, not
|
||||
which pose is canonically "at rest" — a grab a second earlier would show the
|
||||
glows. What the measurement supports is: for reproducing the committed captures,
|
||||
use the last keyframe.
|
||||
|
||||
🟡 **Default unchanged.** The rule is better on both screens where it fires and
|
||||
provably identical on the other three, but it would alter the rest pose of
|
||||
**2 305** elements disc-wide and two of them have been measured. Reachable via
|
||||
`SYLPHEED_REST_RULE=last` for anyone who wants to take that further.
|
||||
|
||||
✅ Unaffected by the earlier correction: all **195** zero-scale rest poses are
|
||||
inside the genuinely-ambiguous 2 305 — none is a single-keyframe element.
|
||||
|
||||
Reference in New Issue
Block a user