feat(jobs): integrate table and board workspace

This commit is contained in:
cesnimda
2026-09-29 23:01:05 +02:00
parent 6fc8937701
commit 384dfa8a4b
35 changed files with 1191 additions and 60 deletions
+2
View File
@@ -1,5 +1,7 @@
# Redesign traceability
Current Jobs integration: [P5-04b scoped trace and evidence](../phase-5/p5-04b/README.md#preservation-traceability) maps PRES-J03–J07, W01/W02, E07–E09 and S03 to the shared workspace, compatibility adapter, native/unit regressions and rendered evidence. Its containing commit identifies the implementation checkpoint; earlier phase records below remain historical evidence.
Phase 5 planning: [57-contract change impact](../phase-5/PRESERVATION_IMPACT.md), [navigation migration](../phase-5/NAVIGATION_MIGRATION.md) and [visual evidence protocol](../phase-5/VISUAL_ACCEPTANCE.md). The successor [P5-00 readiness trace](../phase-5/p5-00/README.md#preservation-trace) records bounded shell prerequisite changes and actual evidence. P5-01 visible redesign has not begun; baseline, package/CV and production conditions remain explicit.
Successor planning checkpoint: [Phase 3 impact matrix and architecture](../phase-3/PRESERVATION_IMPACT_MATRIX.md). It maps all 57 contracts to proposed destinations/validation, without changing their requirements or claiming implemented/visual parity. The subsequent [P4-01 trace sheet](../phase-4/p4-01/TRACEABILITY.md), [P4-02 named-control/modal record](../phase-4/p4-02/README.md), [P4-03 preview keyboard record](../phase-4/p4-03/README.md), [P4-04 Settings layout/typography record](../phase-4/p4-04/README.md) and [P4-05 table/list density record](../phase-4/p4-05/README.md) link shared foundation changes to regression and representative visual evidence. [P4-06 acceptance](../phase-4/p4-06/README.md) and its [57-row reconciliation](../phase-4/p4-06/PRESERVATION_ACCEPTANCE.md) retain scoped evidence, incomplete checks and affected-migration gates; they do not claim exhaustive preservation or production readiness.
@@ -22,7 +22,7 @@ Keep existing children visible in shell secondary navigation until their workspa
| Job applications | Job search → Jobs primary, `/jobs` | Tracked Table default; P5-03 | J03–J06 |
| Discover jobs | Jobs secondary, `/discover` | Jobs secondary row; discovery owner unchanged | J01, J02 |
| Reminders + count | Jobs secondary, label Follow-ups, `/reminders` | Retain count and all reasons, not just overdue rows | W11 |
| Kanban board | Jobs secondary, `/kanban` | P5-04a same route; switch/alias only after P5-04b parity | J07 |
| Kanban board | Jobs view switch, `/jobs?view=board`; `/kanban` retained | P5-04b integrates after proven parity; alias replaces history and preserves query/hash/state | J07 |
| Companies | Jobs secondary, `/companies` | Preserve `?edit=id`, contacts/history | J08 |
| Offer comparison | Jobs secondary, `/offers` | Retain recorded offer comparison, no new salary model | J09 |
| Job email / Correspondence | Job search → Correspondence **primary**, `/correspondence` | Inbox, Drafts, Review remain independent; not hidden in Documents | M01–M06 |
@@ -66,7 +66,7 @@ No compatibility removal date is approved. Each row retains refresh, direct entr
| `/jobs/:id` | Dedicated job workspace | 08a, 08b | W01–W12, M01, M02 |
| `/reminders` | Jobs → Follow-ups | 01 link only | W11 |
| `/operations` | Notification/account activity utility | 01, 02 link only | W12 |
| `/kanban` | Keep standalone until parity; then direct replace to `/jobs?view=board` | 04a, gated 04b | J07 |
| `/kanban` | P5-04b direct replace to `/jobs?view=board`, retaining other query/hash/state | 04a, 04b | J07 |
| `/companies` | Jobs → Companies, preserve `?edit=id` | 01, 02 link only | J08 |
| `/offers` | Jobs → Offers | 01 link only | J09 |
| `/correspondence` | Correspondence primary; inbox/drafts/review | 01 link only | M01–M06 |
+1 -1
View File
@@ -24,7 +24,7 @@ Reconciled against [P4-06](../phase-4/p4-06/README.md#opendeferred-issue-reconci
| F01 / audit D01 stale CV revision (related profile/job revisions distinct) | Open version increments without expected revision guard | **Blocks P5-09–14 broad CV**; separately authorized integrity work with cross-client proof. Profile/job persistence changes likewise gated, but their unchanged page links are safe. No automatic B07 |
| Creation-intent idempotency | Open independent contract; not B02 identity or stale revision | **Separate backend/product work**; no Add/import/POST-on-mount expansion in Phase 5. Existing create review/no-write navigation must remain |
| CV margins/templates/preview/pagination | Open, user concern reiterated during P4; current preview has extra pagination/cropping logic | **Blocks P5-09–14** via dedicated G-CV-RENDER corpus/repair checkpoint; keyboard passing does not prove geometry. No broad renderer replacement inside UI slice |
| Table/Board filter/population mismatch | **Read prerequisite resolved in [P5-04b readiness](p5-04b-readiness/README.md)**: shared logical query, complete ID membership, owner/trash/derived filters and mutation refresh proven | **GO for P5-04b** with existing full-array scaling limits documented; integration itself remains unimplemented and must preserve query/route state |
| Table/Board filter/population mismatch | **Read prerequisite resolved in [P5-04b readiness](p5-04b-readiness/README.md)**: shared logical query, complete ID membership, owner/trash/derived filters and mutation refresh proven | [P5-04b integration](p5-04b/README.md) preserves that query/route contract; full-array scaling remains an explicit limitation |
| P3-O01 analytics names/periods/populations | Open source-confirmed semantic limitations | **Blocks P5-06/07 accurate presentation acceptance**; labels/values tests within those slices, backend metrics/data repair separate |
| F04/B06 production ingress | **Open**; repository/local checks are not deployed proof. Historical DNS/HTTPS observations do not prove actual peer/firewall boundary or current topology | **Production gate; does not block local P5 slices**. Operator evidence for actual Traefik peer, nginx trust, listeners/ports, direct/spoofed access, B04 client IP, firewall/NAT/IPv6, DNS/TLS/redirect and restart needed; no closure or credentials accessed here |
| Protected-main CI/browser runner and deployment | Unresolved remote-runner evidence; local tests pass | **Separate release gate**; feature-branch docs/UI push is not production deployment approval |
+1 -1
View File
@@ -13,7 +13,7 @@ Sources: [Phase 3 sequencing](../phase-3/PHASE4_IMPLEMENTATION_PLAN.md), [P4-06
| 3 — P5-02 | Global shell utilities | Interaction and visible UI; medium | P5-01; existing command and notification capabilities |
| 4 — P5-03 | Jobs Table and mobile cards | Major visible UI; high | P5-01/02, G-JOBS behavior fixtures; includes shared Trash consumer |
| 5 — P5-04a | Board presentation | Major visible UI; high | P5-03; keep `/kanban` and existing population |
| 6 — P5-04b | Table/Board workspace integration | Architecture/interaction; medium | **Blocked** on G-JOBS read/query parity and separately authorized contract work |
| 6 — P5-04b | Table/Board workspace integration | Architecture/interaction; medium | G-JOBS proven by separate readiness; [integration record](p5-04b/README.md) owns current acceptance |
| 7 — P5-06 | Dashboard presentation | Major visible UI; high | P5-01/02 and G-METRICS; need not wait for 04b |
| 8 — P5-07 | Existing-report Analytics destination | Presentation/refactoring; high | P5-06; exact existing report inventory/definitions and preference proof |
| 9 — P5-08a | Job header and Overview | Major visible UI; high | Jobs entry regression, G-WORKSPACE mobile proof; no package relocation |
+1 -1
View File
@@ -24,7 +24,7 @@ Exit: focused reproduction now passes, no general axe exclusions, final complete
## G-JOBS — before table/board consolidation
**Current query gate: GO after [P5-04b readiness](p5-04b-readiness/README.md).** Both existing endpoints now use one server query, the separate clients share URL interpretation, and native membership/refresh/ownership evidence passes. Full Board population remains O(N), not one Table page; see the explicit performance ceiling. Integration has not begun. The paragraphs below preserve the original prerequisite and why the readiness checkpoint was necessary.
**Current query gate: GO after [P5-04b readiness](p5-04b-readiness/README.md).** Both existing endpoints now use one server query and native membership/refresh/ownership evidence passes. [P5-04b integration](p5-04b/README.md) uses that unchanged contract in the shared workspace. Full Board population remains O(N), not one Table page; see the explicit performance ceiling. The paragraphs below preserve the original prerequisite and why the readiness checkpoint was necessary.
Before P5-03, extend PRES-J05/J06 behavioral coverage for saved-view create/select/delete, filtered selection, partial bulk failures, column/page preferences, custom-status URLs, Back/refresh, capture review without writes and 320px actions. Preserve current local Comfortable default; density is neither server-persisted nor a CV setting.
+1 -1
View File
@@ -1,6 +1,6 @@
# Phase 5 — Representative screens / major UI redesign plan
**Current successor: [P5-04b query readiness](p5-04b-readiness/README.md), GO for the shared-read prerequisite.** P5-01–P5-04a implementation records remain authoritative for their scopes. The separate Table and Board now share proven logical query membership; Table/Board integration has not begun. P5-02 manual screen-reader acceptance remains mandatory for P5-15 and does not block independent Jobs work. P2-D01, F04, native touch verification and recorded baseline timing observations remain open. B07 has not started.
**Current successor: [P5-04b Table/Board integration](p5-04b/README.md).** Jobs now has two URL-addressable views with shared filters, matching membership and a retained `/kanban` alias. The [query-readiness checkpoint](p5-04b-readiness/README.md) remains the backend contract evidence; P5-01–P5-04a records remain authoritative for their scopes. P5-02 manual screen-reader acceptance remains mandatory for P5-15. P2-D01, F04, native touch verification, Board scaling and recorded baseline timing observations remain open. P5-06 and B07 have not started.
Historical planning checkpoint: source `2a2f9e48052c562ef599825458d0d3a6f9f9fc61`, inspected on 2026-09-13 on `codex/ui-redesign-phase4`. That checkpoint was documentation-only; the successor record above owns implementation/validation status.
+105
View File
@@ -0,0 +1,105 @@
# P5-04b — Table/Board integration
Source checkpoint: `6fc8937701a073f89fb680235bce58029a27550b`, branch `codex/ui-redesign-phase4`. This slice implements only the approved [P5-04b plan](../PHASE5_PLAN.md). The [separate readiness checkpoint](../p5-04b-readiness/README.md) established matching-ID parity first; its backend contract, authorization, ordering and complete Board response are unchanged here.
## Structure and compatibility
- `/jobs` defaults to Table; `/jobs?view=table` and `/jobs?view=board` explicitly select presentation. Unknown view values safely use Table. No per-account presentation preference or SavedView schema is added.
- `/kanban` remains an authenticated route. Its replace redirect targets `/jobs`, sets `view=board` and retains all other query parameters, hash and router state. A conflicting `view=table` on the legacy **Board** URL is overwritten so historical Board links still mean Board. The alias does not add a history entry or redirect externally. All 31 route/compatibility patterns remain.
- The existing Jobs sidebar destination now covers both views; the separate Board child is removed. Discover, Reminders, Companies, Offers, Trash and other destinations remain. No provider/auth/permission change or command-catalogue expansion.
- App retains the shared heading and Add Job action. The existing `JobTable` is the bounded workspace owner: one responsive filter/saved-view toolbar, a labelled Table/Board link group, matching-result count, and either the original Table/mobile cards or `KanbanBoard`. A new wrapper/framework would duplicate the existing mature filter owner, so none was introduced.
- The view links have `aria-current="page"`, text labels, shared theme focus treatment and distinct filled/outlined states. They use native navigation links, support keyboard Enter and remain mounted across switches. Activating the current view is a no-op. New view choices push history; filter edits retain the established replace behavior. Back/Forward restores the recorded query/view.
## State and lifetime contract
Search, status (including raw custom values), company, location, follow-up, readiness, include-deleted scope and sort parameters survive switching. The Table's page stays in the URL, is ignored by the Board API parser, and is restored on return. Changing filters or applying a saved view resets the Table page as before. Board grouping/stage ordering still controls visual card placement; Table sort does not redefine Board columns.
Table selection is explicitly page/view-local: it clears when leaving or re-entering Table, including history traversal. Hidden selections cannot drive bulk actions. Comfortable/Compact remains local to the mounted workspace and survives a view switch; persisted page-size/column preferences keep their existing owner. Density/columns/pagination/bulk controls are Table-only. Trash always renders Table, even with a crafted `view=board` parameter.
Job opening still records the originating row/card on its history entry. Full workspace Back and browser Back restore the originating query and focus. Switching presentation clears only the transient `focusJobId` hint on the new history entry, preventing an old job-return hint from stealing focus from the switch; unrelated route state is retained.
## Loading and performance
Board code is lazy-loaded on first selection, with an accessible local fallback. Only the active results representation is mounted. The Table controller/filter owner remains mounted, but its `useViewResource` read is disabled while Board is active; it reloads on return. Table data/preferences can remain in local memory during the switch, not in a new shared/account cache. Board unmounts on leaving and reloads on return. It receives the existing creation refresh token, so Add Job refreshes whichever representation is active.
Board query edits debounce for 250 ms using the existing hook, avoiding a full read per keystroke. Initial Board entry reads immediately. One settled Board query uses one complete read; there is no Table-page crawl, arbitrary page size, hidden full-result preload or duplicate Table read. The native regression counts Jobs-result requests across both switch directions. Company-filter metadata still loads through the existing `useCompanies` owner and is now available in Board too; the one-read statement does not claim the entire application makes only one HTTP request. Reload/error behavior and status PATCH → membership reload remain unchanged.
**Residual ceiling:** Board still returns and renders the full matching array (O(N)); this integration does not add a result cap or virtualization. Server data can change between separate reads; matching-ID parity is the same-query/stable-data guarantee established by readiness, not a database snapshot across requests. Large-account virtualization/paging requires separate design work.
## Preservation traceability
This maps affected contracts, not exhaustive coverage of every branch in the 57-contract catalogue.
| Contract | Existing behavior → integration | Automated evidence | Visual/UX evidence |
|---|---|---|---|
| PRES-J03/J04 | Reviewed creation/capture → existing Add Job action now shared with Board, same modal and post-create refresh | Existing quick-capture/command/create regressions and extension checks; new active-view creation-refresh case | Shared Add Job entry visible in Table and Board screenshots; no new creation flow |
| PRES-J05 | Filters, saved views, sort/page/columns, Table/mobile actions → shared query owner and view links | `jobs-view-integration.test.tsx`, retained `job-table-density`, native `board-presentation` membership/history cases and `table-density` | Same filtered population, page-two return, desktop/mobile Table, EN/NB and both themes |
| PRES-J06 | Bulk/edit/Trash/restore → selection cleared at view boundary, no Board bulk UI | Existing partial-bulk/Table/Trash tests; new Trash view-parameter and selection-lifetime checks | Retained Table controls; density/browser suite |
| PRES-J07 | Full population, custom statuses, pointer/keyboard moves and precise menu → existing Board renderer below shared filters | Retained 15 Board unit cases; native move/failure/custom/filter tests; integration membership/count checks | Keyboard switch/drop/focus, custom query, empty/error/loading, narrow Board |
| PRES-W01/W02 | Open job/full workspace/Back and status progression → canonical query preserved | Native Table row Back and Board card Back; unchanged workspace/status tests | Focus returns to initiating row/card |
| PRES-E07 | Navigation, mobile shell and active destination → one Jobs item, Board alias remains | Native legacy replace/history/hash/state case; updated shell test now asserts Jobs current + Board switch current | Desktop/rail/mobile shell retained |
| PRES-E08 | Locale/theme/focus/error semantics → existing MUI tokens and labels | Full frontend/browser suites; integrated axe/focus checks | Light/dark × English/Bokmål, phone/tablet/desktop |
| PRES-E09 | Account/private-state disposal, authenticated reads → unchanged provider/API boundaries | Full B02/account isolation and backend parity/ownership regressions; native fixture ID ownership comparison | No new private storage or identity source |
| PRES-S03 | Page-size/column/theme/language preferences → existing mechanisms retained | Existing preference/density tests plus local density switch test | Comfortable/Compact retained in Table; no Board density claim |
## Files and scope
Application changes are limited to `src/App.tsx` (alias/sidebar route wiring), `components/JobTable.tsx` (existing shared owner and conditional renderer), `components/KanbanBoard.tsx` (embedded toolbar removal, debounce, active refresh/count), and `i18n/translations.ts` (EN/NB view/count labels and workspace subtitle). No backend, schema, query parser, drag/drop engine, authentication, theme, CV, package or production infrastructure change.
Tests: new `jobs-view-integration.test.tsx`; updated Board unit assertions move the old standalone switch responsibility to the integration fixture; `e2e/board-presentation.spec.ts` adds canonical routing/history and both-view evidence without removing movement/failure checks; `shell-readiness.spec.ts` reflects the approved single Jobs destination while retaining rail/mobile/heading-focus coverage. `kanban-theme.spec.ts` now polls the observable no-horizontal-scroll result after resize, allowing the shared responsive toolbar's React update to settle; it records the measured samples and still fails persistent overflow.
## Validation and evidence
Inherited baseline: 934 backend, 384 frontend, 76 actual browser passes + P2-D01 expected failure; rate-limit 9, ingress 6, PDF 1, configuration 3. Final validation is complete; no unexpected failures remain.
Six new frontend cases cover: both-direction history/page/density/selection and hidden-read behavior; custom-status membership; zero-result membership; shared Board filters; Trash isolation; and saved-query application plus active creation-refresh. The new native browser case proves legacy replacement (including conflicting view, hash and router state) and unknown-view fallback. Existing native Board coverage additionally exercises both-direction ID parity, page-two return, switch focus, one request per selected view, no-results/custom queries and four locale/theme combinations. Existing move/error/Back assertions remain.
| Check | Current result |
|---|---|
| Backend Release regression suite | 934 passed, unchanged |
| Frontend Jest suite | Final-code run: 390 passed in 78 suites, 119.9 seconds; 384 + 6 integration cases |
| Full native browser suite | 77 actual passes + unchanged P2-D01 expected failure, 9.8 minutes; 76 + 1 legacy-route case. Zero skipped, unexpected or flaky outcomes |
| Rate-limit / production-mode ingress / PDF admission | 9 / 6 / 1 passed, 10.3 / 6.4 / 7.7 seconds; unchanged |
| TypeScript / ESLint | Passed |
| Frontend production export / API Release `-warnaserror` | Passed; API zero warnings/errors |
| Ingress configuration | 3 passed |
| Supply-chain policy / Ollama evaluation / browser extension | 3 / 5 / 3 passed |
| Staged secret scan / whitespace / local Markdown targets | Passed; links check local files, not external URLs or anchor fragments |
Commands use the repository-required `rtk`/`rtk proxy` wrapper. UI commands: `npm.cmd test -- --runInBand --silent`, `npm.cmd run typecheck`, `npm.cmd run lint`, `npm.cmd run build`; build uses `NEXT_PUBLIC_API_BASE_URL=http://localhost:5302/api`, `CI=false`. Backend: `C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj -c Release --no-restore --logger 'console;verbosity=minimal'` and `build JobTrackerApi/JobTrackerApi.csproj -c Release --no-restore -warnaserror`. Offline checks: `python scripts/test-ingress.py`, `python scripts/test-supply-chain.py`, `python scripts/test-ollama-evaluation.py`, `node --test browser-extension/tests/*.test.mjs`, `python scripts/supply-chain.py scan-secrets`, `git diff --check`, `git diff --cached --check`.
Native browser command: `npm.cmd run test:e2e -- --reporter=line,json`, with `DOTNET_ROOT=C:/Users/Connor/.dotnet`, `DOTNET_HOST_PATH=C:/Users/Connor/.dotnet/dotnet.exe`, `PLAYWRIGHT_STATIC_EXPORT=true`, `PLAYWRIGHT_PREBUILT_EXPORT=true`, `PLAYWRIGHT_JSON_OUTPUT_NAME=test-results/integration-accepted.json`. Security commands ran sequentially against the same local API port with the same .NET environment: `npm.cmd run test:rate-limits -- --reporter=line`, `npm.cmd exec playwright test -- --config=playwright.ingress.config.ts --reporter=line`, `npm.cmd run test:pdf-admission -- --reporter=line`. These are local regressions, not production ingress proof.
### Rendered visual/interaction review
Evidence is synthetic local data captured through the actual API + exported application, not mocked UI screenshots. Reviewed the actual rendered images for readable hierarchy, status labels, restrained shared surfaces, wrapping, selected links, focus and result context:
Capture date: **2026-09-29**, local Playwright Chromium, standard synthetic owner (27 fixture jobs including one custom stage), EN/Bokmål and current test clock; no real user data or provider. The [readiness screenshots](../p5-04b-readiness/README.md) and [P5-04a record](../p5-04a/README.md) are the pre-integration reference. This is reviewed state evidence, not a clock-frozen pixel-diff claim. Existing fixture viewport heights are retained (320×720, 768×900, 1024×900); the broader Phase 5 visual protocol's other heights/1920-wide matrix is not newly certified by this bounded slice. Resolve this implementation's SHA with `git log -1 -- docs/redesign/phase-5/p5-04b/README.md`, avoiding a self-referential hash placeholder.
- Desktop 1440×900: [Table light/EN](evidence/integrated-table-desktop-light-en.png), [Board light/EN](evidence/board-desktop-light-en.png), [Table dark/NB](evidence/integrated-table-desktop-dark-nb.png), [Board dark/NB](evidence/board-desktop-dark-nb.png).
- Phone 390×844: [Table light/EN](evidence/integrated-table-phone-light-en.png), [Board light/EN](evidence/board-phone-light-en.png), [Table dark/NB](evidence/integrated-table-phone-dark-nb.png), [Board dark/NB](evidence/board-phone-dark-nb.png). All four theme/language combinations are captured in the native test output; this committed set retains representative pairs.
- Narrow 320×720: [Board dark/NB](evidence/board-phone-320-dark-nb.png), with wrapped follow-up label and retained filter/switch access. Native overflow assertions also cover 768 and 1024 widths. Desktop Table retains its established internal horizontal scrolling for optional columns/actions; this is not page-level overflow.
- Shared query: [24 matching Board jobs with keyboard switch focus](evidence/integrated-filtered-board-keyboard.png), [page two of that same query](evidence/integrated-filtered-table-page-two.png), [custom status](evidence/integrated-custom-status-board.png), [zero results](evidence/board-zero-query-light-en.png).
- [Retryable error](evidence/board-error-light-en.png) and [empty state](evidence/board-empty-light-en.png). Lazy loading and actual network loading are both exercised; retry does not fall back to an unfiltered read.
Native keyboard automation verifies Enter on the view link keeps focus on that same control after content replacement; the screenshot shows the Phase 4 focus ring. Existing pointer/keyboard move, custom-stage menu, failed-write, row/card Back and shell drawer checks remain active. These are automated browser interactions plus human-style screenshot review by the agent, not a manual screen-reader session. The inherited post-axe missing-glyph screenshot artifact remains an evidence limitation; no typography/icon fix was smuggled into integration.
Development checks found and corrected test-only label/matcher/type assumptions. The old loading fixture initially observed the new lazy-code fallback before its network handler existed; it now waits for the actual Board request before releasing its simulated error. No production behavior was weakened to make that fixture pass.
The first full browser run (13.2 minutes) had 73 actual passes + P2-D01 expected failure and four unexpected Table-density failures (one per theme/locale). The added result summary duplicated the existing visible loading message: `main.getByText(t.loading, { exact: true })` found two elements at `table-density.spec.ts:235`. The summary now reports only settled results; the established results area owns loading/error feedback. The original four assertions were left unchanged. This was an integration regression, not inherited debt or an expected failure.
The [next browser run](evidence/second-browser-summary.json) (10.1 minutes) passed all four unchanged Table-density cases and had 76 actual passes + P2-D01 expected failure, with one unexpected failure: the old immediate post-resize Board assertion read 27px horizontal scroll at 375px. Its failure screenshot showed the settled mobile toolbar fitting the viewport; the same test had passed in the first full run. Integration adds a `useMediaQuery`-driven shared toolbar, so reading the frame immediately after `setViewportSize` is not a stable readiness check. The assertion now uses bounded Playwright polling with the same zero-scroll expectation and records samples. No application overflow-hiding rule or relaxed threshold was added.
Three focused repetitions passed after that test correction: [measured resize samples](evidence/resize-samples.json) were **[27, 0], [27, 0], [0]**. This independently confirms the brief pre-reflow measurement and subsequent zero overflow, rather than merely obtaining a lucky passing rerun.
The [final full browser result](evidence/final-browser-summary.json) records **77 actual passes plus P2-D01's unchanged expected failure**, with no retries, unexpected failures or skipped cases. Its resize sample is `[0]`. The fixture retains all prior Board movement/failure and Table density assertions.
**Accessibility evidence limits:** final Board phone axe checks reported no violations but left `color-contrast` incomplete for eight nodes in each theme. The empty Board check left six contrast nodes and one `aria-prohibited-attr` node incomplete. These are unresolved automated checks, not passes or screen-reader acceptance. Keyboard/focus regressions pass and rendered screenshots were inspected; manual spoken-name/live-state acceptance remains mandatory for P5-15. No existing expected failure or incomplete check was reclassified to obtain this checkpoint.
## Open acceptance items / stop
Keep open: P5-02 manual screen-reader spoken names/live-state acceptance for P5-15, native touch-drag verification, P2-D01 expected failure/native package proof, F04 production ingress evidence, Board full-array scaling, and readiness R01/R02 command-focus/CV baseline observations. Automated axe/keyboard checks do not close manual screen-reader/touch requirements. Other inherited debt remains with its existing owner.
P5-06, P5-05's unapproved quick preview, CV prerequisites and B07 are outside this slice. Stop after the separate integration checkpoint; no subsequent implementation is authorized by this record.
**P5-04b acceptance: complete within the approved scope.** The shared-query prerequisite remains satisfied; native membership, history, alias, active-view request and focus evidence prove the integration. No integration blocker remains. The open items above retain their separate acceptance owners; completion does not certify production ingress, native touch or manual screen-reader behavior.
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -0,0 +1,689 @@
{
"stats": {
"startTime": "2026-09-29T20:46:15.719Z",
"duration": 588417.8189999999,
"expected": 78,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"actualPasses": 77,
"expectedFailures": [
{
"title": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change",
"expected": "failed",
"outcome": "expected",
"actual": [
"failed"
]
}
],
"unexpected": [],
"boardAxe": [
{
"name": "board-phone-light-axe",
"violations": [],
"incomplete": [
{
"id": "color-contrast",
"nodes": 8
}
]
},
{
"name": "board-phone-dark-axe",
"violations": [],
"incomplete": [
{
"id": "color-contrast",
"nodes": 8
}
]
},
{
"name": "board-empty-light-en-axe",
"violations": [],
"incomplete": [
{
"id": "aria-prohibited-attr",
"nodes": 1
},
{
"id": "color-contrast",
"nodes": 6
}
]
}
],
"mobileResizeScrollSamples": [
[
0
]
],
"cases": [
{
"title": "public entry points meet automated WCAG A and AA checks",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "primary authenticated workspaces meet automated WCAG A and AA checks",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "retained profile request from A cannot write using B cookies and fresh B CSRF",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "missing and forged session contexts fail closed while same-account profile saves work",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "crafted CV identifiers cannot cross read update delete or job-association ownership",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E05 E07 E08] account switch disposes open command, account and notification surfaces",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "two tabs discard A's private form before B can use it, including Back navigation",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J07 J05 W01 W02 E07 E08 E09] Board query membership matches Table and preserves moves, focus and route",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J05 J07 E07 W01] legacy Board replaces history and preserves query, hash and route state; default Jobs stays Table",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J07 E08] Board loading, retryable error and fully empty columns",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-C06 PRES-C07 PRES-C10 PRES-E08] light/en preview keyboard, pagination and responsive state",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-C06 PRES-C07 PRES-C10 PRES-E08] dark/nb preview keyboard, pagination and responsive state",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-C06 PRES-C07 PRES-C10 PRES-E08] light/nb preview keyboard, pagination and responsive state",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-C06 PRES-C07 PRES-C10 PRES-E08] dark/en preview keyboard, pagination and responsive state",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "CSV export has safe cells and headers, and browser download preserves its UTF-8 bytes",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "discovery remains usable across widths and opens the reviewed import",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "kanban columns use dark theme surfaces",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] light/en/1440 named controls, modal keyboard and retained draft",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] dark/nb/1440 named controls, modal keyboard and retained draft",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] light/nb/390 named controls, modal keyboard and retained draft",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] dark/en/390 named controls, modal keyboard and retained draft",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-C01 PRES-C06 PRES-C07 PRES-C10] mobile CV override persists without changing the canonical profile or sibling CV",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change",
"expected": "failed",
"outcome": "expected",
"actual": [
"failed"
]
},
{
"title": "[PRES-S03 PRES-W11] responsive settings navigation keeps rule edits and persists notification preferences",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-S03] rule changes persist through the real API",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-W01 PRES-J04] keyboard command navigation and legacy workspace entry preserve the selected job",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-A01 PRES-S04 PRES-E07] non-admin navigation cannot grant API privileges or unlock CV AI",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] light/en/1440 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] light/en/390 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] light/nb/1440 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] light/nb/390 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-E08 PRES-J05 PRES-J07] light loaded status semantics, navigation and command focus",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-C06 PRES-C07 PRES-C08 PRES-C09 PRES-C11 PRES-S03] light loaded CV tabs, selects and settings",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] dark/en/1440 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] dark/en/390 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] dark/nb/1440 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-J08] dark/nb/390 loading \u00e2\u2020\u2019 error \u00e2\u2020\u2019 retry \u00e2\u2020\u2019 empty \u00e2\u2020\u2019 populated",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 PRES-E08 PRES-J05 PRES-J07] dark loaded status semantics, navigation and command focus",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E08 PRES-C06 PRES-C07 PRES-C08 PRES-C09 PRES-C11 PRES-S03] dark loaded CV tabs, selects and settings",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 E08 E09 S03 S04 S05 J05 J10 M06 W11] light/en Settings headings, reflow and retained actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 E08 E09 S03 S04 S05 J05 J10 M06 W11] light/nb Settings headings, reflow and retained actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 E08 E09 S03 S04 S05 J05 J10 M06 W11] dark/en Settings headings, reflow and retained actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-E07 E08 E09 S03 S04 S05 J05 J10 M06 W11] dark/nb Settings headings, reflow and retained actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 E08 A03] light-en mobile labels, focus and admin reflow",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 J03 J08] light-en command list, keyboard and no-write actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-02 PRES-E07 E08 E09 S02] light-en utility search and notification states",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E08 C06 S05] light-en real Tooltip contrast and open-toast action access",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-01 PRES-E07 E08 A03] light-en grouped shell, rail menu and route focus",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 E09 C06 S02 S03] light-en dirty editor survives shell utilities and cancel",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 E08 A03] light-nb mobile labels, focus and admin reflow",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 J03 J08] light-nb command list, keyboard and no-write actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-02 PRES-E07 E08 E09 S02] light-nb utility search and notification states",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E08 C06 S05] light-nb real Tooltip contrast and open-toast action access",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-01 PRES-E07 E08 A03] light-nb grouped shell, rail menu and route focus",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 E08 A03] dark-en mobile labels, focus and admin reflow",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 J03 J08] dark-en command list, keyboard and no-write actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-02 PRES-E07 E08 E09 S02] dark-en utility search and notification states",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E08 C06 S05] dark-en real Tooltip contrast and open-toast action access",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-01 PRES-E07 E08 A03] dark-en grouped shell, rail menu and route focus",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 E08 A03] dark-nb mobile labels, focus and admin reflow",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 J03 J08] dark-nb command list, keyboard and no-write actions",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-02 PRES-E07 E08 E09 S02] dark-nb utility search and notification states",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E08 C06 S05] dark-nb real Tooltip contrast and open-toast action access",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-01 PRES-E07 E08 A03] dark-nb grouped shell, rail menu and route focus",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[P5-00 PRES-E07 E09 C06 S02 S03] dark-nb dirty editor survives shell utilities and cancel",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "API liveness and database readiness are separate public probes",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "public plans stay honest, responsive and keyboard accessible",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "login establishes an authenticated session",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "a Free account keeps manual work available while AI actions stay honestly locked",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "a saved job can be created through the reviewed UI flow",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "the dedicated application workspace survives deep links, long data and unsaved navigation",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "Career Workspace loads from the authenticated application shell",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "a public CV renders anonymously and downloads as PDF",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "the Code template exports a long structured CV as searchable multi-page PDF",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J05 J06 W01 W02 S03 E08 E09] light/en table and cards preserve behavior at both densities",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J05 J06 W01 W02 S03 E08 E09] light/nb table and cards preserve behavior at both densities",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J05 J06 W01 W02 S03 E08 E09] dark/en table and cards preserve behavior at both densities",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
},
{
"title": "[PRES-J05 J06 W01 W02 S03 E08 E09] dark/nb table and cards preserve behavior at both densities",
"expected": "passed",
"outcome": "expected",
"actual": [
"passed"
]
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

@@ -0,0 +1,23 @@
{
"stats": {
"startTime": "2026-09-29T20:45:27.001Z",
"duration": 18374.364,
"expected": 3,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"mobileScrollSamples": [
[
27,
0
],
[
27,
0
],
[
0
]
]
}
@@ -0,0 +1,67 @@
{
"stats": {
"startTime": "2026-09-29T20:34:53.673Z",
"duration": 608707.245,
"expected": 77,
"skipped": 0,
"unexpected": 1,
"flaky": 0
},
"actualPasses": 76,
"expectedFailures": [
{
"title": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change",
"expected": "failed",
"outcome": "expected",
"actual": [
"failed"
]
}
],
"unexpected": [
{
"title": "kanban columns use dark theme surfaces",
"expected": "passed",
"outcome": "unexpected",
"actual": [
"failed"
]
}
],
"boardAxe": [
{
"name": "board-phone-light-axe",
"violations": [],
"incomplete": [
{
"id": "color-contrast",
"nodes": 8
}
]
},
{
"name": "board-phone-dark-axe",
"violations": [],
"incomplete": [
{
"id": "color-contrast",
"nodes": 8
}
]
},
{
"name": "board-empty-light-en-axe",
"violations": [],
"incomplete": [
{
"id": "aria-prohibited-attr",
"nodes": 1
},
{
"id": "color-contrast",
"nodes": 6
}
]
}
]
}