feat(cv): redesign document editing with revision-safe letters and writing tools

This commit is contained in:
cesnimda
2026-10-25 22:44:14 +01:00
parent 01e10996c5
commit 2bfaf6c14b
57 changed files with 2859 additions and 118 deletions
+36
View File
@@ -0,0 +1,36 @@
# CV-UX-AI — contextual writing assistance
Owner-approved addition, 25 October 2026. This checkpoint is part of CV-UX-01 and does not close AI-P5-13 or authorise production activation.
## Existing owners and contracts
`AiSectionAssistant` is already mounted beneath custom content, ordinary section content (including professional summary), and individual entry bullets (experience, projects and education). `CvBuilderEditor` supplies its existing save-before-generation and reviewed-application callbacks. The new compact actions reuse these callbacks: Improve writing (`improve`), Suggest content (`suggest`), Grammar check (`grammar`), Shorter (`shorten`). Existing additional actions remain available.
`CvVariantController` requires local authentication and the existing Pro entitlement on generation/application. `CvAiSuggestionService` reads the owned variant and Career Profile, checks the requested saved revision/source, validates output shape and grounding, and issues a protected proposal capability bound to owner, variant, version and source fingerprint. Acceptance rechecks that state and uses the ordinary versioned CV save. Neither generation nor acceptance updates the canonical profile. User edits to a proposal are re-evaluated. Generation is not acceptance.
`ISummarizerService` already routes generation to the self-hosted Python sidecar. Factual review uses `/cv/evaluate-rewrite`; unavailable or invalid assessments fail closed. No additional provider/model/dependency or model download is introduced. Suggest content uses the selected saved section's career evidence; it does not infer experience from job requirements. Empty fields request substantiated career facts before generation. Cross-section recommendations are not claimed.
The existing cover-letter `AiWorkspaceService` uses the owned linked CV/profile and job context, returns a reviewable suggestion, and records an AI interaction. The existing Pro/local authorization remains. Its body generation does not have the CV capability/grounding evaluator contract: prompt guardrails and user review are not equivalent to semantic qualification. The four direct controls reuse its existing improve/generate/grammar/shorten operations. Local source changes, source CV changes and cancelled requests invalidate pending proposals. Acceptance edits only the local draft; the ordinary revision-checked letter save remains explicit.
## Safety and UX contract
The source prerequisite now refuses letter inference before model invocation or interaction creation unless an owned linked CV resolves actual career evidence. Identity, section headers, an advert and a prior draft are insufficient. Five source/action refusal combinations were added to the full backend suite. The UI maps `cover_letter_source_required` to actionable EN/Bokmål guidance. The four letter controls are portalled immediately beneath the body field while retaining the existing assistant read lifecycle.
- Original and editable proposed text remain separate; Reject never saves and Accept is explicit.
- Current document language is supplied to CV generation. Letter language uses its existing explicit selector; grammar/improvement/shortening must preserve source language and meaning.
- Loading, retry and logical cancellation retain source text. Cancellation discards responses; it does not claim inference-server interruption.
- Shared controls use MUI and EN/Bokmål strings. Keyboard/mobile/browser checks remain distinct from component tests.
- Source documents and job descriptions are untrusted data, not authority to change instructions or career facts.
## Evidence to date (intermediate, not final acceptance)
`contextual-ai.trx`: 83 backend CV AI tests passed, including four action review/history/canonical-preservation cases. `ai-ui.json`: 61 combined AI/letter UI tests passed. New direct-action and empty-source tests were observed failing before implementation. The new cover-letter concurrent-edit regression also failed before response invalidation was added. These controlled responses do not demonstrate actual model quality.
| Action | Implementation | Frontend | Backend | Actual model / production |
|---|---|---|---|---|
| Improve writing | Existing CV/letter paths exposed directly | Component pass | CV tests pass; letter regression pending final suite | NOT TESTED / not eligible |
| Suggest content | New CV action; existing letter generation | Component pass, missing source asks for input | CV tests pass; letter grounding limitation above | NOT TESTED / not eligible |
| Grammar check | Existing paths exposed directly | Component pass | CV tests pass; letter regression pending final suite | NOT TESTED / not eligible |
| Shorter | Existing paths exposed directly | Component pass | CV tests pass; letter regression pending final suite | NOT TESTED / not eligible |
Outstanding: fresh full regression, endpoint authorization/browser coverage, actual approved self-hosted EN/Bokmål inference and adversarial semantic acceptance, source-grounding qualification for letter operations, human accessibility and language review. Production remains NO-GO; no deferred P5-13 operation is activated by this UI work.
@@ -0,0 +1,33 @@
# CV-UX implementation checkpoint — 25 October 2026
Workspace, section, candidate-template, letter-document and contextual AI implementation is ready for final integration qualification. This is not final CV-UX acceptance. Commands and remaining lanes are in VERIFICATION.md.
The existing editor retains its save queue, content/settings ownership, preview and undo. Document context/history provenance are explicit; movement announces position and retains boundary focus; previews have page selection. Template candidates use real renderer samples, make no writes until Apply, reject late responses and use reversible visual-only application.
CV export flushes local saves and checks the requested saved revision before rendering; changed local revisions discard late downloads. Existing callers without the optional CV revision remain compatible.
All letter writers stage text/design/history with the parent transaction and shared RD21 Version. Generic/draft null/clear rules remain distinct. Previously unrecorded current text is recovered before replacement; restore creates a new version. The additive nullable migration retains old text-only records. Account/backup exports include history/design; submitted packages capture rendered letter bytes/settings without rewriting historical records.
Letter editing provides adjacent/responsive physical preview, explicit Save, reviewed contact/design snapshot copying and saved-revision export. Copy creates no live synchronization. Rendering reuses CV normalization, inline formatting, pagination and bounded PDF admission. The redundant narrower text preview is hidden when physical preview is available; legacy responses retain their fallback.
Four contextual AI controls reuse existing self-hosted owners. CV proposals retain capability/source/revision validation. Letter suggestions edit the local draft explicitly; missing career evidence prevents inference and interaction creation. Cancelled or changed-source/language responses are discarded. Letter prompt guardrails do not establish actual-model semantic qualification; see AI.md.
## Executed intermediate evidence
Artifacts reside under `.artifacts/cv-ux-01/`.
| Check | Result | Qualification |
|---|---|---|
| Full backend Debug successor | 1169 passed, 0 failed/skipped | `backend-successor.trx`; post-test wrapper quoting error retained separately |
| Full backend Release | 1169 passed, 0 failed/skipped | `final-01/backend/backend.trx`; subsequent browser attempt superseded by frontend review correction |
| Earlier full frontend | 972 passed / 107 suites | `frontend-full.json`; predates latest review changes |
| AI/letter frontend successor | 73 passed / 3 suites | `ai-ui-successor.json`; controlled responses, not real inference |
| Preview review correction | 54 passed / 2 suites | `preview-review.json`; physical-preview precedence |
| Actual disposable MariaDB design | 56 passed, 0 skipped | `letter-design-mariadb`; pinned12.2.2, down/up preservation and positive cleanup; fresh final provider run pending |
| Windows letter native PDF | 4 documents / 14 pages, zero differences | `letter-windows-01`; unchanged oracle, real API/export; predates final UI review correction |
| Build/type/lint | PASS | Release API0warnings/errors; TypeScript/lint; static build repeated after correction |
| Independent source review | One P2 corrected | Duplicate preview had narrower formatting dialect; no proven new data-loss/security defect |
Focused results overlap full suites and are never added to their totals. The first final browser attempt is incomplete/superseded and retained. Final regression must bind source/runtime hashes after the review correction.
Remaining: fresh ordinary/contract/RD21 browsers, responsive/localisation automation, provider regression, original Windows/Linux CV oracles and Linux letter fidelity. Actual self-hosted model semantics and human accessibility/device/language/print remain unqualified. Hosted isolation/MariaDB restrictions and production/Phase10 NO-GO remain. CV-IMPORT-01 is not started.
+2
View File
@@ -11,6 +11,8 @@ No main merge/deployment, canonical-profile replacement, new AI providers, Docli
## Tasks
The owner's additional mandatory AI scope is tracked in [AI.md](AI.md): four directly accessible actions, existing self-hosted contracts, review before application, missing-source handling and honest per-action qualification. Complete this checkpoint alongside section editing and revision safety, before final acceptance.
1. **CV-UX-00 entry/research:** verify baseline, hash all original files, inspect all 37 screenshot/DOM checkpoints, preserve portable research prose and map every recommendation against current owners. Commit/push entry and plan.
2. **CV-UX-01/02 workspace/sections:** extend `views/CvBuilderEditor.tsx` and both locale dictionaries. Preserve controls and layout owners; improve context, history wording, section reorder announcements/focus and section discovery. Add assertions to current editor browser tests before changing behavior; run focused suites and commit/push.
3. **CV-UX-03 candidates/preview:** add `components/cv/CvTemplatePreviewDialog.tsx`; integrate at `CvCustomizeTab` without changing library creation semantics. Reuse `cvBuilderApi.themePreview(themeId): Promise<CvRender>` and `applyCvTheme`. Test no update on open/cancel, retry, late response, lock enforcement, reset confirmation, preservation and one undo step. Physical pages use cvPreview readiness; no new PDF request for browsing. Add bounded page navigation to existing preview. Commit/push after unit/browser proof.
+166
View File
@@ -0,0 +1,166 @@
# CV-UX verification execution plan
Prepared 25 October 2026 from the existing Phase 9 reproduction instructions and runners. This document is a prospective execution plan, not passing evidence. The parent owns the final source freeze, serial execution, reconciliation and publication. Do not execute while workers are changing backend/frontend sources. Preserve every failed or superseded attempt.
## Fresh identity and lifecycle
Use a new absolute evidence root, for example `E:/Storage/Projects/Active/Job tracker/.artifacts/cv-ux-01/final-01`; reject it if it already exists. Use `final-02` after an implementation/fixture correction. Do not invoke `.artifacts/p9-sec-02/final-run.py`, `p9-sec-02/reconcile.py`, `p9-sec-02/linux-run.py`, or the historical MariaDB lane wrapper unchanged: they hardcode historical evidence roots, image identities, counts or source lineage and can overwrite/reuse historical evidence.
Before the first build, record branch/HEAD/status and SHA256 for all application, migration, frontend, fixture, config, lock, Dockerfile and helper inputs, including new untracked source. Build once, then freeze the API Release binaries/deps/font resources and frontend `out` file hashes plus tool/runtime/browser identities. Repeat source and runtime hashes after all producers finish. A Git SHA alone does not identify uncommitted worker changes. Record UTC start/end, actual argv, cwd, selected nonsecret environment, exit code and native report hashes for every lane. Never print connection/session credentials. App health's fixture token is not source provenance.
Prerequisites: pinned .NET SDK from `global.json` (currently 9.0.317), `C:/Users/Connor/.dotnet/dotnet.exe`; installed locked UI dependencies and Node; installed Playwright Chromium; Python with `pdfplumber`, `pypdfium2`, Pillow; Docker Linux engine; local pinned MariaDB 12.2.2 image. Do not run npm install, change locks, download models, or mutate developer databases as a substitute for these prerequisites. Obtain the bundled PDF Python path with the app dependency tool if the retained path below is absent.
All commands below are run serially. Root cwd unless explicitly UI cwd. The execution controller must retain stdout/stderr to per-lane logs and check each exit code before proceeding; pipelines must not turn failures into passing exit codes. UI/API servers must be stopped before rebuilding binaries/static assets. Ports 3300/5302 (plus the diagnostic/volume-specific ports) must be free or positively identified as this attempt's owned processes; `PLAYWRIGHT_REUSE_SERVERS=false` prevents accidental reuse.
```powershell
$cvUxRoot = 'E:/Storage/Projects/Active/Job tracker/.artifacts/cv-ux-01/final-01'
if (Test-Path -LiteralPath $cvUxRoot) { throw 'Select a fresh evidence root' }
New-Item -ItemType Directory -Path $cvUxRoot | Out-Null
$env:DOTNET_ROOT = 'C:/Users/Connor/.dotnet'
$env:DOTNET_HOST_PATH = 'C:/Users/Connor/.dotnet/dotnet.exe'
$env:NEXT_PUBLIC_API_BASE_URL = 'http://localhost:5302/api'
$env:PLAYWRIGHT_STATIC_EXPORT = 'true'
$env:PLAYWRIGHT_PREBUILT_EXPORT = 'true'
$env:PLAYWRIGHT_REUSE_SERVERS = 'false'
$env:CV_FIDELITY_OUTPUT = "$cvUxRoot/windows/fidelity"
$env:CV_SETTINGS_FIDELITY_OUTPUT = "$cvUxRoot/windows/settings-fidelity"
$env:LETTER_FIDELITY_OUTPUT = "$cvUxRoot/windows/letter-fidelity"
$env:SKIP_MODEL_LOAD = '1'
$env:AI_SERVICE_SKIP_MODEL_LOAD = '1'
$env:PYTHONIOENCODING = 'utf-8'
```
The model-disable variables retain the established local application regression conditions. Unchanged Python/model security qualification is inherited from the Phase 9 baseline and explicitly labelled historical; this feature does not rerun or establish GPU/model/hosted/provider/production acceptance.
## Builds and complete local suites
Root cwd:
```powershell
rtk C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-restore --logger 'trx;LogFileName=backend.trx' --results-directory "$cvUxRoot/backend"
rtk C:/Users/Connor/.dotnet/dotnet.exe build JobTrackerApi/JobTrackerApi.csproj --configuration Release --no-restore
```
The backend test build also creates the Release PDF process stub required by the separate admission config. If locked restore is actually required, record that separate command/outcome; never treat a restore-only exit as a test result.
UI cwd `E:/Storage/Projects/Active/Job tracker/job-tracker-ui`:
```powershell
rtk node node_modules/jest/bin/jest.js --runInBand --json "--outputFile=$cvUxRoot/frontend.json"
rtk node node_modules/typescript/bin/tsc --noEmit --incremental false
rtk node node_modules/eslint/bin/eslint.js . --max-warnings=0
rtk node --max-old-space-size=4096 node_modules/next/dist/bin/next build
```
Record fresh native totals rather than fixing expected counts to the historical backend 1130/frontend 935. Compare discovery/membership with baseline; every added/removed/renamed case needs an explicit source-backed explanation. Do not add earlier focused worker checks to the full-suite totals.
## Ordinary browsers and independent contracts
Keep UI cwd and the environment above. First retain ordinary discovery:
```powershell
$env:PLAYWRIGHT_JSON_OUTPUT_NAME = "$cvUxRoot/discovery.json"
rtk node node_modules/@playwright/test/cli.js test --list --retries=0 --reporter=list,json
```
Execute four complete shards **one at a time**, with process metadata/logs and a separate native JSON for each:
```powershell
foreach ($cvUxShard in 1..4) {
$env:PLAYWRIGHT_JSON_OUTPUT_NAME = "$cvUxRoot/ordinary-$cvUxShard.json"
rtk node node_modules/@playwright/test/cli.js test --retries=0 --reporter=list,json "--output=$cvUxRoot/ordinary-$cvUxShard-results" "--shard=$cvUxShard/4"
if ($LASTEXITCODE -ne 0) { throw "Ordinary shard $cvUxShard failed; preserve this attempt" }
}
```
Historical ordinary discovery was 362. The new `cover-letter-document-fidelity.spec.ts` currently adds **one browser test containing four physical letter fixtures**; new CV workflow cases may increase discovery further. Reconcile exact test ID/project membership across the four native reports with current discovery; require each discovered case exactly once, no retries, failures, unexpected skips or missing errors. Four physical letter documents are not four browser cases. Capture `LETTER_FIDELITY_OUTPUT` only once per attempt: its producer refuses an existing `started.json`.
Execute each configuration below separately using this exact command pattern, setting `$cvUxLane` and `$cvUxConfig` to the corresponding row. Do not combine or sum these with ordinary cases.
```powershell
$env:PLAYWRIGHT_JSON_OUTPUT_NAME = "$cvUxRoot/$cvUxLane.json"
rtk node node_modules/@playwright/test/cli.js test --retries=0 --reporter=list,json "--output=$cvUxRoot/$cvUxLane-results" "--config=$cvUxConfig"
```
| Lane | Configuration relative to UI cwd | Historical expected membership (verify fresh) |
|---|---|---:|
| ai | `playwright.cv-ai.config.ts` | 2 |
| auth | `playwright.auth-recovery.config.ts` | 2 |
| rate | `playwright.rate-limits.config.ts` | 9 |
| ingress | `playwright.ingress.config.ts` | 6 |
| pdf-admission | `playwright.pdf.config.ts` | 1 |
| preferences | `../docs/redesign/phase-5/p5-15/p5-15-01/diagnostics/playwright.config.ts` | 3 |
| rd21 | `../docs/redesign/phase-9/rd21-remediation/diagnostics/playwright.config.ts` | 6 |
| diagnostics | `../docs/redesign/phase-9/p9-05/diagnostics/playwright.config.ts` | 18 |
| volume | `../docs/redesign/phase-9/p9-05/volume/playwright.config.ts` | 3 |
| rd21-volume | `../docs/redesign/phase-9/rd21-remediation/volume/playwright.config.ts` | 3 |
The six contract lanes historically total 23; RD21/diagnostics/volume lanes remain separate. Run both volume lanes alone without builds, renders, provider pacing or other browser suites. Admission uses inert child stubs and must never be described as real physical PDF fidelity.
## Actual MariaDB
The letter-persistence worker owns provider qualification. Its earlier 47-case all-writer gate predates document design/migration; it is not the final additive-schema gate. Its later checkpoint at `.artifacts/cv-ux-01/letter-design-mariadb` reported 56/56 passing with the additive migration and provider downgrade/reupgrade preservation, and positive generated-project cleanup. That is separately reported worker evidence, not a fresh parent frozen-source full regression. The guarded runner already supports fresh output and generated projects/schemas:
```powershell
rtk python scripts/mariadb-integration.py --output "$cvUxRoot/mariadb"
```
Run only after final source freeze and record actual new TRX membership/count, exact pinned image/server 12.2.2, schema ownership and positive cleanup. The runner's default mode creates a generated `jobtracker-it-<uuid>` project, loopback random port and tmpfs test data, then removes only its owned test service. Do not substitute SQLite or developer `mariadb-dev`; do not use broad prune/down -v. An earlier worker checkpoint may support development sequencing but cannot be added to this fresh full provider total.
Existing MariaDB browser/HTTP-observation/15-minute workload helpers have fixed roots/project assumptions. If those are in the final parent-required matrix, adapt only fresh-root/project parameters and retain their native independent counts and exact paced-duration evidence. Run the pacing workload alone. The parent must identify which helper executes that lane before marking it complete; ordinary browsers and backend MariaDB tests do not supply workload proof.
## Windows original 24-document CV oracle
Ordinary shards produce the existing 16-fixture fidelity corpus and four settings-browser cases containing eight settings states in the fresh Windows roots above. Stop all producers before proof. Root cwd, use the bundled Python (verify available; retained installation path shown):
```powershell
rtk C:/Users/Connor/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe -B docs/redesign/phase-9/p9-requal-01/pdf-proof.py --platform windows --fidelity-root "$cvUxRoot/windows/fidelity" --settings-root "$cvUxRoot/windows/settings-fidelity" --output "$cvUxRoot/windows/proof" --record "$cvUxRoot/windows/native-pdf.json"
```
`pdf-proof.py` accepts fresh roots unchanged and checks exact 16/36-page plus 8/24-page membership using `scripts/verify-cv-fidelity.py`. Retain original oracle SHA256 `64f82e622cc11483c33307d987e969f6cf27f82ab6bdbd72c2aeb1bfbceade87`; never edit tolerances or fixture expectations to make this feature pass. A real regression stays FAIL with artifacts.
## Current-source Linux API and original 24-document oracle
**Do not run the historical image as if it contains current letter schema/rendering.** Prefer the current `JobTrackerApi/Dockerfile` rebuilt from the frozen current source into a new local-only feature tag. Record Dockerfile/context hashes, build log, local base IDs, resulting immutable image ID, runtime/Chromium/font/package identity and API Release DLL hash. `--pull=false` preserves installed inputs but does not make floating local tags immutable. Record resolved inputs; if unavailable, leave the lane blocked rather than silently downloading/reusing a different qualified runtime.
```powershell
rtk proxy docker build --pull=false -f JobTrackerApi/Dockerfile -t jobtracker-cv-ux-api:final-01 .
rtk proxy docker image inspect jobtracker-cv-ux-api:final-01
```
A narrower alternative when existing SDK/apt inputs cannot rebuild offline is a fresh image **over the verified historical Linux runtime ID with every current portable API publish output copied over `/app`**, built from a fresh hashed publish directory with `/p:UseAppHost=false`. That reuses native runtime/fonts, not historical application-source evidence; record current DLL/deps/migration/resource hashes and a new immutable image ID. Do not claim hermetic OS rebuilding. The old source image ID alone is insufficient.
The reusable lifecycle is `p9-requal-01/linux-run.py`: generated guarded `jt_it_<32 hex>` schema, isolated network, tmpfs API `/data`, loopback API port 5302, actual ready/migration checks, logs and positive API/network/schema cleanup. It needs a **small new feature adapter** before execution because its DB project/port checks are hardcoded to `jobtracker-it-p9-requal`/33308 and its config includes only historical CV tests. Required parameters: fresh output, immutable newly built image ID, frozen source identity, validated dedicated tmpfs DB container/project/port and a current Linux Playwright config. Guard DB image pin, tmpfs/no persistent mounts, loopback-only port, nonprivileged/nonhost networking and exact server 12.2.2 before any SQL. Verify `/health` version and source commit against recorded identity; do not infer source freshness from the unchanged legacy fixture-ready token.
The feature Linux Playwright config must retain the original base frontend server only (Linux runner owns API), workers 1/retries 0, and select:
- `cv-readiness.spec.ts` / `native preview/PDF fidelity corpus` (1 browser case, 16 documents).
- `cv-settings-presentation.spec.ts` / `document controls preserve settings` (4 browser cases, 8 states).
- `cover-letter-document-fidelity.spec.ts` / `cover letter native preview/PDF fidelity` (1 browser case, 4 documents).
Set fresh `CV_FIDELITY_OUTPUT`, `CV_SETTINGS_FIDELITY_OUTPUT`, `LETTER_FIDELITY_OUTPUT` under `$cvUxRoot/linux`, `PLAYWRIGHT_JSON_OUTPUT_NAME=$cvUxRoot/linux-renderer.json`, the immutable image and full current source identity. The adapter should retain the existing guarded cleanup and add offline assert checks for wrong image/project/port/schema, reused output, API startup failure and cleanup failures. No adapter was implemented in this documentation-only ownership; the parent must implement/review it or supply an equivalent owned lifecycle before running Linux.
After successful Linux producers and positive cleanup, root cwd:
```powershell
rtk C:/Users/Connor/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe -B docs/redesign/phase-9/p9-requal-01/pdf-proof.py --platform linux --fidelity-root "$cvUxRoot/linux/fidelity" --settings-root "$cvUxRoot/linux/settings-fidelity" --output "$cvUxRoot/linux/proof" --record "$cvUxRoot/linux/linux-pdf.json"
```
## Separate letter physical fidelity
The new `e2e/cover-letter-document-fidelity.spec.ts` is a real authenticated producer, with one browser case/four independent multipage A4/Letter × EN/NB × light/dark documents. It creates a synthetic owned job per fixture, saves text+design with the shared expectedVersion, previews through the real server and application iframe, waits for font/image pagination readiness, walks every next-page control, proves final marker reachability, checks sender/recipient and inline formatting, downloads the saved-revision PDF and records bytes/HTML hashes, settings, all unique text-marker geometry/style, actual browser version and per-page screenshots. It asserts preview/export do not mutate saved letter or canonical source. It refuses reusing the attempt and writes root `measurements.json` only after all four succeed. No browser execution has occurred at preparation time.
Its measurements use the existing oracle's schema. The unchanged lower-level oracle supports arbitrary corpus size, so **no new PDF oracle or widened tolerances are needed**. Run separately after each platform's producers stop:
```powershell
rtk C:/Users/Connor/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe -B scripts/verify-cv-fidelity.py "$cvUxRoot/windows/letter-fidelity"
rtk C:/Users/Connor/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/python.exe -B scripts/verify-cv-fidelity.py "$cvUxRoot/linux/letter-fidelity"
```
Require exactly the four fixture names `light-en-a4`, `dark-nb-a4`, `light-nb-letter`, `dark-en-letter`, each native result passing without failures, no duplicate/missing marker, matching physical page count/geometry/fonts/colors/safe areas. Retain `fidelity-results.json`, actual PDF page images/comparison images and producer inputs/hashes. Do not add these four documents to either original CV24 count. Review extracted PDF text for full sender email/phone/location, multiline recipient, subject, bold/italic content and final diacritics; marker checks alone do not establish every unmarked string. No physical printer/human fidelity claim follows from this oracle.
## Reconciliation and stop rules
The historical collector is not parameterized for this feature and hardcodes old totals/roots. A minimal new parent-owned collector must read only this fresh attempt, reconcile current discovery exactly against four ordinary reports, enumerate frontend assertion names and backend/provider TRX test IDs, validate all independent lane reports and process exits, verify no retries/unexpected skips, check CV24 and letter4 oracle membership, bind inputs/runtime/image hashes, and require positive cleanup. Its offline self-check must reject a historical-root report, absent/duplicate cases, bad process exit, source/runtime drift, wrong image and missing cleanup. `--collect-only` must not mean acceptance. Historical Phase 9 evidence stays immutable.
Stop/re-freeze on source or runtime drift, stale apphost/static output, migration/schema failure, failed oracle, frozen history loss or unqualified revision behavior. Keep failed attempts separate; never replace a full failed shard with an overlapping focused test total. Report focused/full/backend/frontend/browser/provider/PDF/human outcomes independently. Human screen-reader/touch/device/zoom/print, hosted isolation/MariaDB, provider, deployment and production remain NOT TESTED/BLOCKED as applicable. Production and Phase 10 remain NO-GO.