Skip to content

fix(exam): keep each question whole across page breaks (#29) - #30

Merged
agiacalone merged 1 commit into
mainfrom
fix/exam-question-page-breaks
Jul 1, 2026
Merged

fix(exam): keep each question whole across page breaks (#29)#30
agiacalone merged 1 commit into
mainfrom
fix/exam-question-page-breaks

Conversation

@agiacalone

Copy link
Copy Markdown
Owner

Closes #29.

Problem

Exam questions frequently split across a page boundary — a stem stranded at the bottom of a page with its answer choices pushed to the next. Beyond readability, on a proctored paper exam this invites "I never saw part (d)" disputes.

Fix (template-only, preamble)

references/reference_exam.tex:

  • \qreserve reserve (default 5\baselineskip) at the top of every top-level question \item via an enumitem before-hook — if that much room isn't left, the whole question moves to the next page. Level-2 (choice) items are exempt (the enumerate,2 hook restores the plain \item), so only whole questions are space-reserved.
  • Stem↔choices glue via \@beginparpenalty=9999.
  • Widow/orphan damping (\clubpenalty/\widowpenalty = 10000).
  • \raggedbottom so pages run short rather than stretch to force-fit a question.

\qreserve is tunable per exam.

Why it's safe

  • Automatic — no per-question authoring change.
  • Parser-safe — the authored \item ... \textit{(N pts)} pattern is untouched, so exam_pack form-splitting (_QSTART_RE / _PTS_RE) and outline parsing are unaffected. No Python change.
  • No backfill — applies to exams authored from the template going forward; existing exam .tex are not modified (per maintainer direction).

Verification

Docs

  • docs/design/exam-tex-format.md — new "Page-break discipline — questions stay whole" section (mechanism, \qreserve tuning, parser-safety note, verification).
  • CHANGELOG.md — Unreleased entry.

🤖 Generated with Claude Code

https://claude.ai/code/session_011L61RXxaELhXPvbW2RBF5m

Exam questions frequently split across a page boundary — a stem stranded at
the bottom of a page with its answer choices pushed to the next. Beyond
readability, on a proctored paper exam this invites "I never saw part (d)"
disputes.

reference_exam.tex now, in the preamble only:
  - reserves \qreserve (default 5\baselineskip) at the top of every top-level
    question \item via an enumitem before-hook; level-2 (choice) items are
    exempt, so only whole questions are space-reserved
  - glues each stem to its choice list (\@beginparpenalty)
  - damps widows/orphans (\clubpenalty/\widowpenalty)
  - sets \raggedbottom so pages run short rather than force-fit a question

Automatic (no per-question authoring change) and parser-safe: the authored
"\item ... \textit{(N pts)}" pattern is untouched, so exam_pack form-splitting
(_QSTART_RE / _PTS_RE) and outline parsing are unaffected. No Python change.

\qreserve is tunable per exam. Applies to exams authored from the template
going forward; existing exam .tex are not backfilled.

Verification: a 40-question four-choice stress build splits 3 questions with
the pre-#29 template and 0 with this template, at the same page count. Full
suite green (405 passed).

Docs: docs/design/exam-tex-format.md (new "Page-break discipline" section),
CHANGELOG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011L61RXxaELhXPvbW2RBF5m
@agiacalone
agiacalone merged commit 5954626 into main Jul 1, 2026
4 checks passed
@agiacalone
agiacalone deleted the fix/exam-question-page-breaks branch July 1, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exam layout: keep each question together (prevent mid-question page breaks)

1 participant