# OCR and image reports

Image moderation analyzes the visual content first. When `processingOptions.image.ocrEnabled` is `true`, CalmLens also extracts text into a linked text child asset. The child's normal text moderation report contributes to the image's combined report.

Visual moderation can consider readable text, but does not guarantee that every word was read correctly. Enable OCR for screenshots, signs, placards, memes, and other images where written harassment, hate, or criminal instructions matter.

### When OCR is disabled

With `processingOptions.image.ocrEnabled` set to `false` (the default), the image is evaluated directly, including text the visual model can read. Each image qualifier has one presence score: it asks whether **any** qualifying content has that property. This corresponds to the meaning of text **Any**, rather than a separate check of every passage in the written content. The image report supplies `score` for presence and leaves `scopeScore` unavailable.

For clearly readable written content, the intended category boundaries and qualifier presence meaning align with normal text moderation. The scores need not match numerically: image recognition, layout, visual evidence and model uncertainty can change the result. **Only is unavailable for direct image analysis.** Image reports omit `scopeScore`; image qualifier presence cannot establish an **Only → Ignore** exception. Enable OCR for separate scope assessment of extracted text.

### When OCR is enabled

With `processingOptions.image.ocrEnabled` set to `true`, non-empty extracted text becomes a `plaintext-document` child asset with `parentId` set to the image's ID. It inherits the image's project, folder, visibility and processing options. The child goes through normal text moderation and the project's policy, with separate **Any** presence and **Only** scope checks. A historical threat followed by a separate current threat can therefore have high historical Any and low historical Only. Unrelated ordinary sentences do not invalidate Only; a qualifying current threat does.

Use `client.assets.listChildren({ assetId })` or the image's child-assets section in the portal to inspect the extracted text asset and its own report. Successful reclassification updates the same OCR child rather than adding another. Extracted text is retained on the child according to the normal retention and policy rules; its report remains available when content is removed. Purging the image also removes the child's retained OCR text unless a safety hold requires preservation.

The image and extracted-text results are then combined. The combined report retains text Only scope only when every relevant contributing result supplies scope evidence. Relevant visual content lacks that evidence, so OCR cannot establish an Only exception for that whole image.

For merged reports:

- Each parent keeps the higher evaluated score. Different content types remain separate overlapping qualifiers.
- For every qualifier, Any presence keeps the highest supported score across contributing modalities; Only scope uses the lowest supported scope score and is capped by Any. Category evidence below `0.1` does not contribute to qualifier merging. Missing scope stays unavailable and cannot establish Only. An image allowance cannot exempt a separate current threat in OCR text.
- A parent is `evaluated` if either report directly evaluated it, or `partial` if only a narrower signal was evaluated.
- The merged `report.score` is the highest evaluated category score.
- Text labels and notes take precedence when present, and `processedAt` uses the later report timestamp.
- If OCR returns no non-whitespace text, no text child is created and only the visual moderation report is used.
- If OCR extraction or moderation of the extracted text fails, image processing fails. CalmLens does not replace failed text moderation with an approved text result or a completed visual-only decision.

OCR extraction and moderation are separately metered: the OCR request increments OCR usage on the image, and non-empty extracted text incurs normal text-moderation tokens on the child. Combining its report with the image does not run or bill text moderation again.
