fix(labs): say when a scanned PDF was read from its first pages only

A PDF longer than the pages a scan renders was read from its first ten
pages, and the cut was recorded only in the wide event. The person checking
the extracted rows had no way to know that values on later pages were never
read.

The rasterizer now returns the PDF's page count, the extract response
carries pageCoverage { read, total } when the cap applied, and the review
screen says how many of the pages were read.
This commit is contained in:
Marc-André Bombeck committed 2026-10-01 10:05:35 +02:00
1 parent 5caa15f4e1
commit 5f548d331f
16 files changed
+147 -3

No files matched your search

@@ -90,6 +90,9 @@ describe("rasterizePdf", () => {
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.images).toHaveLength(RASTER_MAX_PAGES);
// The page count travels with the result, so a caller can say the
// reading stopped short.
expect(result.pageCount).toBe(RASTER_MAX_PAGES + 4);
});
it("honours a caller maxPages bound (thumbnail path renders page 1 only)", async () => {
+11 -2
View File
@@ -74,7 +74,16 @@ export interface RasterImage {
* would not render" (`render-failed` — malformed / encrypted / zero pages).
*/
export type RasterResult =
| { ok: true; images: RasterImage[] }
| {
ok: true;
images: RasterImage[];
/**
* Pages in the PDF. Above `images.length` when the page cap cut the
* render short, which a caller showing the result has to say: the
* reading covers the first pages only.
*/
pageCount: number;
}
| { ok: false; reason: "unsupported" | "render-failed" };
// Minimal structural types for the slice of the pdfjs API this module uses. A
@@ -212,7 +221,7 @@ export async function rasterizePdf(
action: { name: "documents.rasterize.ok" },
meta: { pages: images.length, cappedFrom: doc.numPages },
});
return { ok: true, images };
return { ok: true, images, pageCount: doc.numPages };
} catch (err) {
annotate({
action: { name: "documents.rasterize.failed" },
+9
View File
@@ -85,6 +85,15 @@ const extractResponse = z
reportDate: z.string().nullable(),
providerType: z.string(),
rows: z.array(extractedRow),
pageCoverage: z
.object({
read: z.number().int().positive(),
total: z.number().int().positive(),
})
.optional()
.describe(
"Present only when a PDF ran past the pages a scan reads: the rows come from the first `read` of `total` pages. Absent when the whole document was read.",
),
})
.meta({
id: "OcrExtractResponse",
+6
View File
@@ -132,6 +132,12 @@ export interface OcrExtractResponseDto {
reportDate: string | null;
providerType: string;
rows: OcrExtractedRowDto[];
/**
* Present only when a PDF was longer than the pages the scan reads
* (`RASTER_MAX_PAGES`): the rows come from the first `read` of `total`
* pages, and the review screen says so.
*/
pageCoverage?: { read: number; total: number };
}
/**