mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 00:26:26 +00:00
feat(layout): measure compiled PDF layout instead of eyeballing it (#378)
* feat(layout): measure compiled PDF layout instead of eyeballing it /apply Step 5b asks for layout properties and executes none of them: they are checked by reading the rendered page, which is exactly how they get missed. The failure that motivates this is silent under every existing check. A moderncv \cventry renders as a tabular, so an entry is one unbreakable block; when it does not fit in the space left, the whole entry moves to the next page and leaves a hole behind. The document still compiles, still reports the expected page count, and still passes tools/verify_pdf.py. Observed in the wild at 273pt, roughly 19 blank lines, mid-page, on a CV whose visual read looked fine. tools/verify_layout.py reports per page where the text starts and stops, bottom whitespace as a share of page height, and the largest gap between lines, then exits 1 on a hole over 100pt, a non-final page ending more than 25% early, body text colliding with the page-number footer, a final page more than 35% empty, or an entry header or section heading stranded at a page break. Page count is deliberately not checked here - verify_pdf.py --pages already does that, and two implementations of one rule drift. Geometry comes from Poppler pdftotext -bbox, already a dependency; a missing Poppler exits 2 with "skipped:" rather than failing the run. Tests build synthetic Page/Line geometry, so the suite needs neither Poppler nor a LaTeX toolchain and runs on the existing 3.10-3.14 matrix. * fix(layout): survive Windows encoding and a pdftotext without -bbox Review found two failures on the repo's primary platform: subprocess.run(..., text=True) decoded pdftotext's UTF-8 output with the Windows ANSI codepage and crashed on the stock cv/main_example.pdf. It now passes encoding="utf-8" with errors="replace" at the call site, matching the fix verify_pdf.py already carries from #369. Git for Windows ships an xpdf-based pdftotext that shadows Poppler in a default PATH and has no -bbox flag; it exited 99, the CalledProcessError escaped, and the run ended in exit 1 - indistinguishable from a real layout problem, which would send /apply chasing a phantom hole. That now routes to the existing "skipped:" exit 2 path with a message naming the likely cause, covered by three tests on the extractor-failure path. Also from review: - .claude/settings.json and security_guards.py gain the verify_layout.py permission entries. apply.md Step 5b runs the tool on every /apply, so without them every run prompts. - The docstring and CHANGELOG no longer call Poppler a dependency verify_pdf.py relies on. Since #369 verify_pdf prefers pypdf and Poppler is the fallback; word bboxes have no pypdf equivalent, so this is the one step that still wants it, and that is now what the text says. - Docstring and apply.md state that the thresholds are calibrated for the stock moderncv and cover.cls geometry, and that the shipped example CV fails the thin-final-page rule by design. - largest_gap documents that it measures top-to-top, so a tall line inflates the gap by its own height - over-detection, the safe direction. - The test module imports via tools.verify_layout like test_verify_pdf.py instead of sys.path.insert. * fix(verify_layout): quote only the first stderr line in the skip message (#378) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013fqqLgQSnwgWkv98twQhHi --------- Co-authored-by: Mads Lorentzen <madslorentzen_17@hotmail.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
Mads Lorentzen
parent
8c81edc330
commit
cbd8a991ab
@@ -28,6 +28,23 @@ per-file diff commands.
|
||||
resolves confirmed rows to `no_response`, logs dated entries to `notes`, updates archive
|
||||
`outcome.md` files, and hands off to calibration when 3+ applications are resolved.
|
||||
|
||||
- **Mechanical layout verification for compiled PDFs** - `tools/verify_layout.py` measures
|
||||
what `/apply` Step 5b previously only eyeballed: per-page text extent, bottom whitespace,
|
||||
the largest internal vertical gap, footer collisions, and entry headers or section
|
||||
headings stranded at a page break. It exists for a failure that survives every existing
|
||||
check - a moderncv `\cventry` is an unbreakable `tabular`, so an entry that does not fit
|
||||
jumps to the next page and leaves a hole behind (observed at 273pt, roughly 19 blank
|
||||
lines) while the document still compiles, still reports the correct page count, and still
|
||||
passes `tools/verify_pdf.py`. Geometry comes from Poppler `pdftotext -bbox`; Poppler is
|
||||
optional repo-wide (since #369 `verify_pdf.py` prefers pypdf), and word bounding boxes
|
||||
have no pypdf equivalent, so this is the one step that still wants it. A missing Poppler
|
||||
- or the xpdf-based `pdftotext` Git for Windows puts ahead of it in PATH, which rejects
|
||||
`-bbox` - degrades to a `skipped:` exit 2 rather than reporting a phantom layout failure.
|
||||
Page count is deliberately left to `verify_pdf.py --pages` so that one rule keeps one
|
||||
implementation. Thresholds are calibrated for the stock moderncv and `cover.cls`
|
||||
geometry. Tests use synthetic page geometry, so they need neither Poppler nor a
|
||||
LaTeX toolchain.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`jobnet-search detail` no longer reports an externally hosted ad as not found** (#432) -
|
||||
|
||||
Reference in New Issue
Block a user