---
title: "CBM & ORF Fluency"
url: https://docs.growamal.com/en/guides/cbm-orf-fluency/
language: en
---

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

> **Warning:** CBM scope is restricted to fluency and accuracy modalities **only**. Comprehension, vocabulary,
> morphology, and syntax monitoring belong to [Progress Monitoring](https://docs.growamal.com/en/guides/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_WCPM` | 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.

> **Warning:** **R12 current-phase scope (2026-06-22):** the four-value storage enum above still exists, but the
> only **CBM-eligible** modality in the current phase is **connected-text ORF** (`ORF_TEXT_READING_ONLY`).
> Per the 80-skill taxonomy update, `DWR-A03`/`DWR-A05` are no longer `cbm_eligible`. Treat connected-text
> ORF as the active current-phase CBM modality; the isolated-word-list and sentence/text-accuracy rows
> are retained in the enum but are not the current-phase CBM scope.

## The ORF probe flow

1. `POST /api/orf/assessments/start`: opens an assessment session for a student + passage.
2. `GET /api/orf/passages/:id/words`: (optional) loads the word list for tap-error marking.
3. `POST /api/orf/assessments/:id/mark`: records an error tap in real time.
4. `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 probes
- `goalScore`: the target fluency score
- `goalSlope`: `(goalScore − baseline) / weeksToTarget`

## The 3-point trend rule and CbmTrendSignal

After **3 or more comparable probes** exist, the engine evaluates the trend using the
3-comparable-point rule. The floor is **config-driven** (default 3, read version-pinned from
`growth_trend_rule.minimumComparablePointsForStrongTrend`; V-6). R12 (2026-06-22, Mohammad
override) lowered the trend floor to 3 comparable points, **superseding the v5 4-point lock** —
a reliable trend now needs 3 comparable points, not 4. 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 3 comparable probes (below the config-driven floor); cannot yet apply the rule (≡ `do_not_decide_yet`) |

`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 as `Not_Assessed`, never as `Below`)
- `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](https://docs.growamal.com/en/guides/rti-decisions/) 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 (11)

**ORF:**

| Method | Path | Purpose |
|---|---|---|
| `GET` | `/api/orf/passages` | List available reading passages (filterable by grade and sub-skill) |
| `POST` | `/api/orf/assessments/start` | Open a new ORF session |
| `GET` | `/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 |
| `POST` | `/api/cbm/aim-lines` | Set or adjust the aim-line goal (baseline + goalScore + weeksToTarget); the current aim line is returned inline in the trend response under the `aimLine` key |
| `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](https://docs.growamal.com/en/api-reference/).

## Related guides

- [Progress Monitoring](https://docs.growamal.com/en/guides/progress-monitoring/): non-fluency evidence recording
- [RTI Decisions & Tiers](https://docs.growamal.com/en/guides/rti-decisions/): the RTI module that applies the fidelity gate to CBM signals
- [Safety Rules](https://docs.growamal.com/en/how-it-works/safety/): the GSR safety rules that govern both CBM and progress monitoring
