Files
jobtrackingapp/docs/redesign/phase-5/p5-10/README.md
T
2026-10-07 13:53:54 +02:00

23 KiB
Raw Blame History

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, revision contract and pagination proof 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 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
Dark/English reset and omitted content remains editable Reset omitted entry
Dark/Bokmål field scope, wrapped reset help and keyboard focus 320px entry
Light/English repeated custom fields and keyboard controls CV-only content
Dark/Bokmål narrow custom-entry actions and localized labels 320px custom content
Destructive consequence and phone dialog actions Bokmål delete confirmation

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 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 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.

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.