From be10adc24b855625f0cf71f5fda9ff08e2f2cf78 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Wed, 14 Oct 2026 12:46:54 -0400 Subject: [PATCH] =?UTF-8?q?docs(agents):=20stats-build=20gotchas=20?= =?UTF-8?q?=E2=80=94=20end-of-day=20anchoring=20(2nd=20occurrence),=20dev-?= =?UTF-8?q?DB=20probe=20pollution,=20DeviceID=20is=20not=20always=20a=20de?= =?UTF-8?q?vice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 277cc9e9..bab1045e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,6 +78,22 @@ were name-only across ALL libraries. Fixed; do not regress. returned zero books until 0a7fbd6). Only real system query types (continue-reading etc.) route there; `query_type='filter'` is the schema DEFAULT on every user row, not a query type. +4. **End-of-day arithmetic**: anchor the END bound to the START of the + day, never to NOW(). `now.AddDate(0,0,1) − 1ns` carries this + instant's clock time into tomorrow — a range "ending today" + resolves tomorrow's calendar date and today's rows land in + yesterday's bucket (found twice now: analytics 1601548 and stats + 2026-10-14). Same trap, two deaths. +5. **Test binaries run against the LIVE dev DB**: hand-probes made in + psql during debugging (seed rows, fake sessions) will silently + pollute the next integration run — DELETE them when done (this + burned the first stats suite run: a stray 30-min probe row shipped + a phantom "185 minutes" failure). +6. **SaveProgressRequest.DeviceID is NOT always a device**: the + web/app progress paths have historically stuffed the USER id into + it (it only fed a broadcast label before stats). Anything that + dereferences it (reading_history device_id FK, device joins) must + probe DeviceExistsForUser first — stats capture does. ## Conventions (absorbed from the retired PROJECT_GUIDELINES.md — ## only the rules that still matched reality)