Consecutive-run (island) detection keys on t minus a ROW_NUMBER ordered by t: within a run both climb together so the difference is constant, and a gap shifts it. Grouping by that difference separates runs that grouping by the value alone would merge.
SELECT COUNT(*) AS len FROM reads WHERE gate = 'in' ;
SELECT island, COUNT(*) AS len FROM ( SELECT t - ROW_NUMBER() OVER ( ORDER BY t ) AS island FROM reads WHERE gate = 'in' ) GROUP BY island ORDER BY island;
Counting 'in' rows says one run of 3, but the gate reopened at t=4 after an 'out' — the row_number-difference key splits it into the two real runs.
Compute island = t - ROW_NUMBER() OVER (ORDER BY t) over the matching rows, then GROUP BY that key to get one group per consecutive run.
day - ROW_NUMBER() OVER (PARTITION BY usr ORDER BY day)