Methods
A condensed version of the formal specification (docs/SPEC.md), written in pre-registration style before any human data. The full document, the hostile review and the ethics statement are in the repository.
Trial structure
fixation 500 ms → static scene U(1000, 2500) ms → linear change over 3 / 6 / 12 s → hold 2 s → endOne object changes along one property. Space (or the button) when a change is noticed, then click the object, then confidence 1–4. Non-response = right-censored at the end of hold. Practice: 4 trials with feedback. Main: 36 change + 6 catch trials, stratified 5–6 per change type, order, target, cells and directions randomised from a per-session seed.
| type | parameter | levels | direction |
|---|---|---|---|
| hue | hue rotation (°) | 20 / 40 / 80 | ± |
| brightness | HSL lightness Δ | 0.15 / 0.30 / 0.50 | ± (must fit without clamping) |
| size | scale factor | 1.25 / 1.5 / 2.0 | grow / shrink |
| position | displacement (u) | 40 / 80 / 160 | random bearing |
| disappearance | alpha 1 → a | 0.5 / 0.25 / 0 | — |
| appearance | alpha 0 → a | 0.5 / 0.75 / 1 | — |
| orientation | rotation (°) | 15 / 30 / 60 | ± |
Object substitution is not implemented: it requires image assets whose rights we do not hold. Normalised magnitude = magnitude ÷ the type's largest level (log₂ scale for size).
Procedural scenes with a semantic scale
1024 × 640 scene units; sky and ground; 6 or 18 non-overlapping objects from ten categories built from rectangles, circles and triangles. Both the browser (Canvas 2D) and the feature pipeline (Pillow) render the same JSON, and a golden-geometry test pins them to each other. Semantic importance is an a-priori ordinal scale — person 1.00, bird 0.85, car 0.75, sign 0.65, house 0.50, tree 0.35, lamp 0.30, bush 0.20, rock 0.15, box 0.10 — declared before data and confounded with shape complexity and size, which the models control for. It is not human-normed.
Features per stimulus from the rendered frames: spectral-residual saliency (mean in target mask; rank among objects), Michelson contrast against a surround annulus, RMS contrast, Sobel edge density, log bounding-box area, eccentricity, nearest-neighbour distance, change energy (mean |end − base| locally and globally), category, animacy, importance. No embeddings in v1.
What a browser can and cannot promise
Progress is a function of performance.now(), not frame count; a dropped frame degrades smoothness but never shifts the schedule. Per trial we store frame count, median and max inter-frame interval, dropped frames (> 1.5× the measured refresh period), longest gap, and visibility changes. Refresh rate is estimated from one second of frames before the first trial. Viewport, DPR and browser are recorded. Visual angle is only computed when the participant completes the credit-card calibration and reports a distance, and it is labelled an estimate.
Trial flags: timing_invalid, too_fast (< 200 ms), premature, mislocalized. Participant flags: incomplete (< 80 %), high_false_alarm (> 50 % of catch trials), inattentive, repeat_suspected, touch_device (desktop-only study), withdrawn. Flags exclude from the primary analysis; nothing is deleted; a sensitivity analysis uses everything.
Censoring first
- Kaplan–Meier by duration, eccentricity and type; log-rank tests.
- Cox PH with robust SEs clustered by participant; Schoenfeld PH test; a Cox model with the current magnitude as a time-varying covariate.
- Weibull and log-logistic AFT models; AIC comparison.
- Mixed-effects logistic (participant random intercept) and cluster-robust logistic for detection.
- Log-normal AFT on the magnitude-at-detection scale with misses censored at end magnitude.
- Prediction: baseline ⊂ low-level ⊂ combined, and semantic; logistic and gradient boosting; GroupKFold by participant and by stimulus; AUC, log-loss, Brier, calibration; Weibull AFT concordance for latency.
Primary outcome: hazard ratio per doubling of duration
| hr_per_doubling | 0.7 |
| alpha | 0.05 |
| power | 0.8 |
| var_log2_duration | 0.6666666666666666 |
| detection_rate | 0.55 |
| trials_per_participant | 36 |
| icc | 0.1 |
| exclusion_rate | 0.15 |
| events required (clustered) | 416.5 |
| participants required | 25 |
| scenario | N = 10 | N = 20 | N = 30 | N = 40 |
|---|---|---|---|---|
| default_generator | 100% (HR 0.229) | 100% (HR 0.225) | 100% (HR 0.226) | 100% (HR 0.22) |
| weak_speed_effect_b_rate_0 | 100% (HR 0.481) | 100% (HR 0.499) | 100% (HR 0.498) | 100% (HR 0.496) |
Default generator: b_rate=0.55 on log2(rate). Weak scenario: b_rate=0, so the only speed effect is that magnitude accrues more slowly; this is the conservative case. Schoenfeld events formula: (z_{1-a/2}+z_{1-b})^2 / (Var(x) (log HR)^2). Design effect 1+(m-1)ICC inflates required events for m trials per participant. Simulation power uses the synthetic generator whose speed effect is set by b_rate, not by HR=0.70; it validates the pipeline's sensitivity, not the human effect size.
Minimal risk, minimal data
Random participant identifiers double as withdrawal tokens; no name, email or IP is stored; the deployed site runs in demo mode (no server storage) unless a database and STUDY_OPEN=1 are configured. No IRB/REB approval exists or is implied. Formal collection waits for institutional requirements. Current data source on this site: SIMULATED.
Tidy tables: participants, sessions, trials, stimuli, questionnaire (Parquet + CSV in data/tidy/); raw events as JSON lines. Schema in docs/DATA_SCHEMA.md.