What happens
Re-running plugins/pomodoro-timer/test/render_readme_assets.py on Windows rewrites three of its four images even though the plugin has not changed:
hero.png identical pixels
options.png 20171 px differ, bbox (24, 26, 744, 564)
phases.png 11814 px differ, bbox (24, 26, 656, 396)
sizes.png 1847 px differ, bbox (24, 26, 88, 542)
hero.png is a bare panel and reproduces exactly. The three that drift are the labelled contact sheets, and the drift is entirely in the caption chrome.
Why
Both renderers pick the caption font from a list of host font paths and fall back if none match.
plugins/pomodoro-timer/test/render_readme_assets.py:
FONT_DIRS = ["/usr/share/fonts/truetype/dejavu", "/Library/Fonts",
"/usr/share/fonts/TTF"]
There is no Windows path in that list, so _font() falls through to ImageFont.load_default() — a completely different typeface — and every caption re-renders.
scripts/render_docs_assets.py has the same shape with the same consequence, just less visibly: its FONT_CANDIDATES does list Windows paths, so a Windows run silently picks Segoe UI where a Linux run picks DejaVu Sans. The captions still differ; nothing errors.
Why it matters
The pomodoro README states the images can be regenerated rather than edited, and several plugin READMEs I have added state that render_docs_assets.py --check verifies the committed images against a fresh render. Both claims hold on one machine and quietly fail across two. Anyone on a different OS who reruns either script produces a diff on images they did not change.
Nothing is failing today — no workflow in .github/workflows/ runs either renderer — so this is latent rather than breaking. But it does mean --check cannot be moved into CI as it stands: a Linux runner would report drift against every composite rendered on Windows, and vice versa.
Options
- Vendor the caption font (DejaVu Sans + Bold, ~1.4 MB) and resolve it from the repo. Fully deterministic; costs repo size.
- Use
ImageFont.load_default(size=...), which since Pillow 10.1 returns the Aileron face bundled with Pillow. No new files, deterministic for a given Pillow version, but no bold variant, so the caption hierarchy would need another cue.
- Leave it and document it — say plainly that the images are regenerated on Linux and that a Windows rerun will differ in the captions only.
Option 1 is the only one that makes --check safe to run in CI, which is the thing that would stop these images drifting from the display for real.
Scope
scripts/render_docs_assets.py, plugins/pomodoro-timer/test/render_readme_assets.py, and every composite currently committed under docs/assets/ and plugins/pomodoro-timer/assets/ (the panels in them are fine; only the captions would change).
What happens
Re-running
plugins/pomodoro-timer/test/render_readme_assets.pyon Windows rewrites three of its four images even though the plugin has not changed:hero.pngis a bare panel and reproduces exactly. The three that drift are the labelled contact sheets, and the drift is entirely in the caption chrome.Why
Both renderers pick the caption font from a list of host font paths and fall back if none match.
plugins/pomodoro-timer/test/render_readme_assets.py:There is no Windows path in that list, so
_font()falls through toImageFont.load_default()— a completely different typeface — and every caption re-renders.scripts/render_docs_assets.pyhas the same shape with the same consequence, just less visibly: itsFONT_CANDIDATESdoes list Windows paths, so a Windows run silently picks Segoe UI where a Linux run picks DejaVu Sans. The captions still differ; nothing errors.Why it matters
The pomodoro README states the images can be regenerated rather than edited, and several plugin READMEs I have added state that
render_docs_assets.py --checkverifies the committed images against a fresh render. Both claims hold on one machine and quietly fail across two. Anyone on a different OS who reruns either script produces a diff on images they did not change.Nothing is failing today — no workflow in
.github/workflows/runs either renderer — so this is latent rather than breaking. But it does mean--checkcannot be moved into CI as it stands: a Linux runner would report drift against every composite rendered on Windows, and vice versa.Options
ImageFont.load_default(size=...), which since Pillow 10.1 returns the Aileron face bundled with Pillow. No new files, deterministic for a given Pillow version, but no bold variant, so the caption hierarchy would need another cue.Option 1 is the only one that makes
--checksafe to run in CI, which is the thing that would stop these images drifting from the display for real.Scope
scripts/render_docs_assets.py,plugins/pomodoro-timer/test/render_readme_assets.py, and every composite currently committed underdocs/assets/andplugins/pomodoro-timer/assets/(the panels in them are fine; only the captions would change).