Regenerating the README Eval Screenshots
July 10, 2026 · View on GitHub
The two evaluation cards in the top-level README.md live in images/:
images/as-we-may-think.png: Vannevar Bush, “As We May Think” (The Atlantic, 1945)images/apple-media-services-terms.png: Apple Media Services Terms
The scores for each card are committed as .eval.md files in
evals/readme-cards/, and the PNGs are rendered from
those. Scoring (an LLM call) and rendering (look-and-feel) are deliberately separate:
- Change the look and feel (design tokens,
print.css, the card template)? Run Flow A: Re-Render only. No API call, no score change; the cards just pick up the new styling. This is the common case. - Want fresh scores? Run Flow B: Re-Score to regenerate the committed
.eval.md, then run Flow A to re-render.
This is a development workflow, not part of the shipped package: it shells out to a
locally installed Chrome plus pdftoppm and magick, so it adds no Python or JS
dependencies to pprose.
Prerequisites
-
Project dependencies installed with
make installfrom the repository root. -
Google Chrome (headless HTML → PDF): both flows.
-
Poppler (
pdftoppm) and ImageMagick (magick) for PDF → trimmed PNG, both flows:brew install poppler imagemagick -
An
ANTHROPIC_API_KEYin.env(or the environment): Flow B only (scoring).
Flow A: Re-Render (Look-and-Feel Changes)
Rebuilds the PNGs from the committed evals/readme-cards/*.eval.md with the current
styles. No scoring, so the numbers on the cards do not change.
Run this after editing the design system, print.css, or the card template (regenerate
the design tokens first with make generate if you changed design-system.yaml).
#!/usr/bin/env bash
set -euo pipefail
REPO="$(git rev-parse --show-toplevel)"
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
WORK="$(mktemp -d)"
cd "$REPO"
export UV_NO_CONFIG=1 UV_LOCKED=1
export UV_BUILD_CONSTRAINT="$REPO/tools/pprose/build-constraints.txt"
for stem in as-we-may-think apple-media-services-terms; do
uv run --no-sync --project tools/pprose pprose render "evals/readme-cards/$stem.eval.md" \
-o "$WORK/$stem.html"
"$CHROME" --headless=new --disable-gpu --no-pdf-header-footer \
--virtual-time-budget=3000 --print-to-pdf="$WORK/$stem.pdf" "file://$WORK/$stem.html"
pdftoppm -png -r 200 -f 1 -l 1 "$WORK/$stem.pdf" "$WORK/$stem-page"
magick "$WORK/$stem-page-1.png" -trim +repage "images/$stem.png"
echo "rendered images/$stem.png"
done
The print stylesheet (print.css) forces the light theme and hides the theme toggle and hover panels, so the printed page is clean.
Flow B: Re-Score (Refresh the Numbers)
Regenerates the committed .eval.md from the source documents in
example-texts/, then you run Flow A to re-render.
Scores depend on the model and vary slightly between runs, so re-scoring will shift the
numbers, update the README caption to match.
#!/usr/bin/env bash
set -euo pipefail
REPO="$(git rev-parse --show-toplevel)"
cd "$REPO"
if [[ -f .env ]]; then
set -a; source .env; set +a # ANTHROPIC_API_KEY
fi
export UV_NO_CONFIG=1 UV_LOCKED=1
export UV_BUILD_CONSTRAINT="$REPO/tools/pprose/build-constraints.txt"
PP() { uv run --no-sync --project tools/pprose pprose "$@"; }
# label|source-path|stem
DOCS=(
"As We May Think|example-texts/as-we-may-think.md|as-we-may-think"
"Apple Media Services Terms|example-texts/apple-media-services-terms.md|apple-media-services-terms"
)
for entry in "${DOCS[@]}"; do
IFS='|' read -r label src stem <<<"$entry"
PP report from-metrics "$src" --label "$label" \
--evaluator "Claude Opus 4.8 (pprose demo)" --method subagent \
--out "evals/readme-cards/$stem.eval.md"
PP score "evals/readme-cards/$stem.eval.md" --model opus --allow-misaligned \
--evaluator "Claude Opus 4.8 (pprose demo)"
done
# Now run Flow A to re-render the PNGs from the refreshed .eval.md.
--model opus selects the current flagship Anthropic Claude Opus alias.
pprose score occasionally returns a sub-5 score without a matching rule citation,
which trips the alignment check; --allow-misaligned writes the report anyway (fine for
a demo; the scores are the model’s real assessment).
Output Interpretation
- The captured PNGs are about 1100 × 1635 px at 200 dpi.
To regenerate at a different resolution, change
-r 200inpdftoppm. - The interactive HTML (with theme toggle and hover detail panels) is the on-screen experience; the print path is only for static snapshots.
- The cards show per-group means and an
Assessed: N/20count, not a single cross-dimension average:overall_meanis reductive and not comparable across genres (N/A dimensions drop out of any average, so a document that doesn’t engage many dimensions can outscore a richer one). The Apple terms, for instance, leave several Reasoning and Judgment dimensions N/A: a contract states terms rather than arguing or weighing them. See the “Scores are reductive” note in practical-prose-rubric.md.