Methods
The analysis as it would run on human data: the model, the likelihood, the inference, the exclusions, and how much the answer moves when the choices are changed.
Orientation as a circular quantity
Orientation has period 180°: 1° and 179° are 2° apart. Every difference in the pipeline is a signed circular distance wrapped into (−90°, 90°]; every average is computed on the doubled angle. The response-error likelihood is a wrapped normal on the same circle, mixed with a uniform lapse component. A test suite pins the edge cases, because a wraparound bug near the 0/180 boundary manufactures large errors that correlate with the previous trial and looks exactly like serial dependence.
The models
Each model predicts the mean signed error on trial t. The primary model, M3adj_full, contains a derivative-of-Gaussian tuning curve on the lag-1 stimulus difference, the same on the lag-1 response difference, attraction to the cardinal axes, regression toward the running mean of the previous 5 and 20 orientations, and pull toward the dial’s random start angle; noise is estimated separately for the two contrast conditions. The derivative-of-Gaussian is scaled so that its amplitude parameter is the peak bias in degrees. The ladder also contains a no-history baseline, the naive lag-1 model, a linear-slope variant, a response-only model, a multi-lag model with geometric decay, a free uncertainty multiplier, a Bayesian observer whose uncertainty modulation is predicted rather than fitted, and a mixture model. Full specification: research/model_specification.md.
Inference
Models are fitted by maximum likelihood separately to each observer (L-BFGS-B, preconditioned, 40 screened random starts). Group inference is an observer-level bootstrap of the mean amplitude with a BCa correction, falling back to the percentile interval when the acceleration estimate is unstable. Trials are never pooled across observers. Models are compared by leave-one-block-out held-out log-likelihood on identical trial sets. A permutation null is built by shuffling previous-stimulus labels within block.
Exclusions, frozen
Trials: practice; reaction time under 200 ms or over 10 s; a within-observer log-RT outlier beyond 3.5 robust SD; stimulus shown more than 50 ms off nominal; window focus lost; the first three trials of a block, where the running-mean regressor does not yet exist. Observers: under 80% completion; over 10% focus loss; circular concentration of error below 0.35 or circular SD above 35°; viewport under 1024 × 700; mobile device; refresh slower than ~30 Hz. No criterion refers to the estimated effect. Version exclusion-policy-1.0.0.
Robustness
The primary estimate on the synthetic cohort is +2.56°. Across 45 comparable specifications — three nuisance-adjustment sets, with and without response history, three reaction-time cuts, both uncertainty strata, and four block subsets — 100% share its sign. Estimates within one uncertainty stratum are lower than the pooled estimate because each uses half the trials, which halves the information in the tuning-curve fit rather than the effect.
Fig. 1 Specification curve
SIMULATED DATA
group a_stim (°) · vertical rule: zero
results/robustness.parquet · run robustness-e756953-10Table view (45 rows)
| tuning | nuisance | response history | RT cut | stratum | blocks | estimate | 95% CI | p |
|---|---|---|---|---|---|---|---|---|
| dog | runmean | yes | 3.5 | all | all | +2.336 | +1.86 to +2.74 | < 0.001 |
| dog | full | yes | 2.5 | all | all | +2.455 | +2.01 to +2.90 | < 0.001 |
| dog | full | yes | 2.5 | all | early_half | +2.456 | +1.97 to +2.85 | < 0.001 |
| dog | full | yes | 5.0 | low | early_half | +2.468 | +1.94 to +2.95 | < 0.001 |
| dog | full | yes | 2.5 | low | drop_first | +2.478 | +2.00 to +3.02 | < 0.001 |
| dog | full | yes | 2.5 | all | drop_first | +2.478 | +2.02 to +2.93 | < 0.001 |
| dog | full | yes | 2.5 | low | early_half | +2.495 | +2.00 to +2.95 | < 0.001 |
| dog | full | yes | 3.5 | all | early_half | +2.502 | +2.03 to +2.95 | < 0.001 |
| dog | full | yes | 5.0 | low | late_half | +2.517 | +1.90 to +3.07 | < 0.001 |
| dog | full | yes | 2.5 | low | late_half | +2.525 | +1.91 to +3.09 | < 0.001 |
| dog | cardinal+runmean | yes | 3.5 | all | all | +2.537 | +2.05 to +2.94 | < 0.001 |
| dog | full | yes | 5.0 | all | early_half | +2.538 | +2.09 to +2.98 | < 0.001 |
| dog | full | yes | 3.5 | low | early_half | +2.542 | +2.01 to +3.00 | < 0.001 |
| dog | full | yes | 5.0 | low | all | +2.546 | +2.09 to +3.03 | < 0.001 |
| dog | full | yes | 5.0 | all | drop_first | +2.547 | +2.06 to +3.01 | < 0.001 |
| dog | full | yes | 2.5 | low | all | +2.547 | +2.06 to +3.02 | < 0.001 |
| dog | full | yes | 3.5 | all | all | +2.556 | +2.09 to +2.97 | < 0.001 |
| dog | full | yes | 5.0 | all | all | +2.558 | +2.11 to +3.02 | < 0.001 |
| dog | full | yes | 5.0 | low | drop_first | +2.558 | +2.12 to +3.10 | < 0.001 |
| dog | full | yes | 3.5 | low | drop_first | +2.559 | +2.12 to +3.09 | < 0.001 |
| dog | full | yes | 3.5 | all | drop_first | +2.579 | +2.13 to +3.02 | < 0.001 |
| dog | full | yes | 3.5 | low | all | +2.582 | +2.15 to +3.06 | < 0.001 |
| dog | full | yes | 2.5 | all | late_half | +2.587 | +2.05 to +3.13 | < 0.001 |
| dog | full | yes | 3.5 | low | late_half | +2.607 | +2.04 to +3.13 | < 0.001 |
| dog | full | yes | 3.5 | all | late_half | +2.637 | +2.12 to +3.13 | < 0.001 |
| dog | full | yes | 2.5 | high | all | +2.676 | +1.91 to +3.24 | < 0.001 |
| dog | full | yes | 5.0 | all | late_half | +2.683 | +2.17 to +3.17 | < 0.001 |
| dog | full | yes | 5.0 | high | all | +2.750 | +1.94 to +3.32 | < 0.001 |
| dog | full | yes | 5.0 | high | late_half | +2.765 | +1.87 to +3.55 | < 0.001 |
| dog | full | yes | 2.5 | high | early_half | +2.782 | +1.85 to +3.50 | < 0.001 |
| dog | full | yes | 2.5 | high | drop_first | +2.793 | +2.08 to +3.32 | < 0.001 |
| dog | full | yes | 3.5 | high | all | +2.839 | +2.27 to +3.39 | < 0.001 |
| dog | full | yes | 3.5 | high | late_half | +2.868 | +1.98 to +3.61 | < 0.001 |
| dog | cardinal | yes | 3.5 | all | all | +2.879 | +2.27 to +3.32 | < 0.001 |
| dog | none | yes | 3.5 | all | all | +2.890 | +2.46 to +3.31 | < 0.001 |
| dog | full | yes | 2.5 | high | late_half | +2.895 | +1.87 to +3.73 | < 0.001 |
| dog | cardinal+runmean | no | 3.5 | all | all | +2.904 | +2.37 to +3.31 | < 0.001 |
| dog | runmean | no | 3.5 | all | all | +2.906 | +2.44 to +3.31 | < 0.001 |
| dog | full | yes | 5.0 | high | drop_first | +2.924 | +2.08 to +3.49 | < 0.001 |
| dog | full | no | 3.5 | all | all | +2.942 | +2.49 to +3.38 | < 0.001 |
| dog | full | yes | 3.5 | high | drop_first | +3.025 | +2.30 to +3.60 | < 0.001 |
| dog | full | yes | 3.5 | high | early_half | +3.156 | +2.37 to +3.80 | < 0.001 |
| dog | full | yes | 5.0 | high | early_half | +3.190 | +2.40 to +3.85 | < 0.001 |
| dog | none | no | 3.5 | all | all | +3.243 | +2.62 to +3.68 | < 0.001 |
| dog | cardinal | no | 3.5 | all | all | +3.322 | +2.90 to +3.74 | < 0.001 |
Leaving any one observer out moves the group estimate by at most 0.10°; the result is not carried by a single observer. Estimated from the first 2, 3, 4, 6 of six blocks the amplitude is +2.75, +2.49, +2.56, +2.56° — stable from half a session on, with a between-observer SD of 1.52, 1.24, 1.30, 1.25°. Early versus late halves differ by +0.10° (exploratory).
What behaviour cannot settle
A bias tied to the previous stimulus rather than the previous response is consistent with a perceptual locus, but it is not proof of one: a decision process that stores the stimulus estimate and reuses it would produce the same pattern. The orthogonal-report manipulation separates stimulus from response history; it does not separate perception from decision. The manuscript says this in its limitations, and so does this page.