# CV pagination-fidelity repair checkpoint Source: `046dc304aa68d67e15a019057f9bdec0c89bf475`. This checkpoint repairs only the live document's fragmentation and measurement lifecycle. No P5-09 UI redesign, template/export change, revision change, AI workflow, responsive redesign or B07. The final decision and executed baseline are recorded below. The original [16-fixture evidence](../p5-09-readiness/README.md#measured-corpus-and-results) remains unchanged; its six failures are not removed or reclassified as passes. ## Root cause and per-fixture diagnosis The former screen preview added padding to a tall continuous `.page`, estimated keep-together gaps for selected blocks and cropped every physical page by a vertical transform. It explicitly skipped blocks taller than the usable page. That meant flowing entries/list items received neither native line fragmentation nor repeated page margins. Padding an entire section could not implement `widows`, `orphans`, keep-with-next or margin treatment at a fragment boundary. Font readiness was also absent from the parent page-count callback. All six failures share this mechanism. The sixth is not stale data, reordered DOM or hidden content: it reproduces offline from the identical saved HTML, with stable fonts and no API writes. Its E03/B07 markers appeared on preview page 1 instead of PDF page 2; later S09/R09/R10 positions differed by approximately 21 mm despite equal overall counts. | Original failing fixture | Original divergence | Repair proof | |---|---|---| | long-en-minimal | 3 vs 4 pages; E05/B13/B14 stayed on page 2 instead of 3; later vertical error up to 72.60 mm | Native flow fragmentation, repeated usable height and unchanged print keep rules | | long-nb-code | 3 vs 4 pages; E03/B07 wrongly on page 1; accumulated subsequent-page displacement | Same native flow; monospaced headings and Segoe body metrics preserved | | compact-8mm-letter | 3 vs 4 pages; compact flow and page-boundary splitting | Native fragmentation **and print fragmentainer pixel rounding**, independently demonstrated with a native ruler | | roomy-28mm-nb | 4 vs 5 pages; large repeated safe area absent from long flow; displacement over 200 mm | Renderer margin 33.04 mm retained on every fragment | | long-sidebar-nb | 4 vs 5 pages; main/sidebar fragmentation and subsequent-page offsets diverged | Existing grid/column layout fragments natively; no sidebar/template rewrite | | unbreakable-and-boundary | 4 vs 4 pages, but markers assigned to wrong pages and custom-section anchors displaced | Same source and native keep/flow rules; focused marker-membership regression plus positional oracle | An offline probe reusing actual server HTML and native PDFs corrected all counts and 15/16 positional results with browser column fragmentation. Compact Letter still misplaced later anchors by roughly 10.9 mm when given a fractional fragmentainer height. Rounding each margin separately produced a different wrong result: the Languages section incorrectly fit on page 3. Neither workaround was shipped. A separate Chromium CLI **1px native ruler**, with the same page and margin rules, establishes the correct physical rounding: | Page / effective margin | Calculated usable CSS height | Native first-page 1px rows | Preview fragmentainer | |---|---:|---:|---:| | A4 / 16 mm | 1001.574803 px | 1002 | 1002 px | | Letter / 6.56 mm | 1006.412598 px | 1007 | 1007 px | | A4 / 33.04 mm | 872.768504 px | 873 | 873 px | The repair uses `ceil(physicalHeight − 2 × effectiveMarginPx)`, matching these measured print fragmentainers. It is at most one CSS pixel (0.2646 mm) of platform quantization, not an arbitrary content buffer, a changed margin or a widened tolerance. ## Renderer and geometry contract **Generated PDF remains authoritative.** `ThemedCvRenderer`, `PlaywrightCvPdfExporter`, their CSS/CLI flags, admission and submitted/frozen content are unchanged in this checkpoint. `cvPreview.ts` replaces the former estimation function with native CSS column fragmentation. Each column has one page's physical width and usable height; selecting a page translates horizontally by that width inside the existing physical-page iframe. The application still presents the same vertically stacked page previews, zoom, scrolling and named keyboard region. - Physical width/height come from the actual renderer's `.page` CSS. The existing selected-page height is only a fallback. A4 and Letter keep their existing dimensions. - Effective top/bottom margin comes from the existing `--cv-page-margin` CSS token, including template/default margin and density. The duplicate frontend density/margin calculation is removed. - Existing `@media print` declarations are reused in the screen fragmentainer. Header/main/sidebar padding, min-height, borders, fonts and content remain renderer-owned. - Existing computed `avoid-page` break decisions are applied as `avoid-column` in the preview. Automatic flow, line height, `widows`/`orphans`, list/paragraph/section spacing and native element splitting stay with the browser engine. - Print rules supply no separate CV footer/header space. No browser chrome, PDF margin, PDF pagination, font or document setting changes. - The hidden measurement iframe loses its default border, so its content viewport agrees with visible borderless document frames. This is a measurement correction, not editor layout work. The original failures had matching horizontal anchors and font sizes (within approximately 0.006 pt) while vertical/page membership diverged. The retained CSS confirms the same family/fallback chain, weight, line-height, letter spacing, paragraph/list gaps, entry/section gaps, box sizing and template borders. There is no font-specific shrink, substituted document font, generic safety padding or forced one-page fit. ## Measurement lifecycle and fonts Each document waits for `document.fonts.ready` and image decode, applies the existing print decisions, then waits for two animation frames to settle layout. It publishes a single `cv-preview-ready` event and page/geometry metadata. The parent consumes that settled measurement, rejects an obsolete frame/document callback and does not count the previous continuous scroll height. No arbitrary sleep or continuous resize/mutation re-pagination loop is added. The fidelity fixture waits for this explicit readiness signal, including standalone document captures. Horizontal columns are normalized into the **same physical-page coordinate system** used by the unchanged PDF oracle: column index from x; local x within that page; local y plus page index × physical height. Raw x/y and page membership are retained. This representation change does not change tolerance, expected marker membership or the PDF data. Font families/fallbacks remain those documented in the original readiness record. Local preview/CLI use the same Chromium family; native PDFs retain their embedded selected/substituted font subsets. No font files are added, exposed or redistributed. Production Debian/font substitution and other browser engines still require deployment qualification; local evidence is not production font certification. New layout readiness waits do not claim to supply missing fonts. Final evidence integrity checks confirm **16/16 server HTML inputs are byte-identical to the original readiness corpus**, **16/16 PDFs have identical extracted page text**, and all PDFs retain the same normalized embedded font names and page counts. PDF file-byte identity is not asserted because generated metadata can vary. All retained screenshot manifest hashes resolve correctly; no authentication state or raw browser traces are committed. ## Fidelity acceptance and evidence The original numerical oracle is unchanged: page size ±0.5 mm; exact page count/marker membership; anchor position ±2 mm; font size ±0.5 pt; extractable RGB component ±1/255; repeated vertical safe area ±1 mm; no blank pages, missing/extra markers or hidden-interest leakage. All original 16 fixtures remain. Full wrapped-line/photo/all-font/all-template-long-form qualification is not implied by a numerical pass. Both the repaired real-editor/native-export focused run and the subsequent complete browser run measured **16/16 passing**, exit 0, at the original tolerances. The final [numerical results](evidence/fidelity/fidelity-results.json), [source measurements](evidence/fidelity/measurements.json) and synthetic source HTML/native PDFs/page comparisons are retained under `evidence/fidelity/`. | Fixture | Before preview pages | PDF pages | After preview pages | Measured result | |---|---:|---:|---:|---| | default-modern | 1 | 1 | 1 | Pass | | default-minimal | 1 | 1 | 1 | Pass | | default-executive | 1 | 1 | 1 | Pass | | default-technical | 1 | 1 | 1 | Pass | | default-ats-classic | 1 | 1 | 1 | Pass | | default-nordic | 1 | 1 | 1 | Pass | | default-elegant | 1 | 1 | 1 | Pass | | default-creative | 1 | 1 | 1 | Pass | | default-code | 1 | 1 | 1 | Pass | | long-en-minimal | 3 | 4 | 4 | Pass | | long-nb-code | 3 | 4 | 4 | Pass | | compact-8mm-letter | 3 | 4 | 4 | Pass | | roomy-28mm-nb | 4 | 5 | 5 | Pass | | grid-and-bubbles | 1 | 1 | 1 | Pass | | long-sidebar-nb | 4 | 5 | 5 | Pass | | unbreakable-and-boundary | 4 | 4 | 4 | Pass, including corrected marker placement | Total: **31 → 36 preview pages**, matching the unchanged **36 PDF pages**. Final-run maxima: x **0.0000037 mm**, y **1.493055 mm**, font **0.005026 pt**, extractable RGB component **0.0000451**. No count, marker membership, hidden-content, blank-page or vertical-safe-area failure is waived. These values do not claim pixel identity or exhaustive complete wrapped-line qualification. Rendered comparisons show corrected continuation/bullet/section placement in all six former failures, including the compact Letter Languages section on page 4. Native short-sidebar surface height now agrees with print instead of being stretched to the screen page height. Small rasterization/glyph-box differences remain within the declared contract. The PDF's existing long-entry keep rules can leave an entry heading plus company at the bottom of a page with bullets continuing next page (visible in the roomy fixture). Preview now represents that faithfully. Improving that native print-quality policy would change output semantics and is deliberately deferred; it is not hidden by a preview-only workaround. ## Preservation and changed owners | PRES IDs | Invariant | Evidence | |---|---|---| | C06, E08/E09 | Same editor/preview panes, zoom/scroll, accessible name, focus entry/exit and responsive visibility | Inherited four P4-03 EN/NB × light/dark keyboard cases; rendered editor evidence | | C07/C08/C09 | Override/source, hidden/order, template/settings and physical document geometry | All 16 unchanged source/settings fixtures; exact marker/content/page comparisons | | C10, C01/C02 | Revision protection, canonical source separation, undo/redo | Existing 941 backend / editor conflict/history cases and native stale-write proof; owners untouched | | C12 | Native PDF truth/content and admission | Unchanged native export endpoint/renderer; existing PDF and security suites | | W05/W07, E05 | Selected versus frozen submitted CV and account ownership | Ordinary P2-D01/native package proof and account-isolation cases retained | | C11 | Grounded AI review/accept/reject | Existing regressions retained; AI owners untouched | Production files: new small `src/cvPreview.ts` isolates the existing document-preview owner for native behavioural testing; `CvBuilderEditor.tsx` consumes it and its settled measurements. No editor-frame/navigation/control redesign. Test files: `e2e/cv-pagination.spec.ts` adds two behaviours (six original failure memberships; delayed-image readiness), and `e2e/cv-readiness.spec.ts` records the new coordinate representation/readiness/performance without weakening the existing oracle. ## Performance An offline benchmark uses the same saved HTML and Chromium, three runs of every fixture per implementation: **48 samples each**. Document setup through settled font/layout frames: median **48.75 → 52.28 ms**, p95 **59.19 → 62.84 ms**. This small local change is not production latency or a universal performance guarantee; scheduling/frame waits are included. The [benchmark measurements](evidence/performance.json) preserve each sample. The [native ruler results](evidence/native-ruler/results.json) retain the independent page-capacity observation, with its three synthetic HTML inputs and generated PDFs. These are local probes, not new runtime dependencies or CI services. The existing 300 ms preview debounce/API boundary remains. Pagination runs once per newly rendered document. Break-style reads are collected before writes to avoid an unnecessary alternating read/write loop. The existing architecture still loads the document into a measurement frame and each visible page frame; corrected page counts naturally add one frame to five formerly undercounted fixtures. Long-document DOM duplication remains an existing scaling limitation, not a newly introduced PDF request on each edit. No premature caching/virtualization platform is introduced. ## Visual and accessibility review All **36** final comparison pages were reviewed as six contact-sheet overviews; selected template, continuation, final-page and boundary comparisons were also inspected at full resolution. This review finds matching document sequence, continued text, margins and sidebar fragment surfaces, including Languages on compact Letter page 4 and the corrected custom section on boundary page 4. The [visual manifest](evidence/visual-manifest.json) records hashes and review method; unreviewed standalone raster files are not labelled as individually inspected. Source HTML/native PDF/preview/PDF raster/comparison pairs remain available for every fixture. The existing keyboard suite exercises EN/Bokmål × light/dark, named editor/preview regions, preview entry/exit, focus retention, zoom/scroll and phone pane visibility. It does not certify human screen-reader speech. Mounted-page visual and axe results from the final run are recorded below; incomplete findings remain incomplete. No editor/preview controls, layout, routes, reduced-motion rules or focus owners are redesigned. All twelve retained mounted-editor screenshots were individually reviewed: one-page, multipage end and 390 px phone preview, each in EN/Bokmål × light/dark. Examples: [light/English desktop](evidence/one-page-light-en.png), [dark/Bokmål desktop](evidence/multipage-end-dark-nb.png), [light/Bokmål phone](evidence/preview-390-light-nb.png), [dark/English phone](evidence/preview-390-dark-en.png). Preview focus remains visible and document scrolling/page gaps remain usable. The deliberately unchanged fit-to-width phone rendering can have small document text; interaction/presentation improvements belong to later CV slices. The [sixteen scoped axe scans](evidence/accessibility-summary.json) have **zero violations**, but retain **32 `aria-prohibited-attr` incomplete nodes and 252 `color-contrast` incomplete nodes**, each rule appearing in all 16 scans. Those are not passes or human acceptance. Earlier scans had fewer incomplete contrast nodes; the retained multipage DOM/visibility changes alter scanned node population, not proof of contrast compliance. Template-card descriptions and their localisation/disabled appearance remain existing controls debt, not part of this repair. ## Final validation and decision Executed against the final code/test candidate on 2026-10-07. Commands use the repository-required `rtk` prefix (`rtk proxy` for unfiltered runners); below, prefixes are omitted for readability. Root commands run in the checkout, `npm.cmd` commands in `job-tracker-ui`. Browser runs set `DOTNET_ROOT=C:/Users/Connor/.dotnet` and `DOTNET_HOST_PATH=C:/Users/Connor/.dotnet/dotnet.exe`. Complete browser acquisition uses the production export with `PLAYWRIGHT_STATIC_EXPORT=true`, `PLAYWRIGHT_PREBUILT_EXPORT=true`, `CV_FIDELITY_OUTPUT=../.artifacts/p5-09-pagination/final`, and `PLAYWRIGHT_JSON_OUTPUT_NAME=../.artifacts/p5-09-pagination/final-browser.json`. Specialized suites run sequentially because they share the disposable API port. | Exact command / check | Final result | |---|---| | `C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj -c Release --no-restore --logger 'console;verbosity=minimal'` | **941/941 passed**, zero failures/skips; unchanged count. Includes revision/atomic writes, source/override, frozen package/ownership, import/CSV/PDF/security regressions | | `npm.cmd test -- --runInBand --silent --json --outputFile=../.artifacts/p5-09-pagination-jest.json` | **422/422 passed**, 80 suites; unchanged count. Editor history/conflict/undo/recovery owners retained | | `npm.cmd run test:e2e -- --output=../.artifacts/p5-09-pagination/final-browser --reporter=line,json` | **98/98 actual passes**, 15.9 minutes, zero failures/skips/flaky/expected-failure cases; [safe case summary](evidence/browser-summary.json) | | `npm.cmd run typecheck` / `npm.cmd run lint` | Both passed; no suppression or CI/dependency change | | `npm.cmd exec tsc -- --project ../.artifacts/p5-09-readiness-e2e-tsconfig.json --noEmit --incremental false` | All permanent browser fixtures type-check; ignored local config extends existing project types | | `npm.cmd run build` with `NEXT_PUBLIC_API_BASE_URL=http://localhost:5302/api` | Frontend production static export passed | | `C:/Users/Connor/.dotnet/dotnet.exe build JobTrackerApi/JobTrackerApi.csproj -c Release --no-restore -warnaserror` | API Release passed, zero warnings/errors | | `npm.cmd run test:rate-limits -- --reporter=line` | **9/9 passed**, trusted principal/IP/session and forwarding-spoof boundaries retained | | `npm.cmd exec playwright test -- --config=playwright.ingress.config.ts --output=../.artifacts/p5-09-pagination/ingress --reporter=line` | **6/6 passed**; local application behavior, not deployed production proof | | `npm.cmd run test:pdf-admission -- --output=../.artifacts/p5-09-pagination/pdf-admission --reporter=line` | **1/1 passed**, actual cross-route capacity/recovery | | `python scripts/test-ingress.py` | **3/3 passed**, configuration/Compose checks | | `python scripts/test-supply-chain.py` / `python scripts/test-ollama-evaluation.py` / `node browser-extension/tests/capture-url.test.mjs` | **3 / 5 / 3 passed**, local fixtures, no provider certification | | Bundled Python `-X utf8 scripts/verify-cv-fidelity.py .artifacts/p5-09-pagination/final` | **16/16 pass, exit 0**; unchanged oracle/tolerances; all 36 pages retained | | `python scripts/supply-chain.py scan-secrets` | Passed against the staged/tracked candidate; no high-confidence credential patterns | | `git diff --check` / `git diff --cached --check` | Passed | | `python .artifacts/p4-04-check-doc-links.py` | 145 current/root Markdown documents, zero missing local targets; historical archive excluded | The bundled PDF Python executable is `C:/Users/Connor/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe`; it uses already available PDF extraction/rasterization libraries. No application dependency is added. **Count reconciliation:** 941 backend and 422 frontend are unchanged. Browser **96 → 98** adds only the two permanent `cv-pagination.spec.ts` behaviours: original six failing fixtures' exact native membership, and image-gated one-time settled measurement. The existing corpus case still contains all 16 numerical fixtures. Four inherited P4-03 preview keyboard cases, native stale-write recovery and frozen-package/P2-D01 cases pass normally. P2-D01 has no expected-failure annotation. The initial focused run had 8/9 passing: the corpus readiness poll dereferenced `documentElement` during the iframe's initial document transition. The final fixture uses a null-safe poll for the explicit readiness signal; the native three-case rerun passed, followed by the complete 98/98 run above. No test expectation, fixture, oracle threshold or difficult content was removed. **P5-09: GO.** G-CV-REV remains accepted and regression-green. G-CV-RENDER is satisfied by the retained corpus: exact page counts/membership, no missing content/blank-page/hidden-section/safe-area failures, positional/typographic/color results within the original tolerances, and matching reviewed page boundaries. P4-03 keyboard behavior remains green. This is a local measured gate, not certification of every possible CV, browser, font or deployment environment. Remaining qualifications: production Linux/font substitution, other browser engines, complete wrapped-line/photo/all-font/all-template-long-form comparisons, existing native heading/bullet keep policy and later template/control presentation. The synthetic delayed-image test proves measurement readiness, not photo/PDF equivalence. These are explicit limits of the accepted fixture contract; no remaining fixture has a material count/placement/clipping mismatch. Further qualification must retain PDF truth rather than weaken this oracle. F04, P5-02 human screen-reader acceptance, incomplete accessibility/manual checks, Dashboard preference-save 500, Board scaling/native touch and deferred `followMode` UI remain separate. No unrelated debt is closed by this repair. No backend/schema/export/package/CI/provider changes occurred. Stop before P5-09 and B07; the next authorised slice would be P5-09 editor frame/navigation using these unchanged output/revision contracts.