Files
jobtrackingapp/docs/redesign/phase-5/p5-09-pagination-readiness/README.md
T

21 KiB
Raw Blame History

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 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, source measurements 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 preserve each sample. The native ruler results 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 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, dark/Bokmål desktop, light/Bokmål phone, dark/English phone. 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 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
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.