test(redesign): establish preservation baseline

Map 57 capability groups before restructuring. Add behavioral regression coverage and a standalone TypeScript gate; retain the native SQLite package failure as separate baseline debt.
This commit is contained in:
cesnimda
2026-09-10 12:53:06 +02:00
parent 2d0f131a99
commit d6d3dd977d
14 changed files with 835 additions and 3 deletions
+2
View File
@@ -1,5 +1,7 @@
# Phase 1 — Frontend audit
Successor checkpoint: [Phase 2 preservation matrix, regression results and traceability](../phase-2/README.md), based on the completed Phase 1 commit `2d0f131`. The historical audit below is retained; no visual redesign has started.
Date: 2026-09-09. Source checkpoint: `97fce89c002fe86e737ca7387170321d464b80d7` (application changes through `0954876`; subsequent commits contain the brief and CI prerequisite corrections). Audit branch: `codex/ui-redesign-audit`. Test-only packaging correction `23cc250` leaves the frontend census unchanged; its fresh 22 PDF and 915 broader backend passes are recorded in the test assessment.
**Phase 1 source audit complete; redesign implementation has not started.** The repository already implements much of the proposed workflow. Retain its MUI/React foundation and domain contracts, improve shared semantics, then migrate representative screens in small steps. A replacement frontend framework or component library is not justified by the observed problems.
+68
View File
@@ -0,0 +1,68 @@
# Phase 2 baseline defects and intentional gaps
Application source is unchanged from `2d0f131`. No defect below was fixed as part of the preservation checkpoint.
## P2-D01 — SQLite tailoring and submitted-package capture fail
**Confirmed in the disposable running local API, not production.** The new [browser regression](../../../job-tracker-ui/e2e/redesign-preservation.spec.ts) creates a real non-admin account, canonical profile, company/job, attached CV, cover letter and UTF-8 attachment. It opens the existing legacy job URL, then clicks **Freeze current package** in the **CV section** (not the cover-letter section).
Observed:
| Request | Result |
|---|---|
| Profile/job/CV/letter/file fixture writes | Successful, including B02 session preconditions |
| GET job submitted-packages | 200, empty list |
| GET job tailoring | 500 |
| POST job submitted-packages | 500; no successful package row shown |
| API exception | `System.NotSupportedException: SQLite does not support expressions of type 'DateTimeOffset' in ORDER BY clauses.` |
Stack evidence points to [ApplicationAssetsService](../../../JobTrackerApi/Services/ApplicationAssetsService.cs), `GetTailoringPlanAsync` (ordering verified CareerEvidence by UpdatedAtUtc at line 182), and [SubmittedApplicationPackageService](../../../JobTrackerApi/Services/SubmittedApplicationPackageService.cs), `CaptureAsync` (ordering variants by UpdatedAtUtc at line 67). These paths do not use the SQLite-safe ordering used in some nearby services. Existing [SqliteDateTimeOffsetCompatibilityTests](../../../JobTrackerApi.Tests/SqliteDateTimeOffsetCompatibilityTests.cs) exercise other ordering paths; they do not certify these two. Existing [SubmittedApplicationPackageTests](../../../JobTrackerApi.Tests/SubmittedApplicationPackageTests.cs) prove snapshot/owner/failure contracts with test seams, not successful native SQLite execution of this query.
The new desired success test is retained with an explicit `test.fail` annotation activated **after fixture and navigation setup, only for the observed capture HTTP 500**. Playwright reports an expected failure as expected execution; this is **not** a successfully frozen package. Post-capture checks for unchanged archived HTML/letter and exact attachment bytes after deleting the current source are present but **not reached**. Do not count them as achieved coverage. A successful capture runs all later assertions as ordinary tests; setup, non-500 responses and subsequent archive failures cannot be masked by the annotation. Remove the narrow annotation and update this classification only with the separately scoped fix and successful native evidence.
Initial fixture error: the first draft looked for package capture under the cover-letter tab; inspection showed the existing capture lives under CV, and the test was corrected. That locator error is not an application defect.
Scope/next owner: a separate bounded provider-compatibility repair and native storage verification before any package/tailoring redesign. Preserve timestamps/ownership and MariaDB behavior; no schema change is presumed. Phase 2 neither changes ordering nor claims the same failure in MariaDB/production. All original 916 backend and 298 frontend cases remain retained.
Local diagnostic command (PowerShell, from job-tracker-ui, after the documented build):
```powershell
$env:DEBUG='pw:webserver'
node node_modules/@playwright/test/cli.js test e2e/redesign-preservation.spec.ts
```
The full debug log is local ignored evidence, `.artifacts/phase2-browser-focused.log`; it is not committed wholesale. It contains synthetic accounts only. The exception/request facts above are the durable evidence. Use the normal commands in [README](README.md) to reproduce with an isolated data directory; never substitute production URLs.
## P2-O01 — one rules-save HTTP 500, not independently reproduced
The first browser run sent the valid rule object with appliedFollowUpDays=5 and received 500; a subsequent GET still returned 14. The visible draft retained 5. Response contained a generic problem and trace ID; that run did not retain the server exception, so the cause is unknown.
An isolated authenticated direct PUT then returned 204 and persisted 5. A repeat of the original mobile→desktop browser save with explicit response observation also returned 204 and persisted 5. **No rules regression is expected-failed or skipped.** Both successful browser/direct saves remain ordinary permanent tests. Do not claim a confirmed root cause from one transient result. If it recurs, collect the server exception/trace before proposing a fix. Failed notification-save UI retention is independently covered with a deterministic transport failure.
## Audit precision: workspace overlay and admin route
The current source has a reusable ApplicationWorkspace with override/onClose/full-page-link props, but the production call-site search finds only its normal full-page wrapper. Preserve the reusable contract; do not claim the test named application-workspace-overlay exercises a mounted production quick-preview host. A future overlay needs its own close/dirty/focus tests before adoption.
Non-admin navigation hides admin destinations. A crafted admin URL can render the page shell; the API returns 403 and no user list is exposed. The browser test verifies this established boundary, not a nonexistent frontend route-denial screen.
## Existing debt remains separate
The [Phase 1 risks](../audit/RISKS_AND_MIGRATION.md), [baseline summary](../audit/PHASE1_SUMMARY.md) and [validated queue](../../audits/2026-09-07/validation/implementation-queue.md) remain authoritative for prior findings:
- Stale CV revision overwrites, creation idempotency, calendar/timezone correctness, restore/rollback readiness, billing/deletion and operational failures are not resolved by redesign tests.
- Shared contrast/focus, builder preview scrolling and incomplete loaded accessibility/manual testing remain open. No axe/WCAG certification is added.
- Historical TS2571 was corrected before Phase 2; it does not recur. This checkpoint adds the explicit full src/app standalone type gate without relaxing strictness. Its existing tsconfig scope includes Jest files, not all Playwright/config files.
- Main CI run 743's worker SIGSEGV/retry timeout/closed-browser failures and skipped deployment remain unresolved runner evidence. A local passing suite and feature-branch push do not close this release blocker.
- **B06 implementation complete; F04 remains open.** Actual Traefik peer, nginx/API runtime listeners, firewall/NAT/IPv6 exposure, forwarded client IP, DNS/TLS/redirect and restart behavior still need the [operator handoff](../../audits/2026-09-07/validation/b06-completion.md). No production credentials accessed or live tests run here.
## Intentional gaps by deadline
| Deadline | Evidence still required |
|---|---|
| Before shell/Jobs restructuring | Mobile drawer focus/return, saved view CRUD, bulk partial failures/trash restore, capture/legacy entries; matrix E07/J04/J05/J06/W01 |
| Before CV/package restructuring | Native capture/tailoring success, item-specific override reset/source edit, browser history restore, loaded preview keyboard and template/control combinations; C07–C10/W05/W07 |
| Before career import restructuring | Low-confidence selection/discard, real unusual document extraction and error recovery; C03 |
| Before mail/settings/admin restructuring | Provider sandbox reconnect/delivery; persisted draft conflict/uncertain-send retained; session list UI, audit undo/restore, dashboard toggle ownership; E05/M01–M06/S02/A02 |
| Before public release | Manual assistive technology/touch/zoom/reflow; EN/NB and both themes; provider/DNS/TLS/firewall/backup restoration; original CI runner remediation |
These gaps permit Phase 3 planning, not unguarded production restructuring of the affected capability.
@@ -0,0 +1,223 @@
# Phase 2 preservation matrix
Baseline: **`2d0f131`**, the [57-group Phase 1 ledger](../audit/FUNCTIONALITY_INVENTORY.md). `PRES-E01` is a stable alias of `E01`, and similarly for all rows; original IDs retain their meaning. No capability has been removed, merged or deprecated. Each row includes all sub-capabilities in its linked baseline group, even when its short label abbreviates them.
## Measurement and limits
**57/57 groups (100%) have mapped automated behavioral evidence for at least one core behavior.** This is group-level preservation coverage, not statement coverage, exhaustive sub-workflow coverage, visual parity or 100% readiness. Every row's remaining gaps are explicit. A passing mock/service test does not prove a real provider, actual browser persistence, or production. In particular W07 retains passing service/component evidence but its new native SQLite capture test is an **expected failure**, not successful end-to-end preservation proof. See [baseline defects](BASELINE_DEFECTS.md).
`H` = identity/data loss/irreversible action or a high-risk shared navigation/editing surface; `M` = important reversible presentation/workflow risk. These are redesign regression risks, not security severity labels. “Touch” is expected later-phase impact, not implementation authorization. `F` links are Jest component/helper tests; `B` links are backend tests. Named behaviors describe assertions, not mere file existence. The existing App.test harness is deliberately not counted as route proof.
New browser tests live in [redesign-preservation.spec.ts](../../../job-tracker-ui/e2e/redesign-preservation.spec.ts); original [smoke](../../../job-tracker-ui/e2e/smoke.spec.ts), [account isolation](../../../job-tracker-ui/e2e/account-isolation.spec.ts), and special B01–B06 suites stay unchanged. The [full original test census](../audit/TEST_FILES.md) supplies secondary coverage beyond the representative tests mapped below.
| Preservation ID / capability | Route / entry | Frontend; backend owners | Automated tests and protected behavior | Missing evidence / deliberate gap | Risk | Expected redesign touch |
|---|---|---|---|---|---|---|
| **PRES-E01** — Public product/plans; honest unavailable billing | `/` | LandingPage, planCatalog; AccountPlans | [F:landing-page][F:landing-page.test.tsx], [F:planCatalog][F:planCatalog.test.ts], [F:LandingPage.authRedirect][F:LandingPage.authRedirect.test.tsx]; [B:AccountPlans][B:AccountPlansTests]. Free/Pro copy, unavailable checkout and authenticated redirect | Actual checkout/provider availability; public mobile/keyboard review | M | Yes — public entry |
| **PRES-E02** — Local login/register/remember, challenge, reset and verification | `/login; /register; /forgot-password; /reset-password; /verify-email` | LoginPage, TurnstileWidget, VerifyEmailPage; AuthController | [F:login-page][F:login-page.test.tsx], [F:verify-email-page][F:verify-email-page.test.tsx], [F:turnstile-widget][F:turnstile-widget.test.tsx]; [B:LocalAuthIdentity][B:LocalAuthIdentityTests], [B:AuthAndSystemController][B:AuthAndSystemControllerTests]. Configuration gates, two-factor branch, safe redirect, verification outcomes; smoke login | Real reset-email delivery, Turnstile widget/browser configuration, complete reset submit journey | H | Yes — entry forms |
| **PRES-E03** — Google/Microsoft login, link, legacy relink and popup results | `/login; /microsoft-legacy-relink; provider callbacks` | GoogleAuthCard, MicrosoftAuthCard, MicrosoftLegacyRelinkPage; token validators | [F:login-page][F:login-page.test.tsx], [F:microsoft-legacy-relink-page][F:microsoft-legacy-relink-page.test.tsx]; [B:GoogleTokenValidator][B:GoogleTokenValidatorTests], [B:MicrosoftTokenValidator][B:MicrosoftTokenValidatorTests], [B:LocalAuthIdentity][B:LocalAuthIdentityTests]. Provider failure/relink presentation and token validation | Real consent/popups, revoked grants, provider sandbox; callbacks must retain origin/state | H | Yes — account entry |
| **PRES-E04** — 2FA challenge/recovery/setup/disable; trusted-device revocation | `/profile; /login` | TwoFactorSettingsCard, TwoFactorChallenge; TwoFactorController | [F:two-factor-settings][F:two-factor-settings.test.tsx], [F:login-page][F:login-page.test.tsx]; [B:TwoFactorController][B:TwoFactorControllerTests], [B:SessionsController][B:SessionsControllerTests]. Setup/recovery presentation, disable failure/retry; server trusted-device/session checks | Real mobile authenticator/recovery and trusted-device UI traversal | H | Yes — security forms |
| **PRES-E05** — Session list/current device, revoke one/others, logout | `/profile; shell user menu` | SessionsSettingsCard, AppShell, auth; SessionsController | [F:session-boundary][F:session-boundary.test.ts], [F:account-scoped-state][F:account-scoped-state.test.tsx]; [B:SessionsController][B:SessionsControllerTests], [B:AuthSessionRevocation][B:AuthSessionRevocationTests]. Own active sessions only, revoke ownership and next-request invalidation; B02 browser logout | Session-list card UI selection/refresh after remote revoke | H | Yes — shell/account |
| **PRES-E06** — Avatar, account names/headline, email change and password | `/profile; /confirm-email-change` | ProfilePage; AuthController, AvatarStorage | [F:profile-page][F:profile-page.test.tsx], [F:verify-email-page][F:verify-email-page.test.tsx]; [B:AvatarStorage][B:AvatarStorageTests], [B:LocalAuthIdentity][B:LocalAuthIdentityTests]. Email change password/confirmation contract; safe avatar storage and identity endpoints | Avatar upload/remove and password-change browser journeys | H | Yes — account/profile separation |
| **PRES-E07** — Desktop collapse/mobile drawer, active nav and command search/actions | `Shell; Ctrl/Cmd+K` | AppShell, QuickCommandDialog; job/company search APIs | [F:sidebar-active-nav][F:sidebar-active-nav.test.ts], [F:app-shell-notifications][F:app-shell-notifications.test.tsx], [F:quick-command-preservation][F:quick-command-preservation.test.tsx]; [B:JobApplicationsAuthorization][B:JobApplicationsAuthorizationTests], [B:CompanyRelationship][B:CompanyRelationshipTests]. Active matching and notification entry; NEW job/company destinations, reviewed add and search reset; NEW browser keyboard navigation | Drawer focus return and collapse persistence in EN/NB; all command destinations before shell migration | H | Yes — first restructuring target |
| **PRES-E08** — Theme/system, EN/NB hydration, toast/confirm/prompt and errors | `Shell; preferences; fallback routes` | themePrefs, I18nProvider, confirm, prompt; auth preference | [F:theme-state][F:theme-state.test.tsx], [F:i18n-provider][F:i18n-provider.test.tsx], [F:confirm][F:confirm.test.tsx], [F:prompt][F:prompt.test.tsx], [F:dialog-flow][F:dialog-flow.test.tsx]; [B:LocalAuthIdentity][B:LocalAuthIdentityTests]. Hydrated theme/language, confirmation/cancellation and dialog behavior | Not-found/error-boundary retry route; full locale/theme/state cross-product and OS theme changes | M | Yes — shared foundations |
| **PRES-E09** — Account-switch private-state disposal and stale request rejection | `All private routes; tabs/BFCache/focus` | App, api, sessionBoundary; SessionContextMiddleware | [F:session-boundary][F:session-boundary.test.ts], [F:account-scoped-state][F:account-scoped-state.test.tsx]; [B:SessionContextMiddleware][B:SessionContextMiddlewareTests], [B:CurrentUserIdLiveEvaluation][B:CurrentUserIdLiveEvaluationTests], [B:OwnershipGuard][B:OwnershipGuardTests]. B02 stale mutation/read abort, account-scoped state; four real-API/two-tab account-isolation browser cases | Real BFCache variations and long offline retry; preserve server precondition even with old bundles | H | Yes — all shared state |
| **PRES-J01** — NAV discovery/filter/sort/source/deadline/details | `/discover` | JobDiscoveryPage; JobDiscoveryController | [F:job-discovery][F:job-discovery.test.tsx]; [B:JobDiscoveryController][B:JobDiscoveryControllerTests], [B:JobOpportunitySync][B:JobOpportunitySyncTests]. Search/sort/source details, empty versus failure/retry; responsive discovery browser | Live NAV freshness/API availability; long result keyboard traversal | M | Yes — jobs entry |
| **PRES-J02** — Saved searches, run/delete/alerts, result changes/dismissal | `/discover` | JobDiscoveryPage; saved-search/alert services | [F:job-discovery][F:job-discovery.test.tsx]; [B:SavedJobSearchAlert][B:SavedJobSearchAlertTests], [B:JobDiscoveryController][B:JobDiscoveryControllerTests]. Saved search run, pause and dismiss controls; owner-scoped alert results | Scheduler-to-notification browser journey, delete confirmation on mobile | M | Yes — discovery workspace |
| **PRES-J03** — Reviewed manual/URL/paste job create, company/tags/dates, duplicates | `Shell AddJobModal` | AddJobModal; JobImportService, JobApplicationsController | [F:quick-capture][F:quick-capture.test.tsx]; [B:JobImportService][B:JobImportServiceTests], [B:JobImportHttpTransport][B:JobImportHttpTransportTests], [B:JobApplicationsController][B:JobApplicationsControllerTests]. Preview before write, URL prefills, manual browser create; B01 real connection boundary | Duplicate warning and company/date edge UI; creation-intent idempotency remains separate unresolved contract | H | Yes — capture/navigation |
| **PRES-J04** — Extension/bookmarklet/share capture; post-create attachment/CV | `?add= / ?addtext=; QuickCaptureCard; browser-extension` | App, captureUrl, QuickCaptureCard; job/CV APIs | [F:captureUrl][F:captureUrl.test.ts], [F:quick-capture][F:quick-capture.test.tsx], [F:quick-command-preservation][F:quick-command-preservation.test.tsx]; [B:JobImportService][B:JobImportServiceTests], [B:CvBuilder][B:CvBuilderTests]. Capture URL encoding/review/no auto-create, post-create CV; extension node tests; NEW keyboard add opens review only | Installed extension permissions/browser-share flow and optional attachment failure recovery | H | Yes — entry contracts |
| **PRES-J05** — Job filters/sort/page/columns, saved views and row/mobile actions | `/jobs` | JobTable, SavedViewsMenu; JobApplicationsController | [F:application-workspace-overlay][F:application-workspace-overlay.test.tsx], [F:account-scoped-state][F:account-scoped-state.test.tsx], [F:daily-control-loop][F:daily-control-loop.test.tsx]; [B:JobApplicationsController][B:JobApplicationsControllerTests], [B:JobApplicationsEndpointBehavior][B:JobApplicationsEndpointBehaviorTests]. URL hydration, selection does not open row, list return/focus; browser dirty/full workspace | Saved-view CRUD browser journey, page-size changes with dirty nested state | H | Yes — jobs view consolidation |
| **PRES-J06** — Bulk status/delete, soft delete/trash/restore and job edit | `/jobs; /trash; EditJobDialog` | JobTable, EditJobDialog; job lifecycle/controller | [F:application-workspace-overlay][F:application-workspace-overlay.test.tsx], [F:confirm-flow][F:confirm-flow.test.tsx]; [B:JobApplicationsController][B:JobApplicationsControllerTests], [B:JobApplicationsAuthorization][B:JobApplicationsAuthorizationTests], [B:JobLifecycleEvent][B:JobLifecycleEventTests]. Selection and destructive confirmation primitive; server CRUD/ownership/lifecycle behavior | Bulk partial failure and trash→restore UI journey; shared confirm tests alone do not prove bulk flow | H | Yes — table/actions |
| **PRES-J07** — Kanban grouped statuses, pointer/keyboard move and precise menu | `/kanban` | KanbanBoard, pipeline; status endpoint | [F:kanban-grouped-board][F:kanban-grouped-board.test.tsx], [F:pipeline][F:pipeline.test.ts]; [B:JobPipeline][B:JobPipelineTests]. Keyboard pickup/drop, failed move keeps card, custom group and precise stages; dark browser test | Touch drag, keyboard cancel/focus after responsive view switching | H | Yes — table/board unified entry |
| **PRES-J08** — Company/contact edits, pipeline dates and linked-job history | `/companies; ?edit=id` | CompaniesTable; company relationship APIs | [F:companies-relationship][F:companies-relationship.test.tsx], [F:quick-command-preservation][F:quick-command-preservation.test.tsx]; [B:CompanyRelationship][B:CompanyRelationshipTests]. Job history/context and NEW command company destination | All contact/date edits persisted through browser; source URL safety | M | Yes — directory/navigation |
| **PRES-J09** — Recorded offers/compensation/deadlines/notes and source links | `/offers` | OfferComparisonPage; job API | [F:offer-comparison][F:offer-comparison.test.tsx]; [B:AnalyticsSalary][B:AnalyticsSalaryTests], [B:JobApplicationsEndpointBehavior][B:JobApplicationsEndpointBehaviorTests]. Recorded values/empty states and salary normalization | Mobile many-offer comparison; localized currency/date visual review | M | Yes — jobs/analytics placement |
| **PRES-J10** — CSV/JSON export, JSON import and CSV-to-JSON conversion | `/settings; ImportExportJobs` | ImportExportJobs; CSV/job controller | [F:csv-export][F:csv-export.test.tsx]; [B:CsvExport][B:CsvExportTests], [B:JobApplicationsController][B:JobApplicationsControllerTests]. B05 formula/quotes/UTF-8/typed dates and numeric behavior; CSV browser byte download | Full browser JSON import/count/roundtrip; Excel/LibreOffice compatibility remains separately bounded | H | Yes — settings/download placement |
| **PRES-W01** — Full workspace, sections, legacy links and optional reusable overlay | `/jobs/:id; /applications/:id; section/followMode` | ApplicationWorkspacePage, jobWorkspaceRoute; workspace API | [F:application-workspace-overlay][F:application-workspace-overlay.test.tsx], [F:applicationWorkspace][F:applicationWorkspace.test.ts], [F:application-route-contracts][F:application-route-contracts.test.ts]; [B:ApplicationWorkspace][B:ApplicationWorkspaceTests]. Deep links, dirty cancel/discard, missing job and back/filter/focus; NEW actual App command/legacy entry | No active production caller of override/onClose overlay props found; full overlay parity needs a host fixture before adoption | H | Yes — primary workflow |
| **PRES-W02** — Detail/status/progression, recruiter/dates/description/timeline | `/jobs/:id overview` | WorkspaceHeader, JobDetailsSection, ApplicationProgress/Timeline; workflow APIs | [F:application-intelligence][F:application-intelligence.test.tsx], [F:workflow-trust-signals][F:workflow-trust-signals.test.tsx], [F:daily-control-loop][F:daily-control-loop.test.tsx]; [B:JobApplicationsWorkflowSignals][B:JobApplicationsWorkflowSignalsTests], [B:JobApplicationsAppliedDateHistory][B:JobApplicationsAppliedDateHistoryTests]. Timeline source labels, next-action routing and applied-date history | Edit/status→timeline real-browser sequence across locale/timezone | H | Yes — workspace |
| **PRES-W03** — Analysis, match/gaps, strategy and reviewed status/workflow suggestions | `/jobs/:id?section=analysis` | ApplicationAnalysis/Match/StrategySnapshot/StatusSuggestion; intelligence/AI services | [F:application-intelligence][F:application-intelligence.test.tsx], [F:application-workflow-assist][F:application-workflow-assist.test.tsx]; [B:ApplicationIntelligence][B:ApplicationIntelligenceTests], [B:StrategySnapshotOperation][B:StrategySnapshotOperationTests], [B:JobApplicationsEndpointBehavior][B:JobApplicationsEndpointBehaviorTests]. Loading/error/empty states, match and explicit suggested action behavior | Actual model truthfulness/evaluation; source freshness and cancelled generation browser states | H | Yes — contextual AI |
| **PRES-W04** — Checklist create/edit/complete/delete/order and next action | `Job overview/checklist entry` | ApplicationChecklist; checklist service/controller | [F:application-checklist][F:application-checklist.test.tsx]; [B:ApplicationChecklist][B:ApplicationChecklistTests]. Persisted item actions and keyboard reorder; localized readiness | Real-API mobile edit/delete and interruption recovery | H | Yes — workspace detail |
| **PRES-W05** — Attach/select/create/tailor CV and source context | `Job CV section; builder deep link` | ApplicationCvSection/TailoringSection; ApplicationAssetsService | [F:application-assets][F:application-assets.test.tsx], [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx]; [B:ApplicationAssets][B:ApplicationAssetsTests], [B:CvBuilder][B:CvBuilderTests]. Attach re-points only, detach keeps variant, foreign owner denied, tailoring never writes source; B02 API browser | P2-D01 SQLite tailoring ordering blocks successful real-browser guidance; actual attach→render relationship beyond existing service coverage | H | Yes — document relationships |
| **PRES-W06** — Cover-letter manual/AI review, versions/restore and dirty protection | `Job cover-letter section` | ApplicationCoverLetterSection, CoverLetterAiAssistant; assets/history | [F:application-assets][F:application-assets.test.tsx], [F:application-workspace-overlay][F:application-workspace-overlay.test.tsx]; [B:ApplicationAssets][B:ApplicationAssetsTests]. Manual save/discard/restore, linked-CV AI explicit apply then save, version history owner scope | Whole-browser AI reject/provider success and cover-letter history persistence; no actual model called here | H | Yes — workspace/content editing |
| **PRES-W07** — Application drafts and immutable submitted package/archived binaries | `Job cover-letter drafts; CV section package history` | ApplicationPackageDraftsSection, SubmittedPackagesSection; package service/storage | [F:application-assets][F:application-assets.test.tsx], [F:application-drafts][F:application-drafts.test.ts]; [B:SubmittedApplicationPackage][B:SubmittedApplicationPackageTests], [B:JobApplicationsApplicationPackage][B:JobApplicationsApplicationPackageTests], [B:JobApplicationsEndpointBehavior][B:JobApplicationsEndpointBehaviorTests]. Drafts keep ordinary notes; service frozen document/hash/copy-failure/tenant assertions; NEW native browser capture oracle | P2-D01 expected failure: SQLite capture 500. NEW post-capture mutation/archive assertions are NOT reached. Require real storage/provider success before package restructuring | H | Yes — documents/submission |
| **PRES-W08** — Attachments upload/category/name/AI consent/preview/download/delete | `Job overview Documents accordion; package archive` | Attachments; AttachmentsController, AttachmentStorage | [F:attachments][F:attachments.test.tsx]; [B:AttachmentsController][B:AttachmentsControllerTests], [B:AttachmentConsistency][B:AttachmentConsistencyTests], [B:AttachmentFlagsRecompute][B:AttachmentFlagsRecomputeTests]. Empty/flag controls, storage consistency and owned download; NEW browser fixture uploads real UTF-8 binary | Archived bytes after live delete blocked by W07; drag/drop, rename and download browser journey | H | Yes — document surfaces |
| **PRES-W09** — Interview questions/answers/ready/manual removal/AI review | `Job interview section` | InterviewPrep; interview persistence/AI endpoints | [F:interview-prep][F:interview-prep.test.tsx]; [B:InterviewPrepPersistence][B:InterviewPrepPersistenceTests], [B:InterviewAiContext][B:InterviewAiContextTests], [B:InterviewPrep][B:InterviewPrepTests]. Explicit AI add, manual/answer readiness, relevant prompt context without invented defaults | Populated mobile keyboard editing and real reload; actual model quality separate | H | Yes — workspace AI |
| **PRES-W10** — Debrief/follow-up draft/date/readiness | `Job interview section; follow-up entry` | InterviewPrep; follow-up draft services | [F:interview-prep][F:interview-prep.test.tsx]; [B:JobApplicationsFollowUpDraft][B:JobApplicationsFollowUpDraftTests], [B:InterviewPrep][B:InterviewPrepTests]. Neutral debrief template and follow-up content handling | Timezone/reload browser chain; calendar defects remain outside Phase 2 | M | Yes — workspace workflow |
| **PRES-W11** — Reminder rules/actions/notifications, ICS and Google/Outlook events | `/reminders; job calendar actions; /settings` | RemindersView, RulesSettingsCard, ApplicationCalendarActions; calendar/rules APIs | [F:daily-control-loop][F:daily-control-loop.test.tsx], [F:application-calendar][F:application-calendar.test.tsx], [F:settings-view][F:settings-view.test.tsx]; [B:ApplicationCalendarController][B:ApplicationCalendarControllerTests], [B:RulesEngineProspect][B:RulesEngineProspectTests], [B:NotificationSettingsController][B:NotificationSettingsControllerTests]. Provider write confirmation, ICS and permission; NEW per-scenario rule payload and real saved preference checks | DST/date-only correctness and real provider timezone must be resolved separately; initial rules 500 not reproduced | H | Yes — scheduling/navigation |
| **PRES-W12** — Async progress/failure/retry/cancel/notifications | `/operations; profile processing` | OperationsPage, CareerProfilePage; operation store/worker | [F:operations-page][F:operations-page.test.tsx], [F:profile-page][F:profile-page.test.tsx]; [B:OperationsController][B:OperationsControllerTests], [B:UserOperationStore][B:UserOperationStoreTests], [B:CvProcessingOperation][B:CvProcessingOperationTests]. Failure retry/cancel, durable operation IDs; extraction polling keeps dirty fields | Long-lived disconnect/reconnect and worker fault/recovery operational gaps | H | Yes — notifications/import |
| **PRES-C01** — Canonical structured career data and long-tail/custom sections | `/career?section=profile` | CareerProfilePage, career views; CareerProfileService/controller | [F:profile-page][F:profile-page.test.tsx]; [B:CareerProfileController][B:CareerProfileControllerTests], [B:CareerProfileService][B:CareerProfileServiceTests]. Structured field changes propagate to saved singleton, stable child IDs and relational roundtrip; NEW CV edit leaves master unchanged | Every long-tail section/mobile keyboard save; concurrent canonical saves outside scope | H | Yes — career workflow |
| **PRES-C02** — Profile overview/completeness/import guidance/raw copy/history/restore | `/career` | CareerWorkspacePage, CareerProfilePage; version service | [F:career-workspace-page][F:career-workspace-page.test.tsx], [F:profile-page][F:profile-page.test.tsx]; [B:CareerProfileService][B:CareerProfileServiceTests]. First/returning state, completeness/errors and non-destructive history restore | Clipboard/avatar and full browser historical restore; real extraction quality separate | M | Yes — career entry |
| **PRES-C03** — Upload/extract/rebuild/reprocess/diff/select/accept/discard/retry/cancel | `Career import/review` | CareerProfilePage; profile-CV/processing/diff services | [F:profile-page][F:profile-page.test.tsx]; [B:ProfileCvController][B:ProfileCvControllerTests], [B:CvProfileDiffService][B:CvProfileDiffServiceTests], [B:CvProcessingOperation][B:CvProcessingOperationTests], [B:CvExtractionCoverage][B:CvExtractionCoverageTests]. Queue/upload, operation retry, pending explicit apply and polling retains edits; extraction/diff service checks | Manual low-confidence deselection/discard UI; OCR/scanned/unusual real-document quality | H | Yes — career import |
| **PRES-C04** — Evidence bank source/category/tags/add/list/delete | `Career overview/evidence` | CareerEvidenceBank; CareerEvidenceController | [F:career-evidence][F:career-evidence.test.tsx]; [B:CareerEvidenceController][B:CareerEvidenceControllerTests]. Sourced evidence creation, tags and owner boundaries | Delete and many-item search/keyboard browser flow | M | Yes — canonical evidence |
| **PRES-C05** — CV library create/copy/delete/templates/share/publication/PDF | `/career/builder` | CvBuilderPage, thumbnails; CvVariantService/PublicCvController | [F:cv-builder-page][F:cv-builder-page.test.tsx], [F:cv-template-thumbnail][F:cv-template-thumbnail.test.tsx]; [B:CvBuilder][B:CvBuilderTests], [B:PublicCvController][B:PublicCvControllerTests]. General/job-specific creation, delete cancel, duplication fresh slug, public revoke/republish; existing public browser PDF | Complete library→publish/unpublish/revoke old link browser chain | H | Yes — CV workspace |
| **PRES-C06** — Studio tabs, preview debounce/pages/fit/save state/mobile panes | `/career/builder/:id` | CvBuilderEditor, CvPreviewPane; preview API | [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx]; [B:CvBuilder][B:CvBuilderTests]. Five tabs, deep-link/error/save state and preview retry; NEW real mobile Edit/Preview, reload and desktop split | Keyboard preview scroll/focus (known F15), all theme/page interactions | H | Yes — representative editor |
| **PRES-C07** — Visibility/order/custom sections and item/document overrides | `Builder Content` | CvBuilderEditor, CV controls/useDragReorder; resolver/settings | [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx], [F:cvBuilder][F:cvBuilder.test.ts]; [B:CvBuilder][B:CvBuilderTests]. Add/edit/delete/order/hide, override renders without master change; NEW persisted headline and sibling isolation | Native drag/touch and override reset-to-source browser flow; item-level real saved overrides beyond headline | H | Yes — editing controls |
| **PRES-C08** — Capability-aware templates/typography/color/header/skills/sidebar/photo | `Builder Template/Customize` | CvCustomizeTab, registry; ThemedCvRenderer | [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx], [F:cvBuilder][F:cvBuilder.test.ts], [F:cv-template-thumbnail][F:cv-template-thumbnail.test.tsx]; [B:CvBuilder][B:CvBuilderTests]. Template change clears incompatible defaults; normalized overrides reach shared renderer, safe color/markdown | Complete template×advanced control visual/render parity; inaccessible color controls baseline | M | Yes — component foundation |
| **PRES-C09** — A4/Letter/density/margins/dates/document locale/section presentation | `Builder Customize/Content` | cvBuilder, CvCustomizeTab; settings normalization/render model | [F:cvBuilder][F:cvBuilder.test.ts], [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx]; [B:CvBuilder][B:CvBuilderTests]. Page sizes, NB controls/default labels/dates, section grid/columns; existing long searchable PDF browser | All advanced combinations, print margins and long localized text manual review | M | Yes — controls must remain |
| **PRES-C10** — Undo/redo, save queue, dirty guard, history restore/preview lifecycle | `Builder editor/history` | CvBuilderEditor; CvVariantService version history | [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx]; [B:CvBuilder][B:CvBuilderTests]. Undo/redo, failed save retry, guard cancel, restore-as-new-version; NEW saved override reload | Multi-browser stale-CV revision remains separate defect; history-tab browser restore and offline navigation | H | Yes — do not alter persistence contract |
| **PRES-C11** — Section and whole-document AI improve/translate/instruction/grammar review | `Builder AI Tools/content assistant` | AiSectionAssistant, DocumentAiTab; CV AI assist | [F:ai-section-assistant][F:ai-section-assistant.test.tsx], [F:cv-builder-deep-link][F:cv-builder-deep-link.test.tsx]; [B:AiWorkspace][B:AiWorkspaceTests], [B:AiPrivacyPolicy][B:AiPrivacyPolicyTests], [B:ProEntitlementAuthorization][B:ProEntitlementAuthorizationTests]. NEW reject/close, edited acceptance, failure retry, whole-document apply/reject and malformed/missing/duplicate IDs rejected; no implicit PUT | Real model factual validation and section→whole review interactions; Free-disabled controls proven in new browser | H | Yes — AI interaction pattern |
| **PRES-C12** — Private PDF and published anonymous CV/PDF, long searchable pages | `Builder export; /cv/:slug` | PublicCvPage, cvBuilder; HtmlPdfGenerator/shared admission | [F:public-cv-page][F:public-cv-page.test.tsx]; [B:PublicCvController][B:PublicCvControllerTests], [B:PdfRenderAdmission][B:PdfRenderAdmissionTests], [B:CvBuilder][B:CvBuilderTests]. Anonymous public rendering versus private refusal; B03 shared capacity/failure; real multipage/public PDF browser | All templates/print engines; deployed Chromium/font behavior and PDF manual inspection | H | Yes — export/preview links |
| **PRES-M01** — Job-scoped manual correspondence/search/delete/paste import | `Workspace communication accordion` | Correspondence; CorrespondenceController | [F:end-to-end-trust-loop][F:end-to-end-trust-loop.test.tsx], [F:correspondence-search-context][F:correspondence-search-context.test.ts]; [B:CorrespondenceController][B:CorrespondenceControllerTests]. Canonical communication entry does not send mail, job context and CRUD ownership | Manual note edit/delete/paste-import real browser; preserve send/log distinction | H | Yes — workspace/correspondence |
| **PRES-M02** — Gmail candidate/thread import/refresh/sync/unlink/relink/move | `Job communication Gmail tools` | Correspondence; GmailController/provider | [F:correspondence-gmail-import][F:correspondence-gmail-import.test.tsx]; [B:GmailController][B:GmailControllerTests], [B:EmailOwnershipIntegration][B:EmailOwnershipIntegrationTests]. Candidates, selected thread import/move/refresh and diagnostics; owner-bound relationships | Real provider/sandbox threads, multi-account reconnect and sync failure | H | Yes — relationship controls |
| **PRES-M03** — Global inbox filters/page/provider/link/direction/detail/source links | `/correspondence` | CorrespondenceInboxPage; EmailController | [F:correspondence-inbox-page][F:correspondence-inbox-page.test.tsx]; [B:EmailController][B:EmailControllerTests], [B:EmailOwnershipIntegration][B:EmailOwnershipIntegrationTests]. Filter/pagination/detail/provider read failure distinct from empty | Real large mailbox and attachment binary browser flows | H | Yes — inbox/navigation |
| **PRES-M04** — Compose/reply/provider/recipient/job; draft conflicts; confirm send/uncertainty | `/correspondence drafts/compose` | CorrespondenceInboxPage; EmailDrafts/Send/attempt store | [F:correspondence-inbox-page][F:correspondence-inbox-page.test.tsx]; [B:EmailDraftsController][B:EmailDraftsControllerTests], [B:EmailDraftPersistence][B:EmailDraftPersistenceTests], [B:EmailSendController][B:EmailSendControllerTests], [B:EmailSendAttemptStore][B:EmailSendAttemptStoreTests], [B:EmailProviderDelivery][B:EmailProviderDeliveryTests]. Revision conflicts, explicit send confirm, uncertain state has no automatic retry, deliberate new attempt | Actual sandbox mail delivery and browser reconnect; do not loosen idempotency/conflict guards | H | Yes — high-risk drafts/navigation |
| **PRES-M05** — Review proposed jobs/link/reject/keep/notes/sync/create | `/correspondence?view=review; /correspondence/review` | GmailReviewPage, CorrespondenceInboxPage; Gmail review | [F:gmail-review-page][F:gmail-review-page.test.tsx], [F:correspondence-inbox-page][F:correspondence-inbox-page.test.tsx]; [B:GmailController][B:GmailControllerTests]. Review decisions/localization and inbox review entry | Real App legacy alias and suggested-job create browser workflow | H | Yes — merged review entry |
| **PRES-M06** — Gmail/Graph/IMAP connect/status/disconnect separate from sign-in | `/settings/connected-accounts` | EmailProviderConnections; Google/Graph/IMAP controllers | [F:email-provider-connections][F:email-provider-connections.test.tsx]; [B:MicrosoftGraphController][B:MicrosoftGraphControllerTests], [B:ImapController][B:ImapControllerTests], [B:ImapServiceSsrfGuard][B:ImapServiceSsrfGuardTests], [B:GmailController][B:GmailControllerTests]. Connection state/NB/IMAP form and provider ownership; outbound IMAP safety | Actual provider authorization/revocation/token expiry; no credentials contacted in new tests | H | Yes — settings/account |
| **PRES-S01** — Personal metrics/activity/funnel/company/skills/stage/salary/next actions | `/dashboard` | DashboardView; analytics/controllers | [F:daily-control-loop][F:daily-control-loop.test.tsx], [F:workflow-trust-signals][F:workflow-trust-signals.test.tsx]; [B:StageAnalytics][B:StageAnalyticsTests], [B:AnalyticsSalary][B:AnalyticsSalaryTests]. Empty dashboard prioritizes onboarding, attention deep links; server analytics facts | Chart transformation fidelity and full populated/timezone browser dashboard | M | Yes — dashboard/analytics |
| **PRES-S02** — Owner-local five visibility preferences/onboarding dismiss/notifications | `/dashboard; notification bell` | DashboardView, OnboardingChecklist, NotificationsPopover; notification APIs | [F:onboarding-checklist][F:onboarding-checklist.test.tsx], [F:notifications-popover][F:notifications-popover.test.tsx], [F:app-shell-notifications][F:app-shell-notifications.test.tsx], [F:account-scoped-state][F:account-scoped-state.test.tsx]; [B:JobLifecycleEvent][B:JobLifecycleEventTests]. Onboarding actions; unread/read/dismiss UI and owner-scoped storage primitive | Five dashboard toggles/reload per account not fully tested at mounted dashboard; ordering/resizing is new work | M | Yes — preserve current preferences |
| **PRES-S03** — Rules/reminder/table/theme/language preferences and account links | `/settings tabs/mobile selector` | SettingsView, RulesSettingsCard, theme/i18n; rules/notification/auth | [F:settings-view][F:settings-view.test.tsx], [F:theme-state][F:theme-state.test.tsx], [F:i18n-provider][F:i18n-provider.test.tsx]; [B:NotificationSettingsController][B:NotificationSettingsControllerTests], [B:RulesEngineProspect][B:RulesEngineProspectTests]. NEW failed notification retry, rule scenario preservation; NEW mobile→desktop edit + native notification/rule persistence | Initial single rules 500 unconfirmed; unsaved rule drafts are not persisted across tab unmount; table preference/router identity change gap | H | Yes — shared preferences/navigation |
| **PRES-S04** — AI privacy/usage/limits/Free-Pro/server entitlement/conditional billing | `/settings; locked AI controls; plans` | AiPrivacySettingsCard, AiUsageCard, AccountPlanProvider; billing/entitlement | [F:settings-view][F:settings-view.test.tsx], [F:ai-usage-card][F:ai-usage-card.test.tsx], [F:pro-feature-notice][F:pro-feature-notice.test.tsx], [F:planCatalog][F:planCatalog.test.ts]; [B:AiPrivacyPolicy][B:AiPrivacyPolicyTests], [B:AiUsageMeter][B:AiUsageMeterTests], [B:ProEntitlementAuthorization][B:ProEntitlementAuthorizationTests], [B:BillingController][B:BillingControllerTests]. Local-only AI setting, limits/locks, billing readiness; NEW real Free CV AI denied UI and API | Real checkout/webhooks/portal; billing/account deletion issues retain independent queue | H | Yes — settings/AI states |
| **PRES-S05** — Account ZIP/encrypted backup/lifecycle/deletion confirmations | `Settings Backup tab` | BackupCard; export/backup/deletion services | [F:account-data-export][F:account-data-export.test.tsx]; [B:AccountDataExport][B:AccountDataExportTests], [B:BackupController][B:BackupControllerTests], [B:AccountDeletion][B:AccountDeletionTests], [B:DatabaseBackupRunner][B:DatabaseBackupRunnerTests]. ZIP protected download, recent auth, server enable flag and exact deletion phrase; service deletion/backup | Real restored account/database and paid deletion/provider cancellation operational proof; not safe to run against production | H | Yes — account lifecycle |
| **PRES-A01** — Admin user/create/roles/reset/delete/last-admin/self guards | `/admin/users` | AdminUsersPage; UsersController | [F:admin-users-page][F:admin-users-page.test.tsx]; [B:UsersController][B:UsersControllerTests], [B:ApiAuthorizationPosture][B:ApiAuthorizationPostureTests]. Demotion/delete confirm, last-admin server checks; NEW non-admin crafted create/read denied | Role revocation during mounted admin view and actual reset delivery; route can render empty shell without granting privilege | H | Yes — separate admin area |
| **PRES-A02** — Audit list/detail/supported undo/job restore | `/admin/audit` | AdminAuditPage; AdminAuditController | [F:admin-audit-page][F:admin-audit-page.test.tsx]; [B:AuthAndSystemController][B:AuthAndSystemControllerTests], [B:ApiAuthorizationPosture][B:ApiAuthorizationPostureTests]. Unavailable-versus-empty retry and NB stored event text; server admin-only posture | Successful undo and job-restore UI against persisted API; role posture test is not undo behavior proof | H | Yes — admin navigation |
| **PRES-A03** — System/build/DB/AI/mail/SMTP/test/probe/benchmark/maintenance | `/admin/system` | AdminSystemPage; AdminSystemController/maintenance/benchmark | [F:admin-system-page][F:admin-system-page.test.tsx]; [B:AuthAndSystemController][B:AuthAndSystemControllerTests], [B:MaintenanceJobDispatcher][B:MaintenanceJobDispatcherTests], [B:CvCorpusHarness][B:CvCorpusHarnessTests]. Health/error/NB, SMTP submit and benchmark controls; dispatcher authorization and modes | Production SMTP/model/corpus/maintenance and sensitive-data presentation; no live jobs launched | H | Yes — admin hierarchy |
## Before changing a mapped surface
Run its mapped tests and the shared identity/route regressions. Add the missing behavioral fixture needed by the proposed change before editing that workflow. A gap can remain intentional for Phase 3 documentation; it cannot silently become permission to restructure an unprotected workflow. Keep [traceability](TRACEABILITY.md) updated per preservation ID and require real EN/NB, light/dark, desktop/mobile and keyboard evidence for each later migration.
[F:landing-page.test.tsx]: ../../../job-tracker-ui/src/landing-page.test.tsx
[F:planCatalog.test.ts]: ../../../job-tracker-ui/src/planCatalog.test.ts
[F:LandingPage.authRedirect.test.tsx]: ../../../job-tracker-ui/src/LandingPage.authRedirect.test.tsx
[B:AccountPlansTests]: ../../../JobTrackerApi.Tests/AccountPlansTests.cs
[F:login-page.test.tsx]: ../../../job-tracker-ui/src/login-page.test.tsx
[F:verify-email-page.test.tsx]: ../../../job-tracker-ui/src/verify-email-page.test.tsx
[F:turnstile-widget.test.tsx]: ../../../job-tracker-ui/src/turnstile-widget.test.tsx
[B:LocalAuthIdentityTests]: ../../../JobTrackerApi.Tests/LocalAuthIdentityTests.cs
[B:AuthAndSystemControllerTests]: ../../../JobTrackerApi.Tests/AuthAndSystemControllerTests.cs
[F:microsoft-legacy-relink-page.test.tsx]: ../../../job-tracker-ui/src/microsoft-legacy-relink-page.test.tsx
[B:GoogleTokenValidatorTests]: ../../../JobTrackerApi.Tests/GoogleTokenValidatorTests.cs
[B:MicrosoftTokenValidatorTests]: ../../../JobTrackerApi.Tests/MicrosoftTokenValidatorTests.cs
[F:two-factor-settings.test.tsx]: ../../../job-tracker-ui/src/two-factor-settings.test.tsx
[B:TwoFactorControllerTests]: ../../../JobTrackerApi.Tests/TwoFactorControllerTests.cs
[B:SessionsControllerTests]: ../../../JobTrackerApi.Tests/SessionsControllerTests.cs
[F:session-boundary.test.ts]: ../../../job-tracker-ui/src/session-boundary.test.ts
[F:account-scoped-state.test.tsx]: ../../../job-tracker-ui/src/account-scoped-state.test.tsx
[B:AuthSessionRevocationTests]: ../../../JobTrackerApi.Tests/AuthSessionRevocationTests.cs
[F:profile-page.test.tsx]: ../../../job-tracker-ui/src/profile-page.test.tsx
[B:AvatarStorageTests]: ../../../JobTrackerApi.Tests/AvatarStorageTests.cs
[F:sidebar-active-nav.test.ts]: ../../../job-tracker-ui/src/sidebar-active-nav.test.ts
[F:app-shell-notifications.test.tsx]: ../../../job-tracker-ui/src/app-shell-notifications.test.tsx
[F:quick-command-preservation.test.tsx]: ../../../job-tracker-ui/src/quick-command-preservation.test.tsx
[B:JobApplicationsAuthorizationTests]: ../../../JobTrackerApi.Tests/JobApplicationsAuthorizationTests.cs
[B:CompanyRelationshipTests]: ../../../JobTrackerApi.Tests/CompanyRelationshipTests.cs
[F:theme-state.test.tsx]: ../../../job-tracker-ui/src/theme-state.test.tsx
[F:i18n-provider.test.tsx]: ../../../job-tracker-ui/src/i18n-provider.test.tsx
[F:confirm.test.tsx]: ../../../job-tracker-ui/src/confirm.test.tsx
[F:prompt.test.tsx]: ../../../job-tracker-ui/src/prompt.test.tsx
[F:dialog-flow.test.tsx]: ../../../job-tracker-ui/src/dialog-flow.test.tsx
[B:SessionContextMiddlewareTests]: ../../../JobTrackerApi.Tests/SessionContextMiddlewareTests.cs
[B:CurrentUserIdLiveEvaluationTests]: ../../../JobTrackerApi.Tests/CurrentUserIdLiveEvaluationTests.cs
[B:OwnershipGuardTests]: ../../../JobTrackerApi.Tests/OwnershipGuardTests.cs
[F:job-discovery.test.tsx]: ../../../job-tracker-ui/src/job-discovery.test.tsx
[B:JobDiscoveryControllerTests]: ../../../JobTrackerApi.Tests/JobDiscoveryControllerTests.cs
[B:JobOpportunitySyncTests]: ../../../JobTrackerApi.Tests/JobOpportunitySyncTests.cs
[B:SavedJobSearchAlertTests]: ../../../JobTrackerApi.Tests/SavedJobSearchAlertTests.cs
[F:quick-capture.test.tsx]: ../../../job-tracker-ui/src/quick-capture.test.tsx
[B:JobImportServiceTests]: ../../../JobTrackerApi.Tests/JobImportServiceTests.cs
[B:JobImportHttpTransportTests]: ../../../JobTrackerApi.Tests/JobImportHttpTransportTests.cs
[B:JobApplicationsControllerTests]: ../../../JobTrackerApi.Tests/JobApplicationsControllerTests.cs
[F:captureUrl.test.ts]: ../../../job-tracker-ui/src/captureUrl.test.ts
[B:CvBuilderTests]: ../../../JobTrackerApi.Tests/CvBuilderTests.cs
[F:application-workspace-overlay.test.tsx]: ../../../job-tracker-ui/src/application-workspace-overlay.test.tsx
[F:daily-control-loop.test.tsx]: ../../../job-tracker-ui/src/daily-control-loop.test.tsx
[B:JobApplicationsEndpointBehaviorTests]: ../../../JobTrackerApi.Tests/JobApplicationsEndpointBehaviorTests.cs
[F:confirm-flow.test.tsx]: ../../../job-tracker-ui/src/confirm-flow.test.tsx
[B:JobLifecycleEventTests]: ../../../JobTrackerApi.Tests/JobLifecycleEventTests.cs
[F:kanban-grouped-board.test.tsx]: ../../../job-tracker-ui/src/kanban-grouped-board.test.tsx
[F:pipeline.test.ts]: ../../../job-tracker-ui/src/pipeline.test.ts
[B:JobPipelineTests]: ../../../JobTrackerApi.Tests/JobPipelineTests.cs
[F:companies-relationship.test.tsx]: ../../../job-tracker-ui/src/companies-relationship.test.tsx
[F:offer-comparison.test.tsx]: ../../../job-tracker-ui/src/offer-comparison.test.tsx
[B:AnalyticsSalaryTests]: ../../../JobTrackerApi.Tests/AnalyticsSalaryTests.cs
[F:csv-export.test.tsx]: ../../../job-tracker-ui/src/csv-export.test.tsx
[B:CsvExportTests]: ../../../JobTrackerApi.Tests/CsvExportTests.cs
[F:applicationWorkspace.test.ts]: ../../../job-tracker-ui/src/applicationWorkspace.test.ts
[F:application-route-contracts.test.ts]: ../../../job-tracker-ui/src/application-route-contracts.test.ts
[B:ApplicationWorkspaceTests]: ../../../JobTrackerApi.Tests/ApplicationWorkspaceTests.cs
[F:application-intelligence.test.tsx]: ../../../job-tracker-ui/src/application-intelligence.test.tsx
[F:workflow-trust-signals.test.tsx]: ../../../job-tracker-ui/src/workflow-trust-signals.test.tsx
[B:JobApplicationsWorkflowSignalsTests]: ../../../JobTrackerApi.Tests/JobApplicationsWorkflowSignalsTests.cs
[B:JobApplicationsAppliedDateHistoryTests]: ../../../JobTrackerApi.Tests/JobApplicationsAppliedDateHistoryTests.cs
[F:application-workflow-assist.test.tsx]: ../../../job-tracker-ui/src/application-workflow-assist.test.tsx
[B:ApplicationIntelligenceTests]: ../../../JobTrackerApi.Tests/ApplicationIntelligenceTests.cs
[B:StrategySnapshotOperationTests]: ../../../JobTrackerApi.Tests/StrategySnapshotOperationTests.cs
[F:application-checklist.test.tsx]: ../../../job-tracker-ui/src/application-checklist.test.tsx
[B:ApplicationChecklistTests]: ../../../JobTrackerApi.Tests/ApplicationChecklistTests.cs
[F:application-assets.test.tsx]: ../../../job-tracker-ui/src/application-assets.test.tsx
[F:cv-builder-deep-link.test.tsx]: ../../../job-tracker-ui/src/cv-builder-deep-link.test.tsx
[B:ApplicationAssetsTests]: ../../../JobTrackerApi.Tests/ApplicationAssetsTests.cs
[F:application-drafts.test.ts]: ../../../job-tracker-ui/src/application-drafts.test.ts
[B:SubmittedApplicationPackageTests]: ../../../JobTrackerApi.Tests/SubmittedApplicationPackageTests.cs
[B:JobApplicationsApplicationPackageTests]: ../../../JobTrackerApi.Tests/JobApplicationsApplicationPackageTests.cs
[F:attachments.test.tsx]: ../../../job-tracker-ui/src/attachments.test.tsx
[B:AttachmentsControllerTests]: ../../../JobTrackerApi.Tests/AttachmentsControllerTests.cs
[B:AttachmentConsistencyTests]: ../../../JobTrackerApi.Tests/AttachmentConsistencyTests.cs
[B:AttachmentFlagsRecomputeTests]: ../../../JobTrackerApi.Tests/AttachmentFlagsRecomputeTests.cs
[F:interview-prep.test.tsx]: ../../../job-tracker-ui/src/interview-prep.test.tsx
[B:InterviewPrepPersistenceTests]: ../../../JobTrackerApi.Tests/InterviewPrepPersistenceTests.cs
[B:InterviewAiContextTests]: ../../../JobTrackerApi.Tests/InterviewAiContextTests.cs
[B:InterviewPrepTests]: ../../../JobTrackerApi.Tests/InterviewPrepTests.cs
[B:JobApplicationsFollowUpDraftTests]: ../../../JobTrackerApi.Tests/JobApplicationsFollowUpDraftTests.cs
[F:application-calendar.test.tsx]: ../../../job-tracker-ui/src/application-calendar.test.tsx
[F:settings-view.test.tsx]: ../../../job-tracker-ui/src/settings-view.test.tsx
[B:ApplicationCalendarControllerTests]: ../../../JobTrackerApi.Tests/ApplicationCalendarControllerTests.cs
[B:RulesEngineProspectTests]: ../../../JobTrackerApi.Tests/RulesEngineProspectTests.cs
[B:NotificationSettingsControllerTests]: ../../../JobTrackerApi.Tests/NotificationSettingsControllerTests.cs
[F:operations-page.test.tsx]: ../../../job-tracker-ui/src/operations-page.test.tsx
[B:OperationsControllerTests]: ../../../JobTrackerApi.Tests/OperationsControllerTests.cs
[B:UserOperationStoreTests]: ../../../JobTrackerApi.Tests/UserOperationStoreTests.cs
[B:CvProcessingOperationTests]: ../../../JobTrackerApi.Tests/CvProcessingOperationTests.cs
[B:CareerProfileControllerTests]: ../../../JobTrackerApi.Tests/CareerProfileControllerTests.cs
[B:CareerProfileServiceTests]: ../../../JobTrackerApi.Tests/CareerProfileServiceTests.cs
[F:career-workspace-page.test.tsx]: ../../../job-tracker-ui/src/career-workspace-page.test.tsx
[B:ProfileCvControllerTests]: ../../../JobTrackerApi.Tests/ProfileCvControllerTests.cs
[B:CvProfileDiffServiceTests]: ../../../JobTrackerApi.Tests/CvProfileDiffServiceTests.cs
[B:CvExtractionCoverageTests]: ../../../JobTrackerApi.Tests/CvExtractionCoverageTests.cs
[F:career-evidence.test.tsx]: ../../../job-tracker-ui/src/career-evidence.test.tsx
[B:CareerEvidenceControllerTests]: ../../../JobTrackerApi.Tests/CareerEvidenceControllerTests.cs
[F:cv-builder-page.test.tsx]: ../../../job-tracker-ui/src/cv-builder-page.test.tsx
[F:cv-template-thumbnail.test.tsx]: ../../../job-tracker-ui/src/cv-template-thumbnail.test.tsx
[B:PublicCvControllerTests]: ../../../JobTrackerApi.Tests/PublicCvControllerTests.cs
[F:cvBuilder.test.ts]: ../../../job-tracker-ui/src/cvBuilder.test.ts
[F:ai-section-assistant.test.tsx]: ../../../job-tracker-ui/src/ai-section-assistant.test.tsx
[B:AiWorkspaceTests]: ../../../JobTrackerApi.Tests/AiWorkspaceTests.cs
[B:AiPrivacyPolicyTests]: ../../../JobTrackerApi.Tests/AiPrivacyPolicyTests.cs
[B:ProEntitlementAuthorizationTests]: ../../../JobTrackerApi.Tests/ProEntitlementAuthorizationTests.cs
[F:public-cv-page.test.tsx]: ../../../job-tracker-ui/src/public-cv-page.test.tsx
[B:PdfRenderAdmissionTests]: ../../../JobTrackerApi.Tests/PdfRenderAdmissionTests.cs
[F:end-to-end-trust-loop.test.tsx]: ../../../job-tracker-ui/src/end-to-end-trust-loop.test.tsx
[F:correspondence-search-context.test.ts]: ../../../job-tracker-ui/src/correspondence-search-context.test.ts
[B:CorrespondenceControllerTests]: ../../../JobTrackerApi.Tests/CorrespondenceControllerTests.cs
[F:correspondence-gmail-import.test.tsx]: ../../../job-tracker-ui/src/correspondence-gmail-import.test.tsx
[B:GmailControllerTests]: ../../../JobTrackerApi.Tests/GmailControllerTests.cs
[B:EmailOwnershipIntegrationTests]: ../../../JobTrackerApi.Tests/EmailOwnershipIntegrationTests.cs
[F:correspondence-inbox-page.test.tsx]: ../../../job-tracker-ui/src/correspondence-inbox-page.test.tsx
[B:EmailControllerTests]: ../../../JobTrackerApi.Tests/EmailControllerTests.cs
[B:EmailDraftsControllerTests]: ../../../JobTrackerApi.Tests/EmailDraftsControllerTests.cs
[B:EmailDraftPersistenceTests]: ../../../JobTrackerApi.Tests/EmailDraftPersistenceTests.cs
[B:EmailSendControllerTests]: ../../../JobTrackerApi.Tests/EmailSendControllerTests.cs
[B:EmailSendAttemptStoreTests]: ../../../JobTrackerApi.Tests/EmailSendAttemptStoreTests.cs
[B:EmailProviderDeliveryTests]: ../../../JobTrackerApi.Tests/EmailProviderDeliveryTests.cs
[F:gmail-review-page.test.tsx]: ../../../job-tracker-ui/src/gmail-review-page.test.tsx
[F:email-provider-connections.test.tsx]: ../../../job-tracker-ui/src/email-provider-connections.test.tsx
[B:MicrosoftGraphControllerTests]: ../../../JobTrackerApi.Tests/MicrosoftGraphControllerTests.cs
[B:ImapControllerTests]: ../../../JobTrackerApi.Tests/ImapControllerTests.cs
[B:ImapServiceSsrfGuardTests]: ../../../JobTrackerApi.Tests/ImapServiceSsrfGuardTests.cs
[B:StageAnalyticsTests]: ../../../JobTrackerApi.Tests/StageAnalyticsTests.cs
[F:onboarding-checklist.test.tsx]: ../../../job-tracker-ui/src/onboarding-checklist.test.tsx
[F:notifications-popover.test.tsx]: ../../../job-tracker-ui/src/notifications-popover.test.tsx
[F:ai-usage-card.test.tsx]: ../../../job-tracker-ui/src/ai-usage-card.test.tsx
[F:pro-feature-notice.test.tsx]: ../../../job-tracker-ui/src/pro-feature-notice.test.tsx
[B:AiUsageMeterTests]: ../../../JobTrackerApi.Tests/AiUsageMeterTests.cs
[B:BillingControllerTests]: ../../../JobTrackerApi.Tests/BillingControllerTests.cs
[F:account-data-export.test.tsx]: ../../../job-tracker-ui/src/account-data-export.test.tsx
[B:AccountDataExportTests]: ../../../JobTrackerApi.Tests/AccountDataExportTests.cs
[B:BackupControllerTests]: ../../../JobTrackerApi.Tests/BackupControllerTests.cs
[B:AccountDeletionTests]: ../../../JobTrackerApi.Tests/AccountDeletionTests.cs
[B:DatabaseBackupRunnerTests]: ../../../JobTrackerApi.Tests/DatabaseBackupRunnerTests.cs
[F:admin-users-page.test.tsx]: ../../../job-tracker-ui/src/admin-users-page.test.tsx
[B:UsersControllerTests]: ../../../JobTrackerApi.Tests/UsersControllerTests.cs
[B:ApiAuthorizationPostureTests]: ../../../JobTrackerApi.Tests/ApiAuthorizationPostureTests.cs
[F:admin-audit-page.test.tsx]: ../../../job-tracker-ui/src/admin-audit-page.test.tsx
[F:admin-system-page.test.tsx]: ../../../job-tracker-ui/src/admin-system-page.test.tsx
[B:MaintenanceJobDispatcherTests]: ../../../JobTrackerApi.Tests/MaintenanceJobDispatcherTests.cs
[B:CvCorpusHarnessTests]: ../../../JobTrackerApi.Tests/CvCorpusHarnessTests.cs
+107
View File
@@ -0,0 +1,107 @@
# Phase 2 — Preservation regression checkpoint
**Completed 2026-09-10 from `2d0f131` on `codex/ui-redesign-phase2`.** This checkpoint adds regression protection and an explicit TypeScript CI gate. **No visual redesign, application behavior change, route/layout/component restructuring, schema change or B07 work.** The Phase 1 source/audit remains intact.
## Preservation coverage
- **57/57 protected capability groups mapped (100%)**, with stable `PRES-` aliases of the original E/J/W/C/M/S/A IDs.
- **44 high-risk groups**, all mapped to existing behavioral assertions. High risk includes private identity, data edits/history/relationships, irreversible actions and shared navigation likely to be restructured.
- **147 referenced existing/new automated test files** across frontend and backend. Each row records route/entry, component/service owners, protected behavior, missing proof and expected later redesign impact.
- This percentage means **at least one core automated behavioral assertion per capability group**. It is not exhaustive sub-workflow, code, provider, mobile/accessibility or visual coverage. The matrix explicitly retains partial coverage and one native package-capture blocker.
Read the [complete preservation matrix](PRESERVATION_MATRIX.md), [traceability contract and Phase 2 change ledger](TRACEABILITY.md), and [baseline defects/intentional gaps](BASELINE_DEFECTS.md).
## High-risk additions and preserved evidence
| Workflow | New meaningful regression |
|---|---|
| Command/navigation/capture | Three component cases: job/company destination, closing clears query, add opens review without creating; real browser Ctrl+K search, legacy match link, reviewed add |
| CV section AI | Four cases: Reject/Close clear proposal without applying, edited proposal applies only on acceptance, failure retry leaves content untouched |
| Whole-CV AI | Five cases: explicit Apply/Reject; invalid JSON, missing IDs and duplicate IDs cannot become edits; save targets only selected CV |
| Cover-letter AI | One case: Reject preserves saved draft, disabled Save/no dirty state/no PUT |
| Settings | Two component cases: retry failed notification save with retained draft; changing one rule keeps other scenarios |
| Canonical profile → derived CV | Browser mobile edit/preview → reload → desktop preview; stored headline changes only selected CV, complete canonical profile and sibling remain unchanged |
| Documents/submission | Native profile/job/CV/letter/file fixture + legacy entry and capture; **expected failure P2-D01**, with desired immutable HTML/letter/archive-byte checks retained but not reached |
| Responsive preferences | Browser mobile→desktop rule draft stays, native save persists; notification false survives reload; separate direct API rule save |
| Permissions | Non-admin admin-menu entries absent, direct users GET/POST forbidden, normal CV create allowed, Free AI actions disabled and API 403 |
Existing B01 connection-time outbound protections, B02 ownership/session/cache checks, B03 rendering admission, B04 trusted principal/IP limits, B05 CSV bytes, and B06 application/configuration tests are unchanged. Mail draft revisions/uncertain sends, profile extraction acceptance, CV history, long PDF, job dirty navigation and other existing tests were retained.
## Baseline and fresh verification
Fresh local execution uses installed .NET **9.0.317**, Node dependencies already locked in the checkout, Windows/Chromium and Playwright's disposable SQLite API. There were no production requests or provider credentials. Test fixtures use only synthetic accounts and local URLs.
| Gate | Recorded Phase 1 baseline | Fresh Phase 2 result |
|---|---|---|
| Backend Release suite | 916 passing | **916 passed, 0 failed, 0 skipped**; no exclusions, count unchanged |
| Frontend Jest | 298 tests / 67 suites | **313 passed / 68 suites**; +15 cases, +1 test file; no existing test removed |
| General browser | 18 passing | **23 actually passed + 1 expected failure**, 0 unexpected failures/skips/flaky; original 18 still pass, +6 cases |
| B04 real HTTP | 9 cases | **9 passed** |
| B06 production-mode API/forwarding HTTP | 6 cases | **6 passed**; not nginx/Traefik runtime proof |
| B03 PDF burst/admission | 1 case | **1 passed**, multi-route capacity/recovery oracle unchanged |
| Compose ingress/configuration | 3 tests/17 hostile mutations | **3 passed** |
| Backend build | Release | **Pass, 0 warnings/errors**, warnings-as-errors |
| Frontend build | Next production static export | **Pass** |
| Standalone type check | Historical TS2571 repaired before Phase 2 | **Pass**; new explicit CI command, unchanged strictness |
| New browser-spec TypeScript | Previously no whole-Playwright type gate | **Pass** with temporary Node-aware config for this new spec only |
| ESLint | Zero-warning gate | **Pass**, no suppressions added |
| Tracked secret scan; diff whitespace | Required | **Pass** |
Playwright's list reporter says “24 passed” because expected failures count as expected outcomes. Its JSON records **23 `expectedStatus=passed/actual=passed` and one `expectedStatus=failed/actual=failed`**. Do not present this as 24 successful workflows. The failed native package test is not a regression introduced by application changes: there are no such changes in this branch. See P2-D01.
Intermediate test-authoring corrections: one missing test-fixture brace, Testing Library's unsupported `exact` role options, a Playwright callback named `use` misidentified as a React hook, and package capture's actual CV-tab location. Corrected test code rather than weakening lint/types or changing UI. The temporary isolated TypeScript config initially lacked Node type roots; setting the existing installed Node declarations resolved Buffer. No new dependency installed.
One initial rules-save 500 did not reproduce in the direct or repeated browser path; retained as observation P2-O01, not asserted as a diagnosed defect. The reproducible SQLite package/tailoring failure is recorded separately. No blanket skipping or gate bypass was added.
## Exact commands
From the repository root (PowerShell):
```powershell
$env:DOTNET_ROOT='C:/Users/Connor/.dotnet'
& C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-restore --logger 'trx;LogFileName=phase2.trx' --results-directory .artifacts/redesign-phase2 -- xUnit.parallelizeTestCollections=false xUnit.maxParallelThreads=1
& C:/Users/Connor/.dotnet/dotnet.exe build JobTrackerApi/JobTrackerApi.csproj --configuration Release --no-restore -warnaserror
python scripts/test-ingress.py
python scripts/supply-chain.py scan-secrets
git diff --check
```
From `job-tracker-ui`:
```powershell
npm test -- --watchAll=false --runInBand
npm run typecheck
npm run lint
$env:NEXT_PUBLIC_API_BASE_URL='http://localhost:5302/api'
$env:NEXT_TELEMETRY_DISABLED='1'
npm run build
$env:DOTNET_ROOT='C:/Users/Connor/.dotnet'
$env:DOTNET_HOST_PATH='C:/Users/Connor/.dotnet/dotnet.exe'
$env:PLAYWRIGHT_STATIC_EXPORT='true'
$env:PLAYWRIGHT_PREBUILT_EXPORT='true'
$env:PLAYWRIGHT_JSON_OUTPUT_FILE='../.artifacts/phase2-browser-results.json'
node node_modules/@playwright/test/cli.js test --reporter=list,json
node node_modules/@playwright/test/cli.js test --config=playwright.rate-limits.config.ts
node node_modules/@playwright/test/cli.js test --config=playwright.ingress.config.ts
node node_modules/@playwright/test/cli.js test --config=playwright.pdf.config.ts
```
Initial focused command: `npm test -- --watchAll=false --runInBand --runTestsByPath src/quick-command-preservation.test.tsx src/ai-section-assistant.test.tsx src/cv-builder-deep-link.test.tsx src/settings-view.test.tsx` → 31 passed. Final full Jest includes the additional cover-letter reject case.
Final browser rerun after narrowing the known-failure annotation: `node node_modules/@playwright/test/cli.js test e2e/redesign-preservation.spec.ts` → five actual passes and the same one expected HTTP-500 capture failure (23.8s); no unexpected failures. Final lint and isolated browser-spec typing also pass.
Additional isolated browser-spec typing used `node node_modules/typescript/bin/tsc --project ../.artifacts/phase2-browser-tsconfig.json --noEmit`. Temporary config extends the frontend tsconfig, includes only `../job-tracker-ui/e2e/redesign-preservation.spec.ts`, sets `incremental:false`, `typeRoots:["../job-tracker-ui/node_modules/@types"]`, `types:["node"]`. This is a local check, not a claim that every pre-existing Playwright/config source is covered by the new CI type gate.
Local logs: `.artifacts/phase2-{backend,jest,build,api-build,typecheck,browser-typecheck,lint,browser,rate-limits,ingress,pdf,compose,secrets}.log`; backend TRX under `.artifacts/redesign-phase2`; browser JSON and sanitized outcome summary under `.artifacts`. Durable conclusions and reproduction remain in these committed documents/tests; raw traces with synthetic session material are not published.
The matrix was checked against the original ledger: 57 rows, 57 unique IDs, no missing/extra IDs, and all 147 test-reference paths exist. No production source file changed. Full baseline execution was not repeated for documentation-only edits.
## Remaining gaps and next phase
**Phase 2 is complete as a regression/planning checkpoint, with its documented baseline failure.** Phase 3 may define UX architecture: grouped sidebar, page/route destination and backwards compatibility, one Jobs table/board entry, canonical Career Profile/derived-document workflows, contextual AI review, and explicit mobile task rules. Keep the existing MUI/Emotion/React Router/API stack while planning. Do not implement those layouts or components in this checkpoint.
Before a later code migration, close that surface's matrix gaps or establish a deliberately scoped additional fixture. W07 package/tailoring needs native-provider success first; shared shell needs drawer/focus and bulk/saved-view cases; career/mail/admin need their specified interactive and provider proof. Screen-reader/touch/reflow and the full EN/NB × light/dark × desktop/mobile matrix remain visual/UX gates.
**F04 remains open.** The B06 repository/application changes are complete, but actual deployed proxy peer/listeners, firewall/NAT/IPv6, client IP, DNS/TLS/redirect and restart behavior remain unverified; follow the existing [operator commands](../../audits/2026-09-07/validation/b06-completion.md). Prior main CI run 743 failed in the browser worker and did not deploy; this branch's local success does not repair or certify that runner. Pushing this feature branch is a preservation checkpoint, not a production deployment or a release-readiness claim.
No Phase 3 implementation, visual redesign, component-library migration, B07 or later security ticket has begun.
+56
View File
@@ -0,0 +1,56 @@
# Redesign traceability
Phase 2 starts at `2d0f131`. The [preservation matrix](PRESERVATION_MATRIX.md) is the stable baseline: **PRES-E01…PRES-A03**, in the original ledger's groups (not one contiguous numeric range). Old references such as C07 remain valid aliases. Subdivide a later workflow with a suffix, for example `PRES-C07.override-reset`; do not reuse an ID or silently change its meaning.
## Required chain for each later change
`PRES-ID → requirement/source contract → implementation commit + changed owner → regression test + executed result → visual/UX evidence`
The requirement for every current PRES-ID is its **complete original row** in [FUNCTIONALITY_INVENTORY.md](../audit/FUNCTIONALITY_INVENTORY.md), including the source contract. A proposed new requirement uses a separate `NEW-xxx` ID referencing the product brief; it cannot overwrite a PRES requirement. Defects use their original audit IDs or the separate P2-D IDs below, not “preserve the broken behavior.”
For every implementation PR/session, add a row to this file (or link its scoped trace sheet here) with:
| Field | Required evidence |
|---|---|
| PRES-ID / requirement | Original ledger group plus the precise sub-workflow being changed; target-brief requirement if applicable |
| Baseline → destination | Existing route, capture/query/alias/keyboard entry and intended location; preserved/relocated/merged/explicitly deprecated |
| Implementation | Commit SHA, affected components/API owners, reason for the change; “unchanged” is valid but not “done” |
| Automated regression | Named behavioral test, file, command/result and provider/test layer; include negative/dirty/error cases |
| Visual/UX validation | Screenshot/video or review artifact with route, populated/empty/error/locked state, viewport, theme, locale, keyboard/focus result and date |
| Gaps / decision / reviewer | Known baseline defects and intentional missing proof; approval reference only when semantics/deprecation need it |
No screenshot alone proves data preservation. No mocked API test alone proves ownership. No successful localhost run proves F04. A shifted feature remains protected after moving to another page.
## Phase 2 changes (test/CI checkpoint only)
All application implementations and routes remain at their Phase 1 behavior. The commit containing this document identifies the Phase 2 implementation of **regression protection**, not a product migration. Use `git log -- docs/redesign/phase-2` to resolve its SHA without a self-referential commit placeholder.
| PRES IDs → existing requirement | Phase 2 change → automated oracle | Visual/UX evidence |
|---|---|---|
| E07, J04 → command job/company/add entry and reviewed capture | [quick-command-preservation](../../../job-tracker-ui/src/quick-command-preservation.test.tsx): three cases; destinations, callback and no-create boundary | No visual redesign. Native browser keyboard search/add evidence below |
| C11 → per-section review never implicitly applies | [ai-section-assistant](../../../job-tracker-ui/src/ai-section-assistant.test.tsx): reject/close, edit then accept, failed suggestion retry | jsdom interaction only; no model or visual certification |
| C07, C11 → whole-document review changes only accepted CV settings | [cv-builder-deep-link](../../../job-tracker-ui/src/cv-builder-deep-link.test.tsx): apply/reject and invalid/missing/duplicate block responses | jsdom current/proposed comparison; real canonical isolation below |
| W06 → rejected letter does not replace saved content | [application-assets](../../../job-tracker-ui/src/application-assets.test.tsx): reject clears proposal, original remains, no dirty/save | No provider contacted; real delivery remains outside this workflow |
| S03, W11 → scenario-specific rules and retryable preferences | [settings-view](../../../job-tracker-ui/src/settings-view.test.tsx): unchanged scenarios in payload; failed notification save retains draft and retries | Responsive browser preference evidence below |
| C01, C06, C07, C10 → canonical/sibling isolation and responsive editor persistence | [redesign-preservation browser](../../../job-tracker-ui/e2e/redesign-preservation.spec.ts): mobile override, preview/edit, reload, desktop preview; API compares master and sibling before/after | Current Chromium UI at 390×844 and 1440×900, EN/default theme. Behavioral viewport check, not visual approval |
| W01, W05–W08 → source relationships and frozen submission | Same browser spec: fixture creates actual job/CV/letter/file; captures via legacy CV workspace entry | **Expected failure P2-D01:** capture fails on SQLite. Later source-mutation/archive checks not reached; do not mark this migration ready |
| E07, J04, W01 → real command launcher and old links | Same browser spec: Ctrl+K job selection, actual App legacy match link, reviewed add leaves job count unchanged | Current desktop route/keyboard behavior only |
| S03, W11 → responsive rules/notification controls | Same browser spec: edit rule mobile→desktop, save, native API check; notification false survives reload; independent direct rule save | 390×844/1440×900 EN/default theme; no screenshot-based redesign |
| A01, S04, E07 → hidden admin navigation is not authorization; Free AI locks | Same browser spec: hidden admin menu, direct users read/create 403; ordinary CV creation succeeds, all three AI actions disabled, API AI 403 | Current non-admin browser + real API. Admin route shell may render, but cannot retrieve privileged data |
| All 57 → reliable test type baseline | [package script](../../../job-tracker-ui/package.json), [CI gate](../../../.gitea/workflows/ci-deploy.yml): `npm run typecheck` before Jest | Static TypeScript for existing src/app scope; no visual or app change |
## Phase 3 handoff and later migration gates
Phase 3 is **UX architecture documentation**, not a new implementation batch: grouped sidebar/page hierarchy; Jobs table/board view entry; canonical Career Profile versus derived CV/document relationships; full-page versus optional preview; contextual AI review pattern; mobile task flows. Map all 31 existing routes, both aliases, capture/notification/provider entries and all 57 PRES rows to intended destinations.
Keep current MUI/Emotion/React Router/API and ownership contracts while designing. Brand/name/accent and cross-device dashboard customization remain genuine product decisions for the dependent work; do not ask about facts already in the audit.
Before Phase 4/5 code, require an approved route/preservation plan, targeted regression fixtures for that surface's gaps, a shared accessibility/state contract, and coordinated integrity/recovery dependencies. In particular:
- Do not restructure package/tailoring workflows while P2-D01 blocks native success proof.
- Do not conflate B02 identity, stale-CV revision and create-intent idempotency. Those queue items remain distinct; B07 was not started.
- Do not drop mail draft revisions, explicit send/new-attempt controls or owner-bound references.
- Before migrating shared controls, validate EN/NB × light/dark × desktop/mobile, keyboard focus, error/empty/dirty states and representative loaded data. Real screen reader/touch/reflow tests remain manual.
- Do not label a release healthy until the previously failed CI browser runner is diagnosed and the required pipeline passes. F04 requires actual production ingress evidence.
Future trace sheets must link here. There are **no Phase 3+ implementation commits or visual sign-offs** in this checkpoint.