---
title: "Cognitive Warm-Up"
url: https://docs.growamal.com/en/guides/cognitive-warmup/
language: en
---

# 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.

> **Warning:** **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

> **Note:** **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](https://docs.growamal.com/en/guides/diagnostic-and-practice/): the training/practice flows the warm-up opens (never an assessment)
- [Task Delivery](https://docs.growamal.com/en/guides/task-delivery/): how items are selected and served in measurement sessions
- [Safety Rules](https://docs.growamal.com/en/how-it-works/safety/): the cross-cutting rules that include the G-ISO measurement-isolation boundary
