scale_trace: always say HOW the numbers were taken; trust adjacent frames

First clean run — both sides sampled, no errors, no fallback:

  psx-runtime  72, 74, 76, 78    steps of 2
  oracle       12, 16, 20, 24    steps of 4

Both sweep smoothly; neither jumps. The ranges are disjoint (72-78 against
12-24), which is the two sides sitting at different points in the fade, not a
fault.

But the report could not say whether psx-runtime's series was per-frame or
free-running, because native_sampling was only set on the fallback path. Those
support completely different claims: steps of 2 across CONSECUTIVE frames is a
smooth fade, while steps of 2 across samples ninety frames apart is nothing at
all. The field is now set before either path runs and overwritten by whichever
one did.

And the eight-sample floor was applied to per-frame data, where it does not
belong. Consecutive frames measure the increment DIRECTLY rather than sampling
a distribution — four adjacent frames stepping by 2 IS the step. The floor
still applies to free-running samples, which say nothing however many there
are. Applying it to per-frame discarded a measurement that was already
conclusive.

A per-frame result now also states what the increment means: at a median step
of 2 the scale crosses its whole range in about 64 frames, roughly a second,
which does not produce hard bands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Vanderveen
2026-08-23 01:00:47 -04:00
parent fdf8a76274
commit fcd577b02c
2 changed files with 81 additions and 10 deletions
+28 -9
View File
@@ -346,6 +346,7 @@ def main(argv=None):
"""
vals, why = sample_per_frame(conn, pc_, count, reg_)
if vals:
doc["native_sampling"] = "per-frame"
return vals, why
print(f" psx-runtime: per-frame captured nothing ({why}); retrying "
f"free-running — the steps will be aliased, but a measurement "
@@ -355,6 +356,10 @@ def main(argv=None):
doc["native_sampling"] = "free-running-fallback"
return vals2, (why2 or why)
# Recorded up front and overwritten by whichever path actually ran. Leaving
# it unset on success meant a per-frame series and a free-running one looked
# identical in the report -- and they support completely different claims.
doc["native_sampling"] = "free-running"
if args.per_frame:
print(" psx-runtime: stepping one frame between reads, so the deltas "
"are the real per-frame increment")
@@ -495,16 +500,30 @@ def main(argv=None):
print(f"\n Step sizes are comparable "
f"(psx-runtime max {a['max_step']}, oracle max "
f"{b['max_step']}), so the fade granularity matches too.")
elif (args.per_frame and a["samples"] >= 5
and doc.get("native_sampling") != "free-running-fallback"):
elif doc.get("native_sampling") == "per-frame" and a["samples"] >= 4:
# Consecutive frames measure the increment directly. That is not a
# sample of a distribution needing a quorum -- four adjacent frames
# showing steps of 2 IS the step, whereas four free-running samples
# ninety frames apart say nothing however many there are.
doc["granularity"] = "native-measured-per-frame"
print(f"\n psx-runtime, sampled on CONSECUTIVE frames, moves in "
f"steps of up to {a['max_step']} (median "
f"{a['median_step']}). That is its real animation increment. "
f"The oracle's series is not frame-adjacent, so its apparent "
f"step is an upper bound only — but a per-frame increment "
f"this large is a coarse fade regardless of what the oracle "
f"does.")
smooth = a["max_step"] <= 8
doc["native_smooth"] = smooth
print(f"\n psx-runtime, on {a['samples']} CONSECUTIVE frames, "
f"moves in steps of up to {a['max_step']} (median "
f"{a['median_step']}). That is its real animation increment.")
if smooth:
print(f" That is a SMOOTH fade — at {a['median_step']} per "
f"frame the scale crosses its whole range in about "
f"{128 // max(1, int(a['median_step']))} frames. It does "
f"not produce hard bands, so the coarse-fade explanation "
f"is out.")
else:
print(f" That is a COARSE fade: jumping by up to "
f"{a['max_step']} per frame produces hard bands rather "
f"than a gradient, which is the reported symptom.")
print(f" The oracle's series is not frame-adjacent, so its "
f"apparent step is an upper bound only and the two step "
f"figures are not comparable.")
elif doc.get("native_sampling") == "free-running-fallback":
# The claim that must never be made from aliased data: these steps
# are an artefact of sampling ~90 frames apart, not the animation
+53 -1
View File
@@ -376,7 +376,10 @@ class TestAliasedDataIsNeverCalledPerFrame(unittest.TestCase):
for marker in ('"native-measured-per-frame"', '"native-per-frame-only"'):
i = src.index(marker)
window = src[max(0, i - 400):i]
self.assertIn("free-running-fallback", window,
# Either spelling of the guard is fine — excluding the fallback, or
# requiring per-frame outright. What matters is that the claim is
# conditioned on HOW the numbers were obtained.
self.assertIn("native_sampling", window,
f"{marker} is set without checking native_sampling")
def test_a_fallback_run_gets_its_own_granularity_label(self):
@@ -404,3 +407,52 @@ class TestSampleSelection(unittest.TestCase):
src = inspect.getsource(ST.sample_per_frame)
self.assertIn("for cand in ranked:", src)
self.assertIn("break", src)
class TestSamplingMethodIsAlwaysRecorded(unittest.TestCase):
"""The report must say HOW the numbers were obtained, on every path.
A clean run came back with four psx-runtime samples stepping by 2 and no
native_sampling field at all, because it was only set on the fallback path.
A per-frame series and a free-running one then look identical in the report
— and they support completely different claims. Steps of 2 across
consecutive frames is a smooth fade; steps of 2 across samples ninety
frames apart is nothing.
"""
def test_a_default_is_set_before_either_path_runs(self):
import inspect
src = inspect.getsource(ST.main)
self.assertIn('doc["native_sampling"] = "free-running"', src)
def test_success_labels_itself_per_frame(self):
import inspect
src = inspect.getsource(ST.main)
self.assertIn('doc["native_sampling"] = "per-frame"', src)
def test_the_fallback_still_labels_itself(self):
import inspect
src = inspect.getsource(ST.main)
self.assertIn('"free-running-fallback"', src)
class TestConsecutiveFramesNeedNoQuorum(unittest.TestCase):
"""Four adjacent frames stepping by 2 IS the step.
Per-frame samples measure the increment directly rather than sampling a
distribution, so the eight-sample floor that free-running data needs does
not apply — and applying it discarded a measurement that was already
conclusive.
"""
def test_four_per_frame_samples_are_enough(self):
import inspect
src = inspect.getsource(ST.main)
i = src.index('doc["granularity"] = "native-measured-per-frame"')
# The condition sits above the comment block explaining it.
self.assertIn('a["samples"] >= 4', src[max(0, i - 700):i])
def test_free_running_still_needs_more(self):
import inspect
src = inspect.getsource(ST.main)
self.assertIn('a["samples"] >= 8 and b["samples"] >= 8', src)