Problem
The flush-right role/degree date rail added in #425 (render-ats-pdf.ts drawText rightText) can be overdrawn by a long one-line experience header. The date is drawn at x = PAGE_WIDTH - MARGIN - dateWidth, but the left header text wraps against the full CONTENT_WIDTH, so a long flagship-shape header — Title · Company, Location · Team — whose first line extends past 558 - dateWidth renders on top of the date.
Surfaced by Samhit in review of PR #434 (thread on render-ats-pdf.ts:603).
Why the obvious fix regresses the round-trip invariant
The natural fix — reserve dateWidth + gap out of the first-line wrap budget so the header wraps before the date rail — breaks the parse → export → re-parse round-trip (corpus-roundtrip.test.ts). Two fixtures regress with role[0].company dropped:
unknown/student-projects-activities-singlecol.pdf
google-docs/google-docs-skia-proxy-additional-skills.pdf
Both carry a ·-delimited header that fits on one line at full width (visually overlapping the date) but the parser reads company off that single line. Forcing the header to wrap splits Title · Company across two lines and the company is lost on re-parse. Truncating the header (Samhit's alternative) alters the drawn text and regresses the round-trip the same way.
So the overlap is purely visual (the parser ignores glyph position — the round-trip was fine with the overlap), and every text-altering remedy trades a cosmetic bug for a correctness regression.
Durable fix (needs both sides)
- Render: keep the header on one line and auto-fit the font size (shrink the left text to clear the date rail, down to a floor) so no text is added/removed — round-trip-safe. Fall back to wrap only past the floor.
- Parser: teach the experience-header extractor to rejoin a wrapped
·-header so a wrapped export re-parses company correctly, unblocking the wrap path as a fallback.
Either alone is incomplete: (1) without (2) still wraps (and regresses) for very long headers past the shrink floor; (2) makes wrapping safe but auto-fit is the nicer visual.
Acceptance
- A long one-line
Title · Company, Location · Team header + flush-right date renders with no overlap in the exported PDF.
corpus-roundtrip.test.ts stays green — no role[0].* regressions.
- Add a render fixture/assert for the long-header + date-rail overlap case.
Problem
The flush-right role/degree date rail added in #425 (
render-ats-pdf.tsdrawTextrightText) can be overdrawn by a long one-line experience header. The date is drawn atx = PAGE_WIDTH - MARGIN - dateWidth, but the left header text wraps against the fullCONTENT_WIDTH, so a long flagship-shape header —Title · Company, Location · Team— whose first line extends past558 - dateWidthrenders on top of the date.Surfaced by Samhit in review of PR #434 (thread on
render-ats-pdf.ts:603).Why the obvious fix regresses the round-trip invariant
The natural fix — reserve
dateWidth + gapout of the first-line wrap budget so the header wraps before the date rail — breaks the parse → export → re-parse round-trip (corpus-roundtrip.test.ts). Two fixtures regress withrole[0].companydropped:unknown/student-projects-activities-singlecol.pdfgoogle-docs/google-docs-skia-proxy-additional-skills.pdfBoth carry a
·-delimited header that fits on one line at full width (visually overlapping the date) but the parser readscompanyoff that single line. Forcing the header to wrap splitsTitle · Companyacross two lines and the company is lost on re-parse. Truncating the header (Samhit's alternative) alters the drawn text and regresses the round-trip the same way.So the overlap is purely visual (the parser ignores glyph position — the round-trip was fine with the overlap), and every text-altering remedy trades a cosmetic bug for a correctness regression.
Durable fix (needs both sides)
·-header so a wrapped export re-parsescompanycorrectly, unblocking the wrap path as a fallback.Either alone is incomplete: (1) without (2) still wraps (and regresses) for very long headers past the shrink floor; (2) makes wrapping safe but auto-fit is the nicer visual.
Acceptance
Title · Company, Location · Teamheader + flush-right date renders with no overlap in the exported PDF.corpus-roundtrip.test.tsstays green — norole[0].*regressions.