Cognitive Warm-Up
The Cognitive Warm-Up is a rule-based, fully deterministic activity a student plays for a fixed 60 seconds at the start of a training session. Its only purpose is to prime attention, inhibition control, pattern recognition, and working memory: the cognitive resources reading draws on. Nothing in the warm-up touches measurement or Arabic literacy content.
Training-only (R12 Q10, BREAKING). The warm-up is never a gateway before every reading session and is forbidden before any assessment (BOY/MOY/EOY/Screening/ORF/CBM/confirmatory). It runs only inside a TRAINING or INTERVENTION_PRACTICE session. createWarmupSession fail-closes — POST /api/warmup/sessions returns 422 for any other sessionType (session_scope=TRAINING_SESSION_ONLY, assessment_allowed=false). The unit is a fixed 60 seconds; the prior 3–5 minute multi-phase plan is collapsed.
What the warm-up is and is not
The warm-up is completely isolated from the measurement loop. It never computes or touches θ (the student’s ability estimate), never emits a mastery event, never mints XP, and never writes to any measurement or decision table. This is a hard architectural rule (V-5 + G-ISO). The warm-up is allowed in the student experience because it is rule-based and deterministic: it is the explicit carve-out from the “no generative AI in the student experience” anti-feature.
The student sees shapes, colors, paths, and patterns, never words, letters, or numbers. A separate lint (lint:no-llm-in-measurement) and an import-graph isolation test (test:isolation:warmup) verify at CI time that no code path from the warmup module can reach a measurement table.
The readiness telemetry produced (accuracy rate, response times, memory span) is stored in isolated warmup tables and used only as a readiness signal, never fed into the decision engine.
Ten schemas, thirty-two grade configs
The warmup catalog has two configuration layers:
| Layer | What it contains |
|---|---|
| 10 Tier-1 schemas (COG-01..COG-10) | Generic exercise blueprints validated against JSON Schema 2020-12: spatial match, color sequence, memory span, pattern completion, visual tracking, etc. |
| 32 per-grade Tier-2 configs (24 core configs across 8 schemas × G1-G4, plus 8 COG-05/06 final configs added by R12 Q10) | Per-grade bounds for difficulty, asset tags, and session-cycle durations: the values that make COG-03 feel right for a Grade 1 child vs a Grade 4 child |
Configs are read from the database at session creation; the engine is pure (no database access, no clock, no randomness source beyond the seeded PRNG). All ten schemas are now active. R12 Q10 closed FU-41: COG-05 (Matching) and COG-06 (Visual Tracking) final per-grade configs were delivered — both templates flip isActive=true and add 8 new grade configs (COG-G{1..4}-MATCHING / -VISUAL-TRACKING) carrying machine-readable element counts (numberOfVisualElements, pairCount, movingObjectsCount, targetCount, distractorCount, pathNodesCount, crossingCount, occlusionCount, speedChangeCount) and TPL-COG05-* / TPL-COG06-* template contracts. catalog-seed.ts now seeds 10 templates + 32 active grade configs (24 prior + 8 new).
Determinism and the seed
Every warmup session receives a seed integer at creation time. This seed is the only entropy source passed to the engine. The mulberry32 PRNG inside the engine is seeded with mixSeed(seed, sequenceIndex) so that:
- the same
(templateId, grade, difficulty, seed, sequenceIndex)always produces byte-identical output, and - a replay endpoint (
POST /api/admin/warmup/dry-run-replay) can assert this property on demand (V-6).
The clock and Math.random() are never called inside the engine.
Session lifecycle and resumability
| Step | Endpoint | What happens |
|---|---|---|
| Open | POST /api/warmup/sessions | Create session for (studentId, sessionType, grade); sessionType must be TRAINING | INTERVENTION_PRACTICE (R12 Q10 fail-closed — 422 otherwise); returns the first exercise instance and a stateToken |
| Record event | POST /api/warmup/sessions/{id}/events | Record started / submitted / advanced; the server auto-completes the session when the 60-second cap is reached |
| Resume | GET /api/warmup/sessions/{id}/resume | Return the persisted sequenceIndex exercise deterministically; the engine regenerates it from the same seed and no state is mutated (FR-WARM-6 / Q-SYNC-10) |
| Complete | POST /api/warmup/sessions/{id}/complete | Close with completed or skipped; write final readiness telemetry; signal cacheClear: true to the frontend |
| Reference reads | GET /api/warmup/templates/{templateId}, GET /api/warmup/grade-configs?grade= | Catalog reads for frontend rendering |
Browser-cache resilience
The stateToken in the session response is an HMAC token that the frontend stores in localStorage. If the student’s browser refreshes, the app switches, or the device locks, the frontend can call GET /api/warmup/sessions/{id}/resume with the stored token to regenerate the exact exercise at the current sequenceIndex without any round-trip state. This implements the Q-SYNC-10 browser-cache resilience requirement for all student-facing flows.
The 60-second cap
MAX_WARMUP_MS = 60_000 ms (60 seconds, R12 Q10). This limit is enforced server-side and silently; the student never sees a countdown. When the server detects the cap has been reached while processing a submitted event, it auto-advances the session to completed. It is the hard ceiling of the single non-linguistic unit — the prior warmup/core/reset/closure 5-minute multi-phase plan was collapsed into this one 60-second bound.
Skipping is always penalty-free
A skipped outcome on POST /api/warmup/sessions/{id}/complete writes no abandonment flag, triggers no retry requirement, and does not affect anything in the student’s measurement or gamification state. The session simply closes (FR-WARM-1).
No text in the exercise data
The engine’s no-text-guard module scans every rendered string in the exercise data payload. If any Arabic or Latin alphabet character, or any digit, appears, the request fails closed with a 500 rather than serving the contaminated payload. Exercise data carries asset ID references only; the actual SVG/image binaries are resolved by the frontend renderer, not the backend.
Append-only audit
warmup_session_event and warmup_telemetry rows are create-only. The session header (warmup_session) is mutable but with a history shadow. This follows the platform-wide append-only convention enforced by lint:no-update-on-audit-tables.
Permissions
The lifecycle routes (create / resume / events / complete) are student-self-served: a STUDENT holds USE_DIAGNOSTIC_ENGINE and may drive only its own warm-up (own-student scope pin — body.studentId === ctx.userId). Teacher and admin callers keep ClassTeacher / RUN_BACKOFFICE reach (e.g. a teacher-led or sync-orchestrated session rendering on the child’s screen). The reference reads (GET .../templates/{templateId}, GET .../grade-configs) remain teacher/admin-only. The dry-run-replay admin endpoint requires RUN_BACKOFFICE. All routes are tenant-scoped: cross-org reads return 404.
Related pages
- Diagnostic & Practice: the training/practice flows the warm-up opens (never an assessment)
- Task Delivery: how items are selected and served in measurement sessions
- Safety Rules: the cross-cutting rules that include the G-ISO measurement-isolation boundary