# P5-10 — CV section editing and source/override clarity Starts from `44b944e5edd22f9f826663719aa581b5e6db8a83` on `codex/ui-redesign-phase4`. Scope is the existing ContentTab, SectionRow and EntryEditor. The [P5-09 frame](../p5-09/README.md), [revision contract](../p5-09-readiness/README.md) and [pagination proof](../p5-09-pagination-readiness/README.md) remain authoritative. No P5-11+, B07, schema, API or canonical-data mutation is authorised by this slice. ## Discovered model and preservation boundary `GET /api/cv/outline` resolves the current Career Profile with empty settings. It supplies canonical values, including stable entry keys, rather than a variant's effective values. The current preview/export applies CV settings over that source. - `settings.headline`, section `title`/`items`, and entry `title`/`subtitle`/`bullets` provide CV-specific wording. Entry dates/meta and tags are not separately editable overrides. - A missing/null/blank title or subtitle inherits the source; missing/null bullets or section items inherit, while an empty array deliberately empties that content. Inclusion, ordering and presentation do not make source wording “customized”. - `settings.customSections` contains CV-only string content, including presets and the existing multiple-entry format. It is not a second canonical structured Experience/Education editor. - Section inclusion and entry `overrides[key].hidden` remain distinct from content overrides. Omitted content is editable; labels/icons communicate omission rather than whole-container dimming. - History preserves **settings revisions**, not Career Profile snapshots. Restoring old settings creates a new current settings version against the current source. Explicit historical overrides remain unchanged. Immutable submitted packages separately freeze effective source/settings/files. This accepted distinction is preserved; the UI must not claim that settings history is an immutable historical PDF. ## Change-impact contract IDs below use the `PRES-` prefix from the 57-contract ledger (for example C07 is PRES-C07). This is scoped traceability, not a claim of exhaustive coverage of all 57 groups. | PRES IDs | Existing behaviour retained | P5-10 boundary | Required proof | |---|---|---|---| | C01/C02 | Canonical source and source navigation | Explicit Career Profile wording; no embedded canonical editor | Native canonical/sibling readback, inheritance and override retention after source change | | C05/C06/C07 | Current variant, Content forms, overrides, inclusion, section/item order and custom content | Compact entry hierarchy and field-level scope/reset descriptions | Behavioural edit/reset/hide/reorder/add/delete/focus tests and persisted readback | | C10 | One save queue, undo/redo, conflict/recovery and settings history | Same update callback/transactions; source reset remains different from undo/restore | Complete inherited tests and five native/relational revision cases | | C08/C09/C12 | Template/settings, shared preview/PDF truth and export | Renderer and frame unchanged | Original 16-fixture oracle, 36 aligned preview/PDF pages and preview keyboard cases | | C11 | Grounded section AI review/accept/reject | Existing assistant and CV-only apply target retained | Existing section/whole-document acceptance tests | | W05/W07 | Linked CV, frozen package contents and their ownership | Relationship regression boundary only | Native package/P2-D01 and ownership regressions | | E07/E09 | Existing navigation and account-switch private-state disposal | Frame/routes and session boundary unchanged | Inherited shell, account-isolation and stale-client cases | | E08 | Localisation, themes, confirmation and responsive controls | Named fields/actions, explicit inclusion, focus after destructive/reset actions | EN/Bokmål × light/dark rendered desktop/tablet/phone and scoped axe evidence | Builder `/career/builder/:id` and source `/career/profile` compatibility route remain unchanged. No route or information-architecture migration occurs. ## Scope exclusions and acceptance qualifications P5-11 owns preview presentation; P5-12 owns template/document controls; P5-13 owns AI review presentation; P5-14 owns final responsive CV acceptance. The existing controls/rendering owners remain in place. Human screen-reader acceptance, incomplete axe/manual checks, pointer/reflow qualification, production font/photo qualification, F04 production evidence, Dashboard preference-save 500, Board scaling/native touch and deferred `followMode` UI remain open. P2-D01 remains an ordinary passing regression, not expected failure. ## Implemented Content presentation Content retains the existing ordered section selector, multi-open disclosures, headline override and source link. Each expanded section now states its CV-only editing scope and Included/Omitted state. Entry groups use their current title as their accessible name, show translated inclusion beside that title, and separate entries with a border instead of another outlined card. Title and Subtitle share a row when space permits and stack on narrow screens; bullet content remains the existing multiline field and Markdown toolbar. Outline dates are not newly displayed here: the source outline currently formats open-ended dates with default document-language settings, which would leak English into Bokmål. Existing document date rendering remains unchanged. Fields identify **Using Career Profile**, **Customized for this CV**, or, for an explicitly blank title/subtitle, **Blank uses Career Profile**. This describes the existing resolver rules; optional fields acquire no new required-field validation. Omitted entries keep their fields and actions available. Their inclusion label and visibility action convey omission without reducing editable contrast. The existing forms and advanced actions remain available: - All twelve standard sections, populated long-tail outline sections, built-in inclusion, custom sections, the four presets and free text. - Section names, inclusion, confirmed removal, section drag and move buttons, disclosure and navigation. Removing a built-in section omits it; confirmed removal of a custom section deletes its CV-only content and its order row. - Rows/Grid/Compact presentation, Bubble where supported and one/two Grid columns. - Profile-backed entry Title, Subtitle and bullet overrides, entry inclusion, item drag and move buttons. Dates/meta remain source information rather than invented editable overrides. - Profile-backed paragraph/list/tag content, and custom paragraphs, bullets or multiple entries with add, edit, move and confirmed deletion. - Existing section/entry AI entry points and explicit review/apply behavior. Their update targets remain CV settings. ## Source reset, undo and settings history Each defined entry wording override has its own **Use Career Profile: {field}** action. It removes only that field from the existing override object; other wording, hidden state, sibling overrides and section/item order remain intact. Profile-backed section content retains its existing reset, now **Use Career Profile content / Bruk innhold fra Karriereprofil**. Resetting an empty content array also returns to inheritance. Effective preview/export then uses the current canonical source through the existing resolver; the editor's outline is refreshed on reload, without adding source polling or snapshots. Reset uses the same `update` callback as other edits. Session Undo restores the preceding CV settings, including the removed override; Redo reapplies the reset. History Restore remains a separate confirmed operation that creates a new acknowledged settings revision against the current Career Profile. Neither operation rewrites Career Profile or changes the accepted immutable submitted-package boundary. Reset returns focus to the affected field. Custom entry add/reorder focuses the resulting entry; confirmed entry deletion focuses a surviving entry, or Add entry when none remains. Confirmed custom-section deletion focuses Add content. Cancel/Escape retains content and returns focus through the existing confirmation dialog. ## Localisation and touched owners English/Bokmål scope and reset copy use the existing translation owner: **Using Career Profile / Bruker Karriereprofil**, **Customized for this CV / Tilpasset denne CV-en**, **CV-only content / Innhold bare i denne CV-en**, and **Use Career Profile: {field} / Bruk Karriereprofil: {field}**. UI language remains independent of document language and user-authored source/custom content. No content is translated to fit the forms. | File | Bounded responsibility | |---|---| | `job-tracker-ui/src/views/CvBuilderEditor.tsx` | Existing Content form hierarchy, scope/inclusion descriptions, independent wording reset and local focus handling; same settings/update/save owners | | `job-tracker-ui/src/components/RichTextField.tsx` | Optional `helperText` passed to the existing MUI TextField so list/bullet fields can expose the same scope descriptions; unchanged storage and Markdown toolbar | | `job-tracker-ui/src/i18n/translations.ts` | Matching English/Bokmål source and field-reset labels within the existing catalogue | | `job-tracker-ui/src/cv-builder-deep-link.test.tsx` | Four focused cases plus stronger custom-content scope/confirmation/focus assertions | | `job-tracker-ui/e2e/cv-section-scope.spec.ts` | Native item wording/reset/inheritance, selected/sibling/canonical readback, inclusion/order, custom confirmation/focus and settings-history journey in the four theme/locale pairs | No model, API, schema, save protocol, renderer, template capability, provider or route owner changes are required. ## Focused regression evidence The four new unit cases ran before implementation and **4/4 failed** on the missing named entry groups/reset controls. After implementation, the complete editor file passed **30/30**, with no skipped/failed cases. The four additions cover CV-only Title/Subtitle/bullet writes; independent reset with omission/sibling-order preservation and Undo/Redo; omitted-entry draft retention after save failure; and section-content inheritance while retaining inclusion/presentation. The existing custom-content case additionally proves scope text, Cancel focus and focus after confirmed entry deletion. Commands used the repository's `rtk` prefix. Raw focused reports remain ignored at `.artifacts/p5-10-before-jest.json` and `.artifacts/p5-10-after-focused-jest.json`. The initial focused native source/reset/custom-content scenario passed **1/1** against the local disposable API. The final complete run passed all four new native cases plus all 102 inherited cases, as recorded below. ## Separately scoped drag caveat Review identified an inherited boundary in the unchanged `useDragReorder` hook: item drag events can bubble through their enclosing draggable section. A cross-section item drag can therefore reach the section reorder handler; moving an entry between source sections is not a supported operation. This slice preserves within-section native drag and the explicit keyboard move controls. A separate bounded follow-up should define and test nested drag propagation/drop ownership; P5-10 does not silently replace the reorder model or claim cross-section transfer support. ## Native source, revision and rendering proof The four theme/language cases use a fresh ordinary synthetic account, real local cookie authentication and B02 session context, native Career Profile/CV endpoints, and the production static frontend. External browser requests are blocked. Each starts with three source Experience entries, Education, Projects, Skills, a selected CV and an untouched sibling CV. The journey edits all three entry wording fields, omits and edits an entry, moves it by keyboard and native pointer drag, resets each field independently, and compares outgoing mutation fields and persisted native readback. Every checkpoint compares the canonical profile and sibling CV. After a separate native source update and reload, a retained Title override stays local while the reset Subtitle/bullets inherit the updated source. Custom content is added, edited, reordered and deleted using the real confirmations at phone width; Cancel/Escape leaves native content unchanged, and successful removal returns focus to a meaningful surviving control. Finally, native History restores version 1 as a new settings version. The updated Career Profile remains unchanged and the inherited fields use that current source, consistent with the accepted settings-only history model. The unchanged 16-fixture PDF oracle passes with **36 preview pages = 36 PDF pages**. All sixteen generated `render.html` SHA-256 values match the accepted pagination checkpoint exactly. No settings fixture, renderer, PDF semantics or fidelity tolerance changes were made. | Measurement | Declared limit retained | Largest measured variance | |---|---|---| | Page count / marker page membership | Exact | No mismatch | | Page dimensions | 0.5 mm | All fixtures within limit | | Marker X / Y position | 2 mm | X 0.000004 mm / Y 1.493055 mm | | Font size | 0.5 pt | 0.005026 pt | | RGB component | 1/255 | 0.000046 | The five relational revision-readiness cases remain the stale-save/restore, canonical-source, settings-history and account-ownership gate. Submitted-file invariants retain their separate inherited package tests. The complete inherited browser run additionally retains stale-editor conflict/draft recovery, P4-03 keyboard preview entry/exit, frozen-package/P2-D01 and existing AI review/accept/reject. These proofs do not certify every content/font/photo or production renderer combination. ## Candidate review corrections Pre-final review corrected the existing Bokmål section-reset label, replaced an accidental new `h6` entry heading with a styled paragraph, and kept whitespace-only Title overrides named from their effective source value. It also removed the newly proposed outline-date caption because `GET /cv/outline` uses default document settings and can synthesize English “Present” in a Bokmål interface. The existing unit case contains that metadata and asserts it is not newly displayed; document date rendering is unchanged. Earlier partial browser runs were stopped when those corrections required a new production build. They are not counted as completed passes. The first native pointer fixture targeted the centre of a tall form and landed inside its textarea; the fixture now uses the existing entry-header grip area, retains actual browser drag events and requires native `itemOrder` persistence. No drag handler or assertion was replaced to obtain a pass. ## Visual, responsive and accessibility review The retained [visual manifest](evidence/visual-manifest.json) identifies the final-candidate captures and their hashes. Thirty images cover source, customized and reset/omitted entries; populated CV-only content; the workspace after an invalid document name; and confirmed custom-entry deletion. The invalid-name case proves the existing disabled Save action behaviour separately; its scrolled screenshot is not proof of a new inline error UI or complete header visibility. The evidence uses all four light/dark × English/Bokmål pairs, with 1440px desktop, 768px intermediate and 320px phone checks. Native assertions require no horizontal page overflow and focused fields/actions after reflow. Actual rendered captures were inspected, including these representative states: | State / review purpose | Evidence | |---|---| | Light/Bokmål source fields and inclusion | [Desktop source entry](evidence/light-nb-desktop-source-entry.png) | | Dark/English reset and omitted content remains editable | [Reset omitted entry](evidence/dark-en-desktop-reset-omitted-entry.png) | | Dark/Bokmål field scope, wrapped reset help and keyboard focus | [320px entry](evidence/dark-nb-scoped-entry-320.png) | | Light/English repeated custom fields and keyboard controls | [CV-only content](evidence/light-en-custom-cv-only-populated.png) | | Dark/Bokmål narrow custom-entry actions and localized labels | [320px custom content](evidence/dark-nb-custom-cv-only-320.png) | | Destructive consequence and phone dialog actions | [Bokmål delete confirmation](evidence/dark-nb-custom-entry-delete-confirmation.png) | In the inspected scope, fields remain readable, omission is conveyed without dimming editable text, secondary scope descriptions have light/dark treatments, and action/field focus is visible. Repeated entries use a border-separated hierarchy, not a new card per field. Single-line editable titles retain their full value and scroll within their input; narrow actions and descriptions wrap. No preview container, document geometry, font, final branding or permanent colour decision changed. Keyboard behaviour is exercised in the real browser with Enter/Escape, named controls, explicit focus checks and native pointer drag; visual focus inspection complements those assertions. Custom entry actions work at phone width without hover. Field helper text uses MUI's description association. Scope changes do not add a live announcement on every keystroke; reset/add/delete move focus to a meaningful described control. Existing section navigation, preview regions and keyboard entry/exit are regression dependencies, not rewritten here. The [axe summary](evidence/axe-summary.json) retains both violations and **incomplete** checks. Scoped automated results do not certify spoken names, live announcements or every dialog/provider state. Human screen-reader acceptance remains required for P5-15, and existing incomplete contrast/ARIA/table findings remain unclosed. Native mobile-touch and broader pointer/reflow qualification are not inferred from desktop Chromium emulation. ## Final executed validation — 2026-10-07 The final candidate includes the metadata/whitespace/heading corrections above. All application checks below completed afterward. No production requests or deployments were made. | Gate | P5-09 inherited | Final P5-10 | Change | |---|---:|---:|---| | Backend Release | 941 | **941 passed**, zero skipped/failed | No new backend code/tests | | Frontend Jest | 426 | **430 passed**, 80 suites, zero skipped/failed | Four focused Content cases | | Chromium browser | 102 | **106 actual passes**, zero skipped/flaky/failed/expected failures | Four native locale/theme journeys | | Original fidelity oracle | 16/16, 36 pages | **16/16, 36 preview = 36 PDF pages** | Fixtures/tolerances/HTML unchanged | | Revision subset (included in backend total) | 5/5 | **5/5** | Unchanged gate | | Rate-limit / ingress / PDF admission | 9 / 6 / 1 | **9 / 6 / 1 passed** | B03/B04/B06 gates; B01/B02/B05 retain complete backend/browser regressions | | Configuration/Compose fixtures | 3 | **3 passed** | Unchanged repository config gate | | TypeScript / edited browser TypeScript / lint | Passing | **Passing**, lint zero warnings | No TS/CI gate change | | Frontend production / API Release builds | Passing | **Passing**, API zero warnings/errors | No build/CI/dependency change | | Supply-chain / Ollama evaluation / extension fixtures | 3 / 5 / 3 | **3 / 5 / 3 passed** | Ancillary local fixtures | | Secret / whitespace / document links | Passing | **Passing**; 147 current/root Markdown files, zero missing local targets | Historical archives/external URLs/anchors excluded by the inherited local-target check | The [browser summary](evidence/browser-summary.json) records every case's actual/expected status and attempt duration. All expected statuses are `passed`; **P2-D01 is ordinary passing**. Browser duration was 17.8 minutes. Frontend duration was 210.814 seconds; backend reported 19 seconds. Raw Jest/TRX/browser/security outputs stay ignored under `.artifacts/p5-10/`; the retained summaries exclude credentials, requests and raw traces. The complete run retains **205 axe scans, zero reported violations**. Sixteen are new P5-10 scoped scans. New scans retain `aria-prohibited-attr` and `color-contrast` incomplete findings; inherited scans additionally retain `aria-hidden-focus`, `aria-valid-attr-value` and `th-has-data-cells`. These are incomplete checks, not certified passes or closures of the manual accessibility gate. ### Reproducible commands Commands below are invoked through `rtk proxy` (Git uses `rtk git`). UI commands run in `job-tracker-ui`. Native test runners use `DOTNET_ROOT=C:/Users/Connor/.dotnet` and `DOTNET_HOST_PATH=C:/Users/Connor/.dotnet/dotnet.exe`. Frontend production build uses `NEXT_PUBLIC_API_BASE_URL=http://localhost:5302/api`; browser runs use `PLAYWRIGHT_STATIC_EXPORT=true`, `PLAYWRIGHT_PREBUILT_EXPORT=true`, `CV_FIDELITY_OUTPUT=../.artifacts/p5-10/fidelity` and `PLAYWRIGHT_JSON_OUTPUT_NAME=../.artifacts/p5-10/browser.json`. Build the static export before the browser runner; specialized native suites share port 5302 and run sequentially. ```text dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-restore --logger "trx;LogFileName=p5-10.trx" --results-directory .artifacts/p5-10/backend dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-build --filter "FullyQualifiedName~CvRevisionReadinessTests" dotnet build JobTrackerApi/JobTrackerApi.csproj --configuration Release --no-restore -warnaserror npm.cmd test -- --runInBand --silent --json --outputFile=../.artifacts/p5-10/jest.json npm.cmd run typecheck npm.cmd exec tsc -- --project ../.artifacts/p5-09-readiness-e2e-tsconfig.json --noEmit --incremental false npm.cmd run lint npm.cmd run build npm.cmd run test:e2e -- --output=../.artifacts/p5-10/browser --reporter=line,json python -X utf8 scripts/verify-cv-fidelity.py .artifacts/p5-10/fidelity npm.cmd run test:rate-limits -- --output=../.artifacts/p5-10/rate-limits --reporter=line npm.cmd exec playwright test -- --config=playwright.ingress.config.ts --output=../.artifacts/p5-10/ingress --reporter=line npm.cmd run test:pdf-admission -- --output=../.artifacts/p5-10/pdf-admission --reporter=line python scripts/test-ingress.py python scripts/test-supply-chain.py python scripts/test-ollama-evaluation.py node browser-extension/tests/capture-url.test.mjs python scripts/supply-chain.py scan-secrets python .artifacts/p4-04-check-doc-links.py git diff --check git diff --cached --check ``` Fidelity uses the already configured bundled Python with PDF libraries, not a newly installed dependency. The temporary browser-type/link helpers retain the inherited checkpoint procedures; no CI or package.json change is needed. Evidence summaries and thirty final-candidate screenshots are the only new retained artifacts. ## Acceptance and remaining P5-11 boundary **P5-10 accepted locally.** Career Profile, sibling CV and submitted-package boundaries remain protected; current Content edits write the selected CV only. Revision safety, preview keyboard behaviour and the original measurable fidelity gate pass. No rendering/page-count regression blocks the next preview-presentation slice. P5-11 owns live-preview presentation and must preserve this same renderer/geometry/fidelity contract. P5-12 owns template/document controls, P5-13 AI review and P5-14 full responsive CV acceptance. They were not implemented here. The inherited settings-history distinction must remain explicit in future work. Keep open: P5-02 human screen-reader acceptance for P5-15, incomplete axe/manual checks, broader pointer/reflow and production font/photo qualification, **F04 production ingress evidence**, Dashboard preference-save 500, Board full-result scaling/native touch, deferred `followMode` compose UI and unchanged inherited timing observations. **P5-10-O01** records the separately scoped nested drag/drop ownership caveat above; it does not authorize unsupported cross-section item transfer or block preview-only P5-11. No unrelated remediation or B07 work occurred.