re: initial focus is TUTORIAL x3 / NEW GAME x3, and never anything else
Two more data points for the Q5 instability, from today s drives. A run that pressed A with no d-pad movement ended in a tutorial mission, correlating +0.960 with the committed capture, so that boot opened on TUTORIAL. A later boot read NEW GAME from a focus detector on the first menu frame. Six boots on the same harness now: TUTORIAL three times, NEW GAME three times, and no other item ever observed. The distribution is not uniform over the five buttons -- only these two occur -- which is a real constraint on whatever selects initial focus and something an explanation will have to account for. Also records in METHOD a bug that cost a seven-minute driven boot: a value was clamped for readability BEFORE the comparison that used it. A focus detector printed a degenerate margin, so it was capped at 999; the cap ran before the vote-sorting step, two different votes compared equal, the stable sort kept the wrong one, and a correct NEW GAME became an out-of-range index and a refusal. The measurement was right throughout -- a cosmetic fix changed a decision. Clamp at the point of display, never upstream of a comparison. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
@@ -86,10 +86,13 @@ def classify(shot, A, B, ra, pitch):
|
||||
for ref, ref_idx in ((A, IDX_A), (B, IDX_B)):
|
||||
prof = row_profile(shot, ref)
|
||||
r, peak, med = peak_row(prof)
|
||||
# A zero median makes this explode -- floor it at a level that is
|
||||
# small but real, so a degenerate comparison reads as "huge" rather
|
||||
# than 1e10, and cap it so the printed number stays meaningful.
|
||||
margin = min(peak / max(med, 1.0), 999.0)
|
||||
# A zero median makes this explode, so floor it. 🔴 Do NOT cap here:
|
||||
# an earlier version capped at 999 to keep the printed number readable,
|
||||
# which made two different votes compare EQUAL, and the stable sort then
|
||||
# kept the wrong one -- turning a correct NEW GAME into an out-of-range
|
||||
# index and a refusal. Cap at the point of DISPLAY, never before a
|
||||
# comparison that depends on the value.
|
||||
margin = peak / max(med, 1.0)
|
||||
idx = int(round((r - ra) / pitch))
|
||||
votes.append((idx, margin, ref_idx))
|
||||
# If the shot IS one of the references, that comparison is degenerate (all
|
||||
@@ -131,9 +134,10 @@ def main():
|
||||
got, margin = classify(shot, A, B, ra, pitch)
|
||||
ok = got is not None and margin >= MIN_MARGIN
|
||||
if as_json:
|
||||
print(json.dumps({"button": got, "margin": round(margin, 3), "decided": ok}))
|
||||
print(json.dumps({"button": got, "margin": round(min(margin, 999.0), 3),
|
||||
"decided": ok}))
|
||||
else:
|
||||
print(f"{got if ok else 'UNDECIDED'} margin={margin:.2f}")
|
||||
print(f"{got if ok else 'UNDECIDED'} margin={min(margin, 999.0):.2f}")
|
||||
return 0 if ok else 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user