CBM & ORF Fluency
The CBM module (WP-CBM-BE) measures reading fluency and accuracy over time. It has two halves: the probe (a teacher-scored 60-second oral read) and the trend (repeated equal-difficulty probes plotted against an aim line, so a teacher can see early whether support is producing growth).
CBM scope is restricted to fluency and accuracy modalities only. Comprehension, vocabulary,
morphology, and syntax monitoring belong to Progress Monitoring,
not CBM. Sending a non-fluency modality to the CBM endpoints returns 400 cbm_scope_restricted_v2_3.
No speech recognition
The platform does not use automatic speech recognition (ASR) in Wave 1 or Wave 2 (V-5, Q16). The teacher listens to the student read and taps errors on a scoring grid. The server receives the error count, timing, and total words, and computes WCPM + accuracy. Audio recorded during a session is archive-only; it is never processed by any AI or speech system.
Supported CBM modalities
cbmType | Description |
|---|---|
ORF_CBM | Oral reading fluency: words correct per minute (WCPM) from the teacher’s 60-second timing |
ORF_ACCURACY | Oral reading accuracy: percentage of words read correctly |
WORD_LIST_ACCURACY | Accuracy on an isolated word list |
SENT_TEXT_ACCURACY | Accuracy on sentence or passage reading |
Any other cbmType value is rejected with 400.
The ORF probe flow
POST /api/orf/assessments/start: opens an assessment session for a student + passage.POST /api/orf/passages/:id/words: (optional) loads the word list for tap-error marking.POST /api/orf/assessments/:id/mark: records an error tap in real time.POST /api/orf/assessments/:id/stop: closes the 60-second window and triggers the CBM score computation + trend recompute.
The recompute is advisory-locked per (org, student, subSkillId) so concurrent requests from the
same teacher session cannot corrupt the time-series.
Aim line and baseline
The aim line activates only after 3 probes have been recorded. The baseline is the median of the first 3 probes. This protects against a single atypical session distorting the reference point (GSR-05: no single-point decision).
Once active, the aim line is defined by:
baseline: median of the 3 baseline probesgoalScore: the target fluency scoregoalSlope:(goalScore − baseline) / weeksToTarget
The 4-point trend rule and CbmTrendSignal
After 4 or more comparable probes exist, the engine evaluates the trend using the 4-point rule. The result is one of four signals:
| Signal | Meaning |
|---|---|
trend_above_goal | The student’s trajectory is above the aim line |
trend_below_goal | The student’s trajectory is below the aim line |
trend_mixed | Probes alternate above and below; inconclusive |
insufficient_points | Fewer than 4 comparable probes; cannot yet apply the rule |
null is returned while the baseline is still being collected (baselineState: collecting_baseline).
Grade-norm fail-safe
When no benchmark norm exists for a student’s grade (e.g., G1 or G4 where partner norms are pending), the probe still scores and the trend still computes on raw WCPM. The response carries:
riskLevel: null(shown asNot_Assessed, never asBelow)benchmarkMissingFlag: true
A missing norm is never treated as zero or as a risk indicator. No invented cut score is ever used.
Comparable and excluded probes
Not every probe is comparable. A probe is marked comparableFlag: false when it differs from the
majority on one condition, for example, an unadapted probe in a session where the student
normally receives adapted material. Excluded probes appear in the trend response’s
window.excludedProbeIds list but are retained in the time series for full audit.
Emit-only design
The CBM module emits a raw cbm_alert carrying the trendSignal, alertSeverity, and the
pinned benchmarkVersionUsed. It does not:
- Apply the fidelity gate (owned by the RTI module)
- Write a teacher-facing message
- Change
bundle_assignment.status
The RTI module reads readOpenAlerts() from this module and applies the gate + message. An acute
regression (alertSeverity: acute_regression) is emitted as a signal and never auto-fails
the plan.
The RTI input reader also reads the latest cbm_alert.trendSignal per student (org-scoped) and
maps the 4-value CbmTrendSignal into its alert pipeline:
CbmTrendSignal | RTI effect |
|---|---|
trend_below_goal | The “not progressing against the aim line” signal; feeds Layer B’s Targeted-Support gateway, so it can raise a Student_Alert |
insufficient_points | A sentinel contributor (cbm_insufficient_points); a halt guard, never an alert |
trend_above_goal | No effect (progressing) |
trend_mixed | No effect; trend_mixed is the conservative “not conclusive” verdict and never maps to the flat signal, to avoid over-alerting |
See RTI Decisions & Tiers for how that signal moves through the alert and tier-review flow.
Dismissing a CBM alert
POST /api/cbm/alerts/:id/dismiss requires a dismissalReasonCode from the 9-code
OverrideCodeCatalog. An optional contextFlagId from the closed dictionary may be included. No
free-text reason is ever accepted.
CAMELS tags
Each ORF passage is tagged with CAMELS Arabic feature tags (tagCode, arabicLabel). These tags
track error patterns by Arabic linguistic category. The CamelsCardDTO in the trend response shows
occurrence counts and error rates per tag. The full catalog is partner-owed; PHON_HAMZA is
inactive in Wave 1 (hamza is out of the current phase per partner confirmation 2026-06-19).
API endpoints (10)
ORF:
| Method | Path | Purpose |
|---|---|---|
POST | /api/orf/assessments/start | Open a new ORF session |
POST | /api/orf/passages/:id/words | Load word list for error tapping |
POST | /api/orf/assessments/:id/mark | Record a real-time error tap |
POST | /api/orf/assessments/:id/stop | Close the 60-second window + compute score |
CBM:
| Method | Path | Purpose |
|---|---|---|
POST | /api/cbm/probes | Submit a scored word-list or sentence/text accuracy probe |
GET | /api/cbm/trend/:studentId/:subSkillId | Full trend response (series + aim line + signal) |
GET | /api/cbm/alerts | List CBM alerts (filterable by status) |
POST | /api/cbm/alerts/:id/dismiss | Dismiss an alert with a reason code |
GET | /api/cbm/aim-lines | List aim lines for a student |
POST | /api/cbm/modifications | Record a modification marker (context flag + reason) |
All routes are teacher-scored (require VIEW_OWN_CLASSES / ClassTeacher), tenant-scoped, and have
no student-facing surface.
For full request/response shapes see the API Reference.
Related guides
- Progress Monitoring: non-fluency evidence recording
- RTI Decisions & Tiers: the RTI module that applies the fidelity gate to CBM signals
- Safety Rules: the GSR safety rules that govern both CBM and progress monitoring