OK! Now let's plan the next few activities. Tomorrow and next Thursday we hav...
Do we use api.usingandunderstanding or quiz-api.usingandunderstanding in the CBTF?
In CBTF, students go through the quiz-api subdomain: quiz-api.usingandunderstanding.ai → api-service:3001. The quizzes.usingandunderstanding.ai web subdomain pairs with it.
The split exists because the edge nginx in front of those two hosts injects x-cbtf: true on inbound requests, which our cbtfDetection middleware (apps/api/src/middleware/cbtf.ts) uses to flip isCbtf=true and then enforce the route whitelist via cbtfRestriction. api.usingandunderstanding.ai doesn't get the header, so requests through it aren't treated as CBTF.
That's also why the cbtf e2e tests distinguish API_URL (regular) from QUIZ_API_URL (CBTF-flagged) — the latter exercises the restriction path.
Another TODO. It looks like when a student disconnects the count drops and then rebounds? Can we build in some hysteresis?
Two places to track this: an inline TODO next to getPresentStudentCount (matches the pattern from recent commits) and a backlog memory entry.
Logged:
- Inline TODO at
apps/api/src/socket.tsabovegetPresentStudentCount - Backlog memory
project_presence_hysteresis.md, indexed in MEMORY.md
Ready to commit alongside whatever else is pending, or separately.
Let's go ahead and address that TODO.
Implementing hysteresis. Need an override mechanism so the existing presence.spec.ts doesn't have to wait 30s, so I'll add an e2e endpoint to tune the window.
Now the e2e endpoint for tuning the window, and update the presence test.
Let me also add a dedicated hysteresis-behavior test before running everything.
Those TS errors are in unrelated spec files. Let me confirm my changes didn't add any, then run the presence tests.
Both tests pass. Let me stop the dev server.
API type-check clean. Summary of the hysteresis implementation:
apps/api/src/socket.ts:
- Module-level
HYSTERESIS_MS(default 30s, overridable viaPRESENCE_HYSTERESIS_MSenv var) - Per-room
Map<userId, lastSeenAt>tombstone store withmarkStudentRecentlyDisconnected/clearStudentRecentlyDisconnectedhelpers - Added
disconnectinghandler (fires beforesocket.roomsis cleared, unlikedisconnect) — records tombstones for every meeting room the socket was in room:joinnow clears the tombstone so returning students don't linger post-hysteresisroom:leavealso records a tombstone (explicit leave within hysteresis still holds)getPresentStudentCountunions live sockets with tombstones inside the window; prunes expired entries opportunistically- Exported
setPresenceHysteresisMs/getPresenceHysteresisMsfor test overrides
apps/api/src/routes/e2e.ts:
POST /api/e2e/presence/hysteresis{ ms: 0..60000 }— tunes the window for e2e tests (dynamic import avoids pulling socket deps into every e2e route)
testing/e2e/tests/presence.spec.ts:
- Existing dedupe test now sets hysteresis to 500ms so tab-close drops reflect within one SWR poll cycle
- New
hysteresis window holds the count steady through a brief disconnecttest — 8s window, verifies the count holds at 1 during the window and drops to 0 after it elapses afterEachrestores the 30s default so later tests aren't affected
Both presence tests pass (presence project: 7/7 green, 35.5s). Ready to commit.
Your task
First, run git status, git diff, and git log --oneline -10 to understand the current state.
Then add and commit all modified files with a descriptive message. Break the changes into multiple commits if appropriate. If there are untracked files, ask if they should be added or added to the appropriate .gitignore file. The user may also want to take over at this point, so provide an abort option as well. Always check changes for unnecessary debugging statements or logging that might have been accidentally included. Prompt the user if you find any, and offer to remove each one by one. Do not use interactive git staging (git add -p) as it does not work.
Committed 33270c5 on presence_hysteresis. Working tree clean.