The board grammar already parses per-part marks ([N marks] / "Total for Question N is M marks"), but they were dropped building the first-pass template and the row mapper hardcoded max_marks=0 — so every born-digital paper came back with zero marks for a teacher to re-key by hand. Thread the parsed mark through: bands.py derive_bands now carries each part's `marks`, template.build passes it into part_bands, and _map_first_pass_to_rows reads it via a defensive _safe_marks (non-negative int; unknown/None -> 0, so image-only OCR — which has no marks yet — is unchanged). Containers still roll up from parts. Adds test_auto_map_surfaces_born_digital_part_marks. Co-Authored-By: Claude Opus 4.8 <[email protected]>
API Docling first-pass auto-map package
This package is the in-API home for the S5 exam-template/first-pass/v1 extraction pipeline copied from /home/kcar/dev/docling-exam-spike.
auto_map(pdf_bytes) returns the editable first-pass template.json shape consumed by downstream exam-marker mapping. The pipeline keeps margins as constraining inputs: document left/right and per-page top/bottom margins are derived before template assembly, then part/question bands and furniture/figure boxes are constrained through those margins.
dsync Redis env wiring
The OCR path uses dsync.py for docling-serve GPU locking, page cache, and retry. Configure with env-var names only:
DOCLING_SERVEDOCLING_REDIS_URLDOCLING_REDIS_HOSTDOCLING_REDIS_PORTDOCLING_REDIS_PASSWORDDOCLING_REDIS_DB
If Redis is unavailable, dsync falls back to no cache/lock and logs that state. Do not put secret values in this file.