From 3047b6c4a87c43de6f397e4a3d109be9ce3ddeca Mon Sep 17 00:00:00 2001 From: cesnimda Date: Mon, 12 Oct 2026 08:24:23 +0200 Subject: [PATCH] fix(career): preserve source ids and absent metadata --- docs/redesign/phase-7/COMMITS.md | 4 +- docs/redesign/phase-7/DEBT.md | 8 +- docs/redesign/phase-7/PRESERVATION.md | 6 +- docs/redesign/phase-7/README.md | 6 +- docs/redesign/phase-7/p7-02/README.md | 6 +- .../p7-02/evidence/career-results.json | 35 +- docs/redesign/phase-7/p7-03/README.md | 52 + .../p7-03/evidence/entry-baseline.json | 109 + .../p7-03/evidence/source-id-results.json | 2779 +++++++++++++++++ .../evidence/source-id-static-checks.json | 104 + docs/roadmap/todo.md | 4 +- .../e2e/phase7-career-source-ids.spec.ts | 254 ++ job-tracker-ui/src/profile-page.test.tsx | 21 +- job-tracker-ui/src/profileCv.test.ts | 75 + job-tracker-ui/src/profileCv.ts | 16 +- 15 files changed, 3458 insertions(+), 21 deletions(-) create mode 100644 docs/redesign/phase-7/p7-03/README.md create mode 100644 docs/redesign/phase-7/p7-03/evidence/entry-baseline.json create mode 100644 docs/redesign/phase-7/p7-03/evidence/source-id-results.json create mode 100644 docs/redesign/phase-7/p7-03/evidence/source-id-static-checks.json create mode 100644 job-tracker-ui/e2e/phase7-career-source-ids.spec.ts create mode 100644 job-tracker-ui/src/profileCv.test.ts diff --git a/docs/redesign/phase-7/COMMITS.md b/docs/redesign/phase-7/COMMITS.md index 2e05e05..980f964 100644 --- a/docs/redesign/phase-7/COMMITS.md +++ b/docs/redesign/phase-7/COMMITS.md @@ -12,7 +12,9 @@ Entry is the completed Phase6 successor receipt `b5319981ad3d1bd635daff861453d23 | P7-02 onboarding guidance sub-slice | `d21501aa7e5f9040937fa821d6a77d823b7e08eb` | [Report](p7-02/README.md), [frozen source/runtime](p7-02/evidence/onboarding-results.json): affected32/2 (+23 net over nine inherited subset cases), ordinary native13/regression4, app/browser types/lint/build and actual13-image review pass. BuildbwZtqlczGqVRJ0J01IxVK; thirteen all-enabled scans0/13 incompletes with M11/manual/provider conditions. Retry-focus unit/native RED and earlier12-pass history retained; latest full573/89 inherited,596 derived only. Implemented onboarding CONDITIONAL GO; slice-specific hygiene PASS (four commands0,9docs/329links/0errors,57/32 retained) and normal development push directly verified2026-10-11 23:55:12.614723UTC: localHEAD=origin=live developmentd21501aa; local/origin/live main27657f3 unchanged; clean worktree at observation. Actual receipt appended by successor. Career overview/evidence and whole P7-02 pending;57/32 unchanged/main NO-GO | | P7-02 SQLite evidence-list compatibility repair | `01281f52d9279ecdbd3363a11d2e9cb71230bf49` | [Separate repair](p7-02/README.md#separate-evidence-list-provider-repair), [frozen backend/HTTP evidence](p7-02/evidence/evidence-list-repair.json): actual SQLite/HTTP RED0/1 each; new SQLite1/1, fresh guards91/91 and Release0warnings/errors plus ordinary HTTP1/1 GREEN. SQL owner filter/other-provider ordering unchanged; no schema/action/payload change, owned list remainsO(N). Fullbackend1,034 derived only from inherited1,033+1. Bounded local repair GO; slice-specific hygiene PASS00:05:02UTC (9docs337links/0errors,57/32 retained), normal push directly verified2026-10-12 00:06:47.145743UTC: localHEAD=origin=live development01281f52, local/origin/live main27657f3 unchanged; five unfinished Career paths retained/worktree not clean. Actual receipt appended by successor; Career UI/whole P7-02 pending; in-flight frontend excluded | -| P7-02 Career overview/evidence and final implemented checkpoint outcome | PENDING normal commit/push | [Report](p7-02/README.md#career-overviewevidence-commit), [frozen finite evidence](p7-02/evidence/career-results.json): affected46/3 (+14 cases), native14 and fresh ordinary P2-D01/mobile-override2, types/lint/build pass; all22 final PNGs actually inspected. BuildqG82wPnFf-IsAkFvXkmn6,75-file export;0 violations/99 incompletes and M09/M11/manual/provider qualifications retained. Actual Delete-cancel RED/repair and Windows CRLF test correction retained. Implemented P7-02 CONDITIONAL GO; [final Career hygiene](p7-02/evidence/career-static-checks.json) PASS05:48:32UTC (four commands0,9docs347links0errors/57+32 retained); normal push pending. Fullfrontend610/backend1,034 derived only;57/32 unchanged/main NO-GO | +| P7-02 Career overview/evidence and final implemented checkpoint outcome | `8b4d5c21125e800199d3ecc2d9c059a80ac5125d` | [Report](p7-02/README.md#career-overviewevidence-commit), [frozen finite evidence](p7-02/evidence/career-results.json): affected46/3 (+14 cases), native14 and fresh ordinary P2-D01/mobile-override2, types/lint/build pass; all22 final PNGs actually inspected. BuildqG82wPnFf-IsAkFvXkmn6,75-file export;0 violations/99 incompletes and M09/M11/manual/provider qualifications retained. Actual Delete-cancel RED/repair and Windows CRLF test correction retained. Implemented P7-02 CONDITIONAL GO; [final Career hygiene](p7-02/evidence/career-static-checks.json) PASS05:48:32UTC (four commands0,9docs347links0errors/57+32 retained); normal push directly verified2026-10-12 05:51:04.849644UTC: localHEAD=origin=live development8b4d5c2, local/origin/live main27657f3 unchanged, worktree clean at observation. Actual receipt appended by successor; P7-03 entry satisfied with mandatory stable-ID/concurrency conditions. Fullfrontend610/backend1,034 derived only;57/32 unchanged/main NO-GO | + +| P7-03 separate forward source-ID/null-metadata compatibility repair | PENDING normal commit/push | [Prerequisite report](p7-03/README.md#prerequisite-runtime-and-finite-acceptance), [frozen finite results](p7-03/evidence/source-id-results.json): unit46/3 (+8/+1 suite), native2 and fresh ordinary preservation2, types/lint/build pass; all11 readback flagsTRUE and two final PNGs inspected with capture qualifications. One frontend normalizer owner only; API binary unchanged/no new backend build. BuildbzQiDlr6LeM9Gsel4WRS8;0 new axe attachments. Bounded forward repair GO; [final static checks](p7-03/evidence/source-id-static-checks.json) PASS06:21:53UTC (four commands0,10docs370links0errors/57+32 retained); normal push pending. Old orphaned overrides and concurrency remain unrepaired; full618/90/browser216/backend1,034 derived only;57/32 unchanged/main NO-GO | Hashes and remote receipts are appended by a successor to avoid self-referential commit hashes. Each row records actual commands/results, source scope, remaining conditions, normal push and immediate direct remote identity; partial or blocked evidence is recorded without inventing success. Subsequent receipt metadata is a separately reviewable documentation unit, with its own hash reported after push rather than an endless receipt chain. diff --git a/docs/redesign/phase-7/DEBT.md b/docs/redesign/phase-7/DEBT.md index 3dca96e..9b447f5 100644 --- a/docs/redesign/phase-7/DEBT.md +++ b/docs/redesign/phase-7/DEBT.md @@ -95,10 +95,16 @@ Actual review demonstrated lost focus when Retry disappeared. Five strengthened [Career results](p7-02/evidence/career-results.json) retain affected46/3, native14 and fresh existing P2-D01/mobile-override2, types/lint/build and actual22-image review passing. Delete-cancel focus loss was reproduced in native and strengthened unit cases before a minimal state-order correction; the shared confirmation and duplicate guard remain. The separate clipboard failure was native Windows LF→CRLF conversion, with only CRLF→LF test normalization and raw codepoint retention. All prior failures stay in immutable history; no product clipboard or byte-exact OS claim is made. -Twenty-two all-enabled scans retain0 violations/**99 incompletes**: contrast74 `bgOverlap`+22 invisiblebadge `shortTextContent`, plus3 hidden-focus `#menu-` MUI select portals. Actual section/form keyboard and corrected cancel/retry focus pass; M09/M11 contextual contrast/reader and RD06/RD07 human/device/zoom remain open. Error captures retain inherited shell Skip-link/scroll focus qualification and controlled English server-fixture detail. No density/provider/production acceptance is inferred. Source/test/export/runner/raw/unit history is frozen in `.artifacts/phase7/p7-02/career-final/`,152 refs verified; final buildqG82wPnFf-IsAkFvXkmn6. Implemented P7-02 is CONDITIONAL GO; [Career final hygiene](p7-02/evidence/career-static-checks.json) PASS (four commands0,9docs347links0errors), normal push pending. Latest full573/89 remains inherited;610/89 and backend1,034 are derived expectations only. +Twenty-two all-enabled scans retain0 violations/**99 incompletes**: contrast74 `bgOverlap`+22 invisiblebadge `shortTextContent`, plus3 hidden-focus `#menu-` MUI select portals. Actual section/form keyboard and corrected cancel/retry focus pass; M09/M11 contextual contrast/reader and RD06/RD07 human/device/zoom remain open. Error captures retain inherited shell Skip-link/scroll focus qualification and controlled English server-fixture detail. No density/provider/production acceptance is inferred. Source/test/export/runner/raw/unit history is frozen in `.artifacts/phase7/p7-02/career-final/`,152 refs verified; final buildqG82wPnFf-IsAkFvXkmn6. Implemented P7-02 is CONDITIONAL GO; [Career final hygiene](p7-02/evidence/career-static-checks.json) PASS (four commands0,9docs347links0errors), normal push8b4d5c2 directly verified05:51:04UTC, main unchanged/clean worktree at observation. Latest full573/89 remains inherited;610/89 and backend1,034 are derived expectations only. Two independent read reviews identify the existing normalizer dropping job/education/certification/project stable IDs while overrides reference those IDs. P7-03 must separately reproduce and repair optional-ID preservation before structured presentation, with canonical/sibling native and payload proof. This inherited risk is distinct from RD21 stale-save/idempotency and is neither introduced nor closed by P7-02. No date-loss claim is made. Prove dirty-locale/pending-write draft ownership and recovery, and resolve or explicitly bound RD21 before changing save/history owners. Other manual/provider/production and C11/Phase8 gates remain unchanged. +### P7-03 forward-ID repair disposition + +[Source-ID results](p7-03/evidence/source-id-results.json) reproduce ID/override loss and null→0 metadata before a bounded frontend normalizer correction; final unit46/3, native2/preservation2, types/lint/build and11 exact readback flags pass. The +8/+1-suite addition gives only derived618/90; browser216/backend1,034 likewise are not new full runs. Prior API DLL/91 targeted guard evidence is inherited unchanged. No automatic unsafe matching/remap of older orphaned overrides occurs; historical records stay. [Final source-ID hygiene](p7-03/evidence/source-id-static-checks.json) PASS (four commands0,10docs370links0errors); normal push pending. + +RD21 now has actual stale200/last-writer/append-restore/raw-current/owner-denial characterization, retaining its concurrency risk before any save/history semantics change. Dirty-locale and held-PUT/pending-write ownership/recovery still require proof for the presentation slice. Two final PNG reviews remain qualified: original editor sticky-scroll capture and blended frozen-dialog/workspace image, with transition cause unconfirmed. No new axe attachments or human/device/theme/settled-dialog acceptance; RD06/RD07/RD14/P7-06/P7-11 requirements remain. Source-ID forward repair does not close full C01/C07 or import/history/production obligations. + The early Phase6 runner retained exact failure commands/reports/logs but reused result folders, so not all old screenshots/traces/error-context paths remain resolvable. Later runs archive the whole previous output; current successful attachments have exact provenance. Preserve that limit rather than claiming complete old failure-trace retention. Native Windows Chromium/local SQLite/synthetic fixtures and finite PDF oracles do not establish deployed Linux, human semantics, physical devices, real provider quality or production load. API transferSize0 is unavailable cross-origin timing information, not zero network bytes. CDP document/node/heap snapshots can retain earlier navigation/CV iframe documents and do not prove leak/growth. The existing measured Board/Dashboard candidates require baseline/comparative evidence before a repair or capacity claim. diff --git a/docs/redesign/phase-7/PRESERVATION.md b/docs/redesign/phase-7/PRESERVATION.md index 6057e10..be446fd 100644 --- a/docs/redesign/phase-7/PRESERVATION.md +++ b/docs/redesign/phase-7/PRESERVATION.md @@ -101,7 +101,7 @@ Full frontend521→573 adds52 cases across four new suites with no removed/renam ### P7-02 reconciliation, no full-group upgrade -The [onboarding](p7-02/evidence/onboarding-results.json), [separate provider repair](p7-02/evidence/evidence-list-repair.json) and [Career](p7-02/evidence/career-results.json) records retain distinct executed scopes and failures. All57 remain **56 PARTIAL /1 DEFERRED**, with0 PASS/FAIL, and all32 routes remain retained. Career runtime/actual visual review is conditional; [final slice hygiene](p7-02/evidence/career-static-checks.json) PASS (9docs347links0errors/four commands0); normal push pending. +The [onboarding](p7-02/evidence/onboarding-results.json), [separate provider repair](p7-02/evidence/evidence-list-repair.json) and [Career](p7-02/evidence/career-results.json) records retain distinct executed scopes and failures. All57 remain **56 PARTIAL /1 DEFERRED**, with0 PASS/FAIL, and all32 routes remain retained. Career runtime/actual visual review is conditional; [final slice hygiene](p7-02/evidence/career-static-checks.json) PASS (9docs347links0errors/four commands0); normal push8b4d5c2 directly verified05:51:04UTC, main unchanged/clean worktree at observation. | Protected groups | Fresh finite P7-02 proof | Remaining boundary | |---|---|---| @@ -113,6 +113,10 @@ The [onboarding](p7-02/evidence/onboarding-results.json), [separate provider rep Stable job/education/certification/project IDs dropped by the existing normalizer are an inherited **P7-03 entry risk** requiring separate RED/payload/native proof and optional-ID repair before structured editing. This is distinct from RD21 concurrency and is not a P7-02 repair claim. Dirty-locale and pending-write ownership/recovery must also be qualified before save/history expansion. +### P7-03 forward-ID prerequisite reconciliation + +[Finite repair evidence](p7-03/evidence/source-id-results.json) adds ordinary unit46/3 (+8 cases/+1 suite) and native2 plus fresh P2-D01/mobile-override2 with types/lint/build passing. C01/C02/C07/E09 optional source IDs/nullable metadata, canonical payload/readback and selected/sibling/history/frozen boundaries are preserved; all11 final flags areTRUE. The second case characterizes stale200/append-restore/raw-current/foreign-owner denial; it does not close RD21 concurrency. No schema/backend contract or PDF/model action changes. Both lanes have0 axe attachments, and two inspected PNGs remain finite capture qualifications, not settled-dialog/design conformance. [Final source-ID hygiene](p7-03/evidence/source-id-static-checks.json) PASS (four commands0,10docs370links0errors); normal push pending; all57 statuses/32 routes unchanged. Older orphaned overrides require separate justified recovery, and P7-03 structured/import presentation remains pending. + [INVENTORY.md](p7-00/INVENTORY.md#current-route-coverage) reconciles exactly32 current App patterns against [route acceptance](../phase-5/p5-15/ROUTE_ACCEPTANCE.md); all whole-route groups remain PARTIAL. Preserve Board/Application/mail aliases and actual query/hash/state behavior, section/sub precedence, safe internal from, numeric navigation-helper output, capture consumption, focusJobId and provider/token destinations. No Documents/Notifications/aggregate Admin/new Career destination is inferred without contract/content evidence. P2-D01 remains the ordinary passing [frozen-workspace test](../../../job-tracker-ui/e2e/redesign-preservation.spec.ts#L73), retaining native capture/readback/archive bytes/canonical/sibling proof. No skip, expected-failure marker or relaxed oracle may replace it. Preserve server roles/account/tenant/owned-resource denial; canonical Career versus CV overrides; revision/conflict/recoverable drafts; private/public PDF admission/revocation; unchanged physical pagination; immutable packages; existing grounding/proposal/stale guards and Production C11 withholding. diff --git a/docs/redesign/phase-7/README.md b/docs/redesign/phase-7/README.md index 09c6968..a3aa451 100644 --- a/docs/redesign/phase-7/README.md +++ b/docs/redesign/phase-7/README.md @@ -10,8 +10,8 @@ The entry commit is `b5319981ad3d1bd635daff861453d23c0de5320b` on `codex/ui-rede |---|---|---| | [P7-00](p7-00/README.md) | Fresh scope inventory and fixture baseline | Complete finite identity/route/matrix/static checks; inherited runtime separated. Push receipt recorded by the successor before page changes | | [P7-01](p7-01/README.md) | Authentication and account-security presentation | Public sub-slice CONDITIONAL GO, pushed8ad720d with direct receipt; account implementation/runtime/actual8-image review CONDITIONAL GO (573/89 +6/22/10); pushedad7b419 with final static PASS/direct receipt19:16:15UTC; main unchanged | -| [P7-02](p7-02/README.md) | Onboarding and Career overview/evidence | Entryad7b419 pushed/verified; bounded onboarding CONDITIONAL GO32/13/4+types/lint/build/13 actual PNG inspections, hygiene PASS and d21501aa push verified23:55:12UTC. Separate SQLite evidence-list repair91 guards/HTTP1/Release passed, pushed01281f52/direct receipt00:06:47UTC with unfinished Career work preserved. Career affected46/3/native14/preservation2/types/lint/build and actual22-image review pass; implemented checkpoint CONDITIONAL GO with99 incompletes/manual gates. Career final hygiene PASS (four commands0,9docs347links0errors); normal push pending; main unchanged | -| P7-03 | Career structured editing and import review | P7-02 normal push; separately reproduce/repair stable source-ID preservation before structured presentation, then prove dirty-locale/pending-write ownership and resolve or bound RD21 concurrency; planned | +| [P7-02](p7-02/README.md) | Onboarding and Career overview/evidence | Entryad7b419 pushed/verified; bounded onboarding CONDITIONAL GO32/13/4+types/lint/build/13 actual PNG inspections, hygiene PASS and d21501aa push verified23:55:12UTC. Separate SQLite evidence-list repair91 guards/HTTP1/Release passed, pushed01281f52/direct receipt00:06:47UTC with unfinished Career work preserved. Career affected46/3/native14/preservation2/types/lint/build and actual22-image review pass; implemented checkpoint CONDITIONAL GO with99 incompletes/manual gates. Career final hygiene PASS (four commands0,9docs347links0errors); normally pushed8b4d5c2/direct localHEAD=origin=live receipt05:51:04UTC, clean worktree/main unchanged | +| [P7-03](p7-03/README.md) | Career structured editing and import review | P7-02 pushed8b4d5c2; separate forward ID/null-metadata repair unit46/native2/preservation2/types/lint/build and finite readback/image review pass, final hygiene PASS (four commands0,10docs370links0errors), normal push pending. Stale contract characterized without concurrency repair; dirty-locale/pending-write proof precedes structured/import presentation; planned | | P7-04 | CV library and public entry | Existing gallery/editor and P7-03 source language; planned | | P7-05 | Discovery, Companies, Offers and Reminders | Existing domain owners and Jobs return context; planned | | P7-06 | Remaining Application forms and global correspondence | Existing seven-section workspace, immutable packages and draft/send owners; planned | @@ -39,7 +39,7 @@ The separate [account runtime manifest](p7-01/evidence/account-results.json) rec ## Working constraints -The [P7-02 onboarding slice](p7-02/evidence/onboarding-results.json) adds actual fresh affected32/2 (+23 cases over its nine-case inherited subset), ordinary native13 and separate Dashboard/Analytics4, app/browser types/lint/build and13 inspected final PNGs. Its13 all-enabled scans retain0 violation nodes/13 invisible-zero notification-badge contrast incompletes; no manual conformance or real provider grant is inferred. The retry-focus defect was reproduced by five strengthened unit cases and a focused native failure before correction. Latest full frontend573/89 remains inherited;596/89 is only a derived expectation. Onboarding implemented scope is CONDITIONAL GO final hygiene PASS and normal pushd21501aa/direct receipt23:55:12UTC; Career successor affected46/3/native14/preservation2 and22 actual image inspections now pass; implemented P7-02 scope is CONDITIONAL GO with final Career hygiene PASS; normal push pending. Its22 all-enabled scans retain0 violations/99 incompletes;610/89 is derived only, latest full573/89 unchanged. Frozen [Career results](p7-02/evidence/career-results.json) retain failures/source/export/manual qualifications;57 groups/32 routes unchanged and production NO-GO. +The [P7-02 onboarding slice](p7-02/evidence/onboarding-results.json) adds actual fresh affected32/2 (+23 cases over its nine-case inherited subset), ordinary native13 and separate Dashboard/Analytics4, app/browser types/lint/build and13 inspected final PNGs. Its13 all-enabled scans retain0 violation nodes/13 invisible-zero notification-badge contrast incompletes; no manual conformance or real provider grant is inferred. The retry-focus defect was reproduced by five strengthened unit cases and a focused native failure before correction. Latest full frontend573/89 remains inherited;596/89 is only a derived expectation. Onboarding implemented scope is CONDITIONAL GO final hygiene PASS and normal pushd21501aa/direct receipt23:55:12UTC; Career successor affected46/3/native14/preservation2 and22 actual image inspections now pass; implemented P7-02 scope is CONDITIONAL GO with final Career hygiene PASS and normal push8b4d5c2 directly verified05:51:04UTC, main unchanged. Its22 all-enabled scans retain0 violations/99 incompletes;610/89 is derived only, latest full573/89 unchanged. Frozen [Career results](p7-02/evidence/career-results.json) retain failures/source/export/manual qualifications;57 groups/32 routes unchanged and production NO-GO. Use the current MUI/Emotion theme, PageLayout/section primitives, ViewStateNotice/useViewResource, Router, i18n, notification and save owners. Preserve query/history/aliases, account/tenant/role boundaries, canonical Career facts versus CV overrides, revision recovery, frozen packages and original PDF pagination/oracles. Do not infer new Documents/Notifications/aggregate Admin routes from illustrative navigation. No new hard-coded user-facing strings. diff --git a/docs/redesign/phase-7/p7-02/README.md b/docs/redesign/phase-7/p7-02/README.md index b83a3c8..636688f 100644 --- a/docs/redesign/phase-7/p7-02/README.md +++ b/docs/redesign/phase-7/p7-02/README.md @@ -1,6 +1,6 @@ # P7-02 — Onboarding and Career overview/evidence -**Status: implemented P7-02 scope CONDITIONAL GO. Onboarding and the separate SQLite repair are pushed; Career runtime/visual acceptance and final slice hygiene PASS; normal push pending.** Follow the exact [approved handoff](../../phase-6/p6-05/PHASE7_HANDOFF.md#migration-order-and-commit-boundaries). This checkpoint has two bounded commits: onboarding guidance first, then Career overview/evidence. Structured Career editing/import/history remains P7-03; no alternative checkpoint order or new route is introduced. +**Status: implemented P7-02 scope CONDITIONAL GO. Onboarding and the separate SQLite repair are pushed; Career runtime/visual acceptance and final slice hygiene PASS; normally pushed8b4d5c2 with direct receipt.** Follow the exact [approved handoff](../../phase-6/p6-05/PHASE7_HANDOFF.md#migration-order-and-commit-boundaries). This checkpoint has two bounded commits: onboarding guidance first, then Career overview/evidence. Structured Career editing/import/history remains P7-03; no alternative checkpoint order or new route is introduced. ## Accepted entry baseline @@ -75,13 +75,13 @@ Final workspace14/evidence8 replace inherited7+1, adding **14 net cases**; the e | Keyboard/focus | Retry focus, actual section selection/subsequent form traversal and corrected cancel-trigger restoration pass. Failed-save/delete captures retain inherited shell Skip-link/scroll context; complete human focus/spoken-state acceptance remains unverified | | Responsive/localised visual review | Parent actually opened all22 final raw PNGs: eight EN/NB/theme samples320/360/390/768/1024/1280 short landscape/1440/1920 plus six pending/error states. Fields, titles and actions wrap without observed clipping; all22 recorded root-overflow values are0; the1440 many-item fixture has11 rows | | Accessibility | Twenty-two all-enabled scans retain0 violation nodes/99 incomplete occurrences. No automated result establishes reader/device/zoom conformance; density was not varied and Career has no global density control | -| Exit | Runtime and actual22-image review support implemented-scope CONDITIONAL GO. Slice-specific final hygiene PASS; normal commit/push remains pending; main/production stays NO-GO | +| Exit | Runtime and actual22-image review support implemented-scope CONDITIONAL GO. Slice-specific final hygiene PASS; normal push8b4d5c2 directly verified; main/production stays NO-GO | All99 incomplete contexts remain recorded:96 `color-contrast` (74 `bgOverlap` plus22 invisible notification-badge `0`/`shortTextContent`) and3 `aria-hidden-focus` targeting `#menu-`, the hidden MUI section-select portal in narrow evidence states. The actual section and subsequent form keyboard workflows pass; **M09/M11** reader/contextual contrast/forced-colors requirements remain pending. Complete HTML/data/related-node/check vectors remain in the exact hashed raw report, with every rule/target/check context summarized in the portable manifest. Controlled English500 details are server-fixture text, distinct from translated product fallback. Sticky appbar/Skip-link placement in error captures reflects recorded scroll/focus context, not a new demonstrated overflow defect. Final four-source LF digest is `190d0a24368bfc3cc76550ff0f74c272200d3a30f61218a86628449ac83735ce`; build `qG82wPnFf-IsAkFvXkmn6`; **75 exported files**, digest `50896e8ad6934b909b83cc487eaf3579516921fde54b19e50a9039db68e04869`. Final native report SHA256 is `f7a166ec33ecdedd9f0374290961c0daaf1279d8c89d3425fbe3b3a66c4a2360`. Source/test/build/export/runner/config, whole runtime/attempt tree, unit history and entry manifests are frozen under `.artifacts/phase7/p7-02/career-final/`:152 file-reference hashes verified,428 runtime files and81 unit files retained. Parent independently verified152 references/84 unique referenced files with0 errors. Raw hashes/counts remain measured bytes; portable JSON/source canonical-LF policies are explicit. Earlier first-build75-file export/report and failed unit/native attempts stay historical; the first source had already been corrected before export archival, so no original-source snapshot is claimed. -Slice-specific [Career static checks](evidence/career-static-checks.json) passed2026-10-12 05:48:28–05:48:32UTC: four secret/working/staged/entry-whitespace commands exit0; nine Markdown documents/347 local links checked with0errors at that observation;57 qualified groups/32 routes retained and main27657f3 unchanged. Canonical UTF-8/LF static SHA256 is `f575a6304bb4d00e11ee77270d60ebdee11f1cd8faf9692adb4c473961b4d8f4`. Final hygiene PASS; normal commit/push receipt remains pending. Runtime/source/export/manual qualifications are unchanged. +Slice-specific [Career static checks](evidence/career-static-checks.json) passed2026-10-12 05:48:28–05:48:32UTC: four secret/working/staged/entry-whitespace commands exit0; nine Markdown documents/347 local links checked with0errors at that observation;57 qualified groups/32 routes retained and main27657f3 unchanged. Canonical UTF-8/LF static SHA256 is `f575a6304bb4d00e11ee77270d60ebdee11f1cd8faf9692adb4c473961b4d8f4`. Final hygiene PASS; normal push `8b4d5c21125e800199d3ecc2d9c059a80ac5125d` directly verified2026-10-12 05:51:04.849644UTC: localHEAD=origin=live development, local/origin/live main27657f3 unchanged and worktree clean at observation. The successor appends the actual receipt. Measured source hashes apply at8b4d5c2 and immutable snapshots after later P7-03 edits; runtime/source/export/manual qualifications are unchanged. ## Preservation and exit diff --git a/docs/redesign/phase-7/p7-02/evidence/career-results.json b/docs/redesign/phase-7/p7-02/evidence/career-results.json index fa6bd5d..a222c68 100644 --- a/docs/redesign/phase-7/p7-02/evidence/career-results.json +++ b/docs/redesign/phase-7/p7-02/evidence/career-results.json @@ -128,6 +128,10 @@ "staticExportSnapshot": { "root": ".artifacts/phase7/p7-02/career-final/export", "qualification": "Exact raw measured files from job-tracker-ui/out; original export digest paths/algorithm unchanged" + }, + "sourceApplicability": { + "acceptedCommit": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "qualification": "Measured P7-02 source hashes apply at this accepted commit and the immutable sourceSnapshots, not the live workspace after legitimate P7-03 edits. All original measured hashes/source/export identities remain unchanged." } }, "environment": { @@ -7837,7 +7841,7 @@ "Density not varied; no actual global Career density control, human screen reader, browser zoom, physical touch/software keyboard or real provider acceptance.", "Canonical/job concurrency/save-import-history ownership remains P7-03/RD21; P5-13 deferred, Phase8 separate and production NO-GO." ], - "decision": "Career implemented scope and integrated P7-02 CONDITIONAL GO; final hygiene PASS, actual normal push pending; all57 group statuses remain qualified" + "decision": "Career implemented scope and integrated P7-02 CONDITIONAL GO; final hygiene PASS and normal development push directly verified; all57 group statuses remain qualified" }, "preservation": { "groups": 57, @@ -7848,10 +7852,33 @@ "qualifications": [ "Full vectors remain in raw reports; native/finite images are not human reader/zoom/device/provider acceptance.", "P7-03 concurrency/import/history save-owner work, P5-13 AI activation and Phase8 remain separate.", - "Production NO-GO; normal development push receipt pending." + "Production NO-GO; normal development push directly verified, main unchanged. Manual/deferred gates remain." ], "pushReceipt": { - "status": "PENDING_ACTUAL_PUSH" + "status": "PUSHED_AND_DIRECTLY_VERIFIED", + "receipt": { + "observedUtc": "2026-10-12T05:51:04.849644+00:00", + "branch": "codex/ui-redesign-phase4", + "head": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "origin": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "liveRemote": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "main": { + "local": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "origin": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "live": "27657f31131cd95d42f0e1290853ec9c9b3959a4" + }, + "workingTreeClean": true, + "porcelain": "", + "normalPush": true, + "productionDecision": "NO-GO" + }, + "raw": { + "path": ".artifacts/phase7/p7-02/career-final/push-receipt.json", + "sha256": "3de52b1b14ffeda63b18227dff32ce011b47b7608dcd13c38b43285b52f75f4a", + "bytes": 571, + "hashPolicy": "Exact saved raw bytes" + }, + "recordingPolicy": "Actual receipt appended by successor; no self-referential commit hash." }, "rawRetention": { "root": ".artifacts/phase7/p7-02/career-final", @@ -7960,6 +7987,6 @@ "status": "NO-GO", "qualification": "Local fetched refs; direct push observation recorded separately." }, - "qualification": "Final staged finite hygiene PASS; normal commit/push receipt pending. No runtime/manual qualification changed." + "qualification": "Final staged finite hygiene PASS at its recorded observation; subsequent normal push directly verified in pushReceipt. No runtime/manual qualification changed." } } diff --git a/docs/redesign/phase-7/p7-03/README.md b/docs/redesign/phase-7/p7-03/README.md new file mode 100644 index 0000000..a8019bc --- /dev/null +++ b/docs/redesign/phase-7/p7-03/README.md @@ -0,0 +1,52 @@ +# P7-03 — Career structured editing and import review + +**Status: accepted entry with mandatory dependencies; implementation/verification results PENDING.** Follow the [approved handoff](../../phase-6/p6-05/PHASE7_HANDOFF.md#migration-order-and-commit-boundaries): a structured-editor presentation commit, then a separate import/history presentation commit. The newly identified source-ID prerequisite is a separate bounded repair before those presentation changes; it does not introduce another checkpoint or schema. + +## Accepted entry and evidence limits + +P7-02 implemented scope is CONDITIONAL GO, normally pushed `8b4d5c21125e800199d3ecc2d9c059a80ac5125d`. Actual receipt2026-10-12 05:51:04.849644UTC records localHEAD=origin=live development, local/origin/live main27657f3 unchanged and a clean worktree. [Entry baseline](evidence/entry-baseline.json), [P7-02 report](../p7-02/README.md), [Career manifest](../p7-02/evidence/career-results.json) and [ledger](../COMMITS.md) retain the executed scope and receipt. + +Fresh P7-02 affected46/3, ordinary Career14/preservation2, app/browser TypeScript/lint/build, actual22-image review and final staged hygiene pass. Final build `qG82wPnFf-IsAkFvXkmn6`, four-source LF digest `190d0a24368bfc3cc76550ff0f74c272200d3a30f61218a86628449ac83735ce` and75-file export remain historical at8b4d5c2 and immutable snapshots after legitimate P7-03 edits. Its22 all-enabled scans retain0 violations/99 incompletes:74 contrast background-overlap,22 invisible-badge short-text and3 hidden MUI select-portal focus contexts. They remain M09/M11 qualifications, not human conformance. + +Latest full frontend **573/89** remains inherited from P7-01. Frontend610/89, backend1,034 and ordinary browser214 are **derived expectations only**, not fresh whole-suite executions. Backend1,033, sidecar49 and unchanged original16/36 plus8/24 rendering corpora are inherited Phase6 executions; separate P7-02 repair91 guards are fresh targeted proof. New P7-03 runtime results are pending. All57 groups remain56 PARTIAL/C11 DEFERRED and all32 routes retained. Production remains NO-GO; main stays unchanged. + +## Mandatory prerequisite repair + +Two independent read reviews identify [normalizeStructuredCv](../../../../job-tracker-ui/src/profileCv.ts) dropping existing job/education/certification/project IDs while CV overrides refer to those source IDs. The API can assign replacements after the save. This inherited risk is distinct from RD21 concurrency and was not introduced or repaired by P7-02. No date-loss claim is made: server StartDate derives from Start. + +First reproduce the loss in ordinary normalizer/payload and actual local canonical-save/CV-override workflows. Preserve supported optional IDs at the frontend owner, retaining behavior when an ID is absent; verify canonical/sibling readback and continued override matching. Keep the existing singleton contract, field shapes, owner guards and server allocation for genuinely new items. No schema, generic client-generated identity, server revision protocol or provider activation is implied. Commit/push this bounded prerequisite only after actual RED→GREEN, targeted guards and real-HTTP/native proof. + +The initial bounded unit RED at2026-10-12 05:54:52UTC passes25/fails5 of30 ordinary cases: six new normalizer cases plus existing24 Profile cases with the canonical payload assertion strengthened. Actual native baseline06:06:22–06:06:36UTC passes1/fails1 on unchangedqG82; a selected-DTO association timestamp fixture flaw was then corrected. Authoritative native RED06:08:57–06:09:10UTC again passes1/fails1: requested/persisted IDs fail, override title/bullet change from matching to nonmatching, and three null metadata fields become0. Selected/sibling DTOs, both histories and frozen content remain unchanged in the corrected proof. Separate first/corrected command/report/log/trace/embedded-attachment capsules are preserved under `.artifacts/phase7/p7-03/source-id-repair/baseline/` with0skip/retry/flaky; no PDF or concurrency repair follows. + +Two metadata cases extend the bounded new normalizer suite to8; revised unit RED06:08:59UTC passes26/fails6 of32 cases, including valid0/finite/numeric-string preservation. The approved frontend compatibility repair includes eight optional-ID additions and four nullish metadata guards in profileCv.ts, retaining existing field/payload contracts and valid numeric behavior. Baseline profileCv/CareerProfilePage raw snapshots match git show8b4d5c2 canonical LF bytes. Fresh **unit46/3 GREEN passed06:10:43UTC** (normalizer8+existingProfile24+workspace14); final native2/preservation2 and app/browser types/lint/build pass; final hygiene PASS and normal push remains **PENDING**. Null confidence is unit-proven; native RED captures the other three null fields. Planned618/90 adds eight cases/one suite to prior derived610/89, superseding the earlier six-case616 expectation; neither is a fresh full run. Forward ID preservation cannot safely remap older orphaned overrides automatically: historical records remain, with recovery requiring a separate justified decision. + +### Prerequisite runtime and finite acceptance + +[Frozen source-ID results](evidence/source-id-results.json) record actual final unit46/3, native2/2 at2026-10-12 06:12:25–06:12:37UTC and existing ordinary P2-D01/mobile-override2 at06:12:37–06:12:52UTC, with0skip/flaky/unexpected/retry. App/browser TypeScript, lint/build all exit0 at06:11:46–06:12:25UTC. Final export is `bzQiDlr6LeM9Gsel4WRS8`,75 files/digest `812182947b7af96a00f9568a83de1098f2824c53550c7119c76ec41803e71fbf`; repaired profileCv LF SHA256 `7e0b8aa13aa6df830f7e508c338c1e2dd995574bbfbd3233602654452f75cdb9`. One product owner/three test owners, six root lane receipts/raw, relevant unit/RED history, API identity, entry manifest and BUILD_ID/export/runner/config are frozen under `.artifacts/phase7/p7-03/source-id-repair/final/`. API DLL hash matches the prior repaired P7-02 binary; no new backend build/test is claimed, and prior91 guards remain inherited targeted evidence. + +Root verified all11 readback flags TRUE: IDs match all three recorded source snapshots, overrides continue to match, nullable metadata is preserved exactly, and selected/sibling/history/frozen boundaries remain asserted. Confidence null is unit-proven; the other three null metadata fields have native proof. The second ordinary native case explicitly characterizes the unchanged stale200/last-writer behavior, append-only restore/current raw source and foreign-owner denial. It supplies a bounded RD21 contract disposition for presentation-only work; **concurrency remains unrepaired**, with no new version/merge/schema guarantee. + +Root actually opened two final PNGs plus the corrected-RED failure viewport image. The final390x4683 existing-editor image reaches Save/content and captures sticky chrome at current scroll. The frozen-package image blends underlying workspace/chrome through the dialog; its possible transition cause is undiagnosed and settled-dialog visual acceptance remains P7-06/P7-11 qualification. These finite inspections are not a cosmetic migration or new responsive/theme/human acceptance. Both native lanes contain **0 axe attachments**; the earlier P7-02 incomplete inventory/manual gates remain, and no new axe clearance is inferred. + +**Bounded forward compatibility repair GO; final slice hygiene PASS, normal push PENDING.** Structured-editor and import/history presentation, old orphaned-override recovery and all manual/production gates remain pending. Fullfrontend618/90 and ordinarybrowser216 are derived only after this +8/+1-suite addition; no fresh full-suite result replaces inherited573/89. + +Slice-specific [source-ID static checks](evidence/source-id-static-checks.json) passed2026-10-12 06:21:50–06:21:53UTC: four secret/working/staged/entry-whitespace commands exit0;10 Markdown documents/370 local links checked with0errors at observation;57 qualified groups/32 routes retained, main unchanged. Canonical UTF-8/LF SHA256 is `3a910cd0041f2cf855484c161b21bc4f4b1de7446af80600315b4fcf18e76863`; exact static snapshot/log bytes are retained in the final capsule. Root independently verified81 refs/62 unique files and75-file frozen export before later review/receipt metadata. Normal push receipt remains pending; no new runtime or manual claim follows. + +Before changing save/history ownership, resolve or explicitly bound RD21 canonical profile/job stale-save and creation-intent behavior with actual stale-write/recovery tests. Prove dirty drafts survive UI-locale changes and relevant read-retry/navigation boundaries; prove held-PUT/pending-write snapshots, edit/save completion ownership and recoverable failure. Existing verified CV revision handling is a different contract. Presentation migration must retain current data-saving semantics and existing guards; do not infer a missing server token or invent one. + +## Approved presentation boundaries + +| Boundary | Existing owners and bounded change | Required finite acceptance | +|---|---|---| +| Structured editor | [CareerProfilePage](../../../../job-tracker-ui/src/views/CareerProfilePage.tsx), [CareerProfileSections](../../../../job-tracker-ui/src/views/career/CareerProfileSections.tsx), existing RichTextField/date/tag primitives; align headings, forms, states and responsive sections after prerequisite proof | All long-tail/custom fields retained; canonical singleton versus identified CVs/overrides clear; dirty-locale/pending-save/retry/cancel and owned readback, long phone forms, keyboard/focus/labels/errors and EN/NB/light/dark finite widths pass | +| Import review/history | Existing extraction/diff/selection/accept/discard/retry/history owners within CareerProfilePage; migrate their presentation without replacing persistence or renderer | Low-confidence select/deselect, explicit accept versus discard, retry/cancel/no provider on entry; real canonical/sibling/frozen readback and historical restore boundaries; retained draft/failure/focus, localised instructions and narrow/reflow states pass | + +Keep current Career section/query/history ownership, original source/import destinations, aliases and default-query removal. Use MUI/Emotion, PageLayout/sections, shared feedback, notification/confirmation and i18n owners. No new information architecture, automatic extraction acceptance, model qualification, second save owner or preview/pagination renderer change. + +Existing [profile tests](../../../../job-tracker-ui/src/profile-page.test.tsx), [workspace tests](../../../../job-tracker-ui/src/career-workspace-page.test.tsx), [evidence tests](../../../../job-tracker-ui/src/career-evidence.test.tsx), current normalizer/API contracts and ordinary preservation fixtures provide the baseline. Add only meaningful owner regressions and record exact new/renamed counts. For each boundary run fresh affected unit/native and applicable backend/HTTP guards, app/browser TypeScript, lint/build, finite geometry/axe and actual inspected images, secret/whitespace/docs/57+32 checks; then normal commit/push with direct equality receipt. Do not replace a failed ordinary case with a skip/expected failure or relaxed oracle. Full applicable regression remains P7-12; unchanged renderer fidelity is rerun if output/preview is touched. + +## Preservation and remaining gates + +C01–C04/E08/E09 and relevant C07/W07 frozen/override boundaries remain qualified in the [matrix](../PRESERVATION.md). Record raw commands/results/attempts, measured source/build/export identity and every axe violation/incomplete category/context; retain full vectors in hashed immutable reports. Native emulation and finite images do not supply human screen-reader, zoom/reflow, physical touch/software-keyboard, real provider, production-font/photo or deployed-output acceptance. Density is tested only where an actual control applies. + +The source-ID prerequisite has bounded runtime/readback GO and final hygiene PASS; normal push pending. Structured-editor and import/history presentation remain **PENDING**. [Debt](../DEBT.md) retains RD21 separately, M01–M12 manual requirements, deferred M13/P5-13, optional P5-05/`followMode`, production NO-GO and Phase8 separation. Conditional development entry authorizes independent bounded work; it does not declare these gates complete. diff --git a/docs/redesign/phase-7/p7-03/evidence/entry-baseline.json b/docs/redesign/phase-7/p7-03/evidence/entry-baseline.json new file mode 100644 index 0000000..5bd3c3e --- /dev/null +++ b/docs/redesign/phase-7/p7-03/evidence/entry-baseline.json @@ -0,0 +1,109 @@ +{ + "schemaVersion": 1, + "checkpoint": "P7-03", + "status": "ACCEPTED_ENTRY_WITH_MANDATORY_DEPENDENCIES", + "newRuntimeStatus": "PENDING_NOT_EXECUTED_BY_THIS_RECORD", + "developmentEntry": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "branch": "codex/ui-redesign-phase4", + "entryPushReceipt": { + "observedUtc": "2026-10-12T05:51:04.849644+00:00", + "branch": "codex/ui-redesign-phase4", + "head": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "origin": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "liveRemote": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "main": { + "local": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "origin": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "live": "27657f31131cd95d42f0e1290853ec9c9b3959a4" + }, + "workingTreeClean": true, + "porcelain": "", + "normalPush": true, + "productionDecision": "NO-GO" + }, + "production": { + "main": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "decision": "NO-GO" + }, + "acceptedP702": { + "implementedScope": "CONDITIONAL GO", + "report": "docs/redesign/phase-7/p7-02/README.md", + "portableEvidence": "docs/redesign/phase-7/p7-02/evidence/career-results.json", + "immutableEntryManifest": { + "path": ".artifacts/phase7/p7-03/entry/career-results.json", + "sha256": "1f67cfc3b6d2f34143261bf81a466a28289f21bdbf105ac8ea0b45b4f8446951", + "bytes": 329258, + "hashPolicy": "Exact saved snapshot bytes" + }, + "freshAffectedFrontend": { + "passed": 46, + "suites": 3, + "netAddedCases": 14 + }, + "freshNative": { + "career": 14, + "ordinaryPreservation": 2, + "skipped": 0, + "flaky": 0, + "unexpected": 0, + "retries": 0 + }, + "typesLintBuild": "PASS at P7-02 recorded source/export", + "static": "PASS at P7-02 recorded observation", + "buildId": "qG82wPnFf-IsAkFvXkmn6", + "sourceSha256Lf": "190d0a24368bfc3cc76550ff0f74c272200d3a30f61218a86628449ac83735ce", + "exportFiles": 75, + "exportSha256": "50896e8ad6934b909b83cc487eaf3579516921fde54b19e50a9039db68e04869", + "sourceApplicability": { + "acceptedCommit": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "qualification": "Measured P7-02 source hashes apply at this accepted commit and the immutable sourceSnapshots, not the live workspace after legitimate P7-03 edits. All original measured hashes/source/export identities remain unchanged." + }, + "axe": { + "scans": 22, + "violationNodes": 0, + "incompleteNodes": 99, + "contexts": { + "backgroundOverlap": 74, + "invisibleBadgeShortText": 22, + "hiddenMuiSelectPortal": 3 + } + } + }, + "inheritedFullExecutions": { + "frontend": "573/89 P7-01; not rerun in P7-02", + "backend": "1033 Phase6;91 targeted guards fresh in separate P7-02 repair", + "sidecar": 49, + "renderingFidelity": "16/16 with36=36 pages and8/8 with24=24 pages from accepted Phase6; untouched" + }, + "derivedExpectationsOnly": { + "frontend": "610/89", + "backend": 1034, + "ordinaryBrowser": 214, + "qualification": "Derived expectations, not newly executed whole-suite totals; finite overlapping packs are not summed as fresh full acceptance." + }, + "preservation": { + "groups": 57, + "partial": 56, + "deferred": 1, + "routes": 32, + "qualification": "No full-group upgrade; C11 remains deferred" + }, + "mandatoryDependencies": [ + { + "name": "Optional stable source-ID preservation", + "status": "PENDING_SEPARATE_REPRODUCTION_REPAIR", + "scope": "Frontend normalizer optional job/education/certification/project IDs; meaningful normalizer/payload/native canonical/sibling proof before structured presentation; no schema change" + }, + { + "name": "Concurrency and dirty/pending-write ownership", + "status": "OPEN_RD21", + "scope": "Resolve or explicitly bound canonical profile/job stale-save and creation-intent semantics; prove dirty-locale and held-PUT/pending-write recovery before save/history owner change" + } + ], + "approvedCommitBoundaries": [ + "Separate source-ID prerequisite repair after RED proof", + "Structured editor presentation", + "Import review/history presentation" + ], + "manualQualifications": "M01–M12 remain unverified; M09/M11 contextual/reader, physical/device/zoom/provider/output and production gates carry; M13/P5-13 deferred, Phase8 separate." +} diff --git a/docs/redesign/phase-7/p7-03/evidence/source-id-results.json b/docs/redesign/phase-7/p7-03/evidence/source-id-results.json new file mode 100644 index 0000000..3a1ce26 --- /dev/null +++ b/docs/redesign/phase-7/p7-03/evidence/source-id-results.json @@ -0,0 +1,2779 @@ +{ + "schemaVersion": 1, + "checkpoint": "P7-03", + "slice": "Separate source-ID and nullable-metadata prerequisite repair", + "collectedUtc": "2026-10-12T06:16:28.371706+00:00", + "acceptance": "GO for bounded forward compatibility repair; final hygiene PASS, normal push pending", + "entryCommit": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "entrySnapshot": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/entry-career-results.json", + "sha256": "1f67cfc3b6d2f34143261bf81a466a28289f21bdbf105ac8ea0b45b4f8446951", + "bytes": 329258, + "hashPolicy": "Exact measured raw bytes" + }, + "identity": { + "source": { + "path": "job-tracker-ui/src/profileCv.ts", + "sha256": "7e0b8aa13aa6df830f7e508c338c1e2dd995574bbfbd3233602654452f75cdb9", + "bytes": 11796, + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + }, + "sourceSnapshot": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/source/job-tracker-ui/src/profileCv.ts", + "sha256": "190b3e15ab00741f1e6bea868a79c3ca221e059936406098b693d13f3ef3f1d7", + "bytes": 12131, + "hashPolicy": "Exact measured raw bytes" + }, + "tests": [ + { + "originalSourcePath": "job-tracker-ui/src/profileCv.test.ts", + "rawSnapshot": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/tests/job-tracker-ui/src/profileCv.test.ts", + "sha256": "a85cbebacb01d11bb92898d2a9809744fd65c9b8f9a525d7f2050c86815c5e97", + "bytes": 4317, + "hashPolicy": "Exact measured raw bytes" + }, + "canonicalLf": { + "path": "job-tracker-ui/src/profileCv.test.ts", + "sha256": "a85cbebacb01d11bb92898d2a9809744fd65c9b8f9a525d7f2050c86815c5e97", + "bytes": 4317, + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + } + }, + { + "originalSourcePath": "job-tracker-ui/src/profile-page.test.tsx", + "rawSnapshot": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/tests/job-tracker-ui/src/profile-page.test.tsx", + "sha256": "84c9f2683e445f8a56de53ec84e2b291792985ea829dcef688aaafa34ddd32a6", + "bytes": 30581, + "hashPolicy": "Exact measured raw bytes" + }, + "canonicalLf": { + "path": "job-tracker-ui/src/profile-page.test.tsx", + "sha256": "ac1421ecf0fb4723fa974e4e1f0899d0eb0aa53d3225eb428b11c086d6f22950", + "bytes": 30021, + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + } + }, + { + "originalSourcePath": "job-tracker-ui/e2e/phase7-career-source-ids.spec.ts", + "rawSnapshot": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/tests/job-tracker-ui/e2e/phase7-career-source-ids.spec.ts", + "sha256": "92bc8f1b4c82210207071c56940813dfece3136832ba09ebd1e6c3471d8d7945", + "bytes": 20601, + "hashPolicy": "Exact measured raw bytes" + }, + "canonicalLf": { + "path": "job-tracker-ui/e2e/phase7-career-source-ids.spec.ts", + "sha256": "92bc8f1b4c82210207071c56940813dfece3136832ba09ebd1e6c3471d8d7945", + "bytes": 20601, + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + } + } + ], + "sourceApplicability": "Measured repaired source/test identities apply to frozen snapshots and eventual repair commit; retain historical hashes after legitimate structured-editor changes.", + "buildId": "bzQiDlr6LeM9Gsel4WRS8", + "buildIdRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/BUILD_ID", + "sha256": "49f2090d798c337c72c6937cf6cb5e0c5da5ff528f90b45ee65253b1312af136", + "bytes": 21, + "hashPolicy": "Exact measured raw bytes" + }, + "exportFiles": 75, + "exportSha256": "812182947b7af96a00f9568a83de1098f2824c53550c7119c76ec41803e71fbf", + "exportHashPolicy": "Sorted original export path TAB exact raw SHA LF records", + "runner": [ + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runner/run-ui.py", + "sha256": "0d556c6cb61be6deb930603de9b58df5e14e4763a6f9e31652258e955f7c5f0d", + "bytes": 4582, + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runner/e2e-tsconfig.json", + "sha256": "55fa6fffaed1e76a32657edfffcc501cd8bd87330bda2c3a3944f8f89d4019e2", + "bytes": 572, + "hashPolicy": "Exact measured raw bytes" + } + ], + "apiBinary": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/api/JobTrackerApi.dll", + "sha256": "d2da64748364880d471d2087d5aa101ce749b26966beed13d9e9dbaa3b92512b", + "bytes": 4026368, + "hashPolicy": "Exact measured raw bytes" + }, + "apiQualification": "Raw API binary equal separately frozen P702 repair DLL; no new backend build/tests. P70291 affected guards remain inherited targeted evidence." + }, + "commands": { + "typecheck": { + "record": { + "name": "typecheck", + "command": [ + "rtk", + "proxy", + "npm.cmd", + "run", + "typecheck" + ], + "startedUtc": "2026-10-12T06:11:46.847379+00:00", + "finishedUtc": "2026-10-12T06:11:56.309351+00:00", + "exitCode": 0 + }, + "recordRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/typecheck-command.json", + "sha256": "8234803d8aefa430c8733cbd916b2ff3523c6a5bbf443bf8c2cbc384090b485e", + "bytes": 247, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/typecheck.log", + "sha256": "89b0ec97b537eca6560c13ca2dfea9e3a97dd1bb35580c4ff39d2462db25e080", + "bytes": 148, + "hashPolicy": "Exact measured raw bytes" + } + }, + "browser-typecheck": { + "record": { + "name": "browser-typecheck", + "command": [ + "rtk", + "proxy", + "npm.cmd", + "exec", + "tsc", + "--", + "--project", + "../.artifacts/phase7/e2e-tsconfig.json", + "--noEmit" + ], + "startedUtc": "2026-10-12T06:11:56.311363+00:00", + "finishedUtc": "2026-10-12T06:11:59.923491+00:00", + "exitCode": 0 + }, + "recordRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/browser-typecheck-command.json", + "sha256": "fc559a667c0d9dcd78fa6342a8ab408317688258288b5b9bdcbc0840567edac4", + "bytes": 343, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/browser-typecheck.log", + "sha256": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6", + "bytes": 78, + "hashPolicy": "Exact measured raw bytes" + } + }, + "lint": { + "record": { + "name": "lint", + "command": [ + "rtk", + "proxy", + "npm.cmd", + "run", + "lint" + ], + "startedUtc": "2026-10-12T06:11:59.926038+00:00", + "finishedUtc": "2026-10-12T06:12:17.583807+00:00", + "exitCode": 0 + }, + "recordRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/lint-command.json", + "sha256": "6aad66214ad3235829030b6cb5df758a4bda63d67d07a9d416e684006362ed94", + "bytes": 237, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/lint.log", + "sha256": "b040dbeca9b4adb3f6f4c25ac49de0d37e921375b2d9b57e87b542a10f599913", + "bytes": 136, + "hashPolicy": "Exact measured raw bytes" + } + }, + "build": { + "record": { + "name": "build", + "command": [ + "rtk", + "proxy", + "npm.cmd", + "run", + "build" + ], + "startedUtc": "2026-10-12T06:12:17.585807+00:00", + "finishedUtc": "2026-10-12T06:12:25.292019+00:00", + "exitCode": 0 + }, + "recordRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/build-command.json", + "sha256": "e4fca0a8aded5ada0bcedacceca3651dd4857a74407bba3b9b71d57bb104cb73", + "bytes": 239, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/build.log", + "sha256": "1b2c5385cfb901084e87ce46a699b8a71ba6204cdfde56d890305489f0c73ce0", + "bytes": 670, + "hashPolicy": "Exact measured raw bytes" + } + }, + "career-source-ids": { + "record": { + "name": "career-source-ids", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/phase7-career-source-ids.spec.ts", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-source-ids-results" + ], + "startedUtc": "2026-10-12T06:12:25.298085+00:00", + "finishedUtc": "2026-10-12T06:12:37.583780+00:00", + "exitCode": 0, + "stats": { + "startTime": "2026-10-12T06:12:25.809Z", + "duration": 11739.815, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "recordRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids-command.json", + "sha256": "780b56d52886a326ff31f04c5f400b2629627e0f03efa391c735ec965b3a87e7", + "bytes": 665, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.log", + "sha256": "7f1cd8aebbb41c1ce75b680fa5a77175094e2783c2cdb702a2659b999b093f6a", + "bytes": 927, + "hashPolicy": "Exact measured raw bytes" + } + }, + "career-preservation": { + "record": { + "name": "career-preservation", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/redesign-preservation.spec.ts", + "--grep", + "mobile CV override|legacy workspace preserves frozen", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-preservation-results" + ], + "startedUtc": "2026-10-12T06:12:37.590840+00:00", + "finishedUtc": "2026-10-12T06:12:52.605547+00:00", + "exitCode": 0, + "stats": { + "startTime": "2026-10-12T06:12:38.101Z", + "duration": 14471.283000000001, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "recordRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation-command.json", + "sha256": "98cf49f4855f153f785908ce33c8f2a64bdda314c37f5ed9b53660595726b910", + "bytes": 751, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.log", + "sha256": "06ae9d36d33e1971bcb628d99d25109b7adf06fb1ad7acf8b9f73b2995be951c", + "bytes": 866, + "hashPolicy": "Exact measured raw bytes" + } + } + }, + "environment": { + "browser": "Native Windows Chromium/local SQLite; original runner/config frozen", + "NEXT_PUBLIC_API_BASE_URL": "http://localhost:5302/api", + "PLAYWRIGHT_STATIC_EXPORT": "true", + "PREBUILT_EXPORT": "true", + "REUSE_SERVERS": "false", + "Workers__SavedJobSearchAlertsEnabled": "false", + "qualification": "Applied runner environment; not deployed/provider/device evidence" + }, + "affectedFrontend": { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z.json", + "sha256": "bccd0cd98270c61f52f1d34967fcf08d346912bdf077dde6568666bce17ce466", + "bytes": 18991, + "hashPolicy": "Exact measured raw bytes" + }, + "startedUnixMs": 1791785428247, + "passed": 46, + "failed": 0, + "pending": 0, + "total": 46, + "suites": 3, + "cases": [ + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function CareerProfilePage]", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function ProfilePage]", + "status": "passed" + }, + { + "name": "Career Profile section headings describe the visible hierarchy without changing editing fields", + "status": "passed" + }, + { + "name": "account headings separate identity from security sections", + "status": "passed" + }, + { + "name": "account CV text status in en does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "account CV text status in nb does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "[PRES-E02/E09/C01] account save carries four identity fields and keeps career, email and CV writes separate", + "status": "passed" + }, + { + "name": "[PRES-E02/E08/E09] failed account save keeps a scoped error and the identity draft for explicit retry", + "status": "passed" + }, + { + "name": "[PRES-E02/E08] failed password update keeps a scoped error and secret draft until explicit retry succeeds", + "status": "passed" + }, + { + "name": "profile page loads persisted structured cv and can re-parse it", + "status": "passed" + }, + { + "name": "saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)", + "status": "passed" + }, + { + "name": "editing a field in an extracted section updates parent state and flows into save (Phase 1 increment 2)", + "status": "passed" + }, + { + "name": "profile page can reprocess from stored artifact history", + "status": "passed" + }, + { + "name": "active extraction polling refreshes run status without resetting unsaved career fields", + "status": "passed" + }, + { + "name": "profile page shows durable CV operation state and retries a failed run", + "status": "passed" + }, + { + "name": "profile page keeps raw extraction collapsed until expanded", + "status": "passed" + }, + { + "name": "saving the master profile (career) persists the structured profile via /career/profile", + "status": "passed" + }, + { + "name": "/career shows the profile completeness overview", + "status": "passed" + }, + { + "name": "/career profile exposes extraction progress", + "status": "passed" + }, + { + "name": "/career profile can queue a CV upload without visiting import review first", + "status": "passed" + }, + { + "name": "/career localizes completeness and review confidence without changing CV data", + "status": "passed" + }, + { + "name": "/career separates overview, profile and import while preserving unsaved profile edits", + "status": "passed" + }, + { + "name": "pending CV extraction can be reviewed and applied", + "status": "passed" + }, + { + "name": "account email changes require a password and use the confirmation flow", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing jobs", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing education", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing certifications", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing projects", + "status": "passed" + }, + { + "name": "legacy structured items without IDs remain usable and acquire no client-generated IDs", + "status": "passed" + }, + { + "name": "legacy parsed sections keep their facts without inventing structured item IDs", + "status": "passed" + }, + { + "name": "API null and missing numeric metadata remain absent rather than becoming zero", + "status": "passed" + }, + { + "name": "zero, finite numbers and numeric strings keep the established metadata number conversion", + "status": "passed" + }, + { + "name": "first-run workspace presents concise profile, import, general CV and job-specific actions", + "status": "passed" + }, + { + "name": "career workspace overview and import state render in Bokmål", + "status": "passed" + }, + { + "name": "returning workspace shows missing profile information and recent general and job-specific CVs", + "status": "passed" + }, + { + "name": "workspace exposes the pending_review import state as a resumable action", + "status": "passed" + }, + { + "name": "workspace exposes the queued import state as a resumable action", + "status": "passed" + }, + { + "name": "workspace exposes the failed import state as a resumable action", + "status": "passed" + }, + { + "name": "workspace represents loading and profile-load errors without inventing status", + "status": "passed" + }, + { + "name": "a settled failed profile read hides the completeness score and retries only through its existing owner", + "status": "passed" + }, + { + "name": "an unknown import read cannot claim no imports, completion or first-run guidance", + "status": "passed" + }, + { + "name": "a failed import read stays unknown and keeps its own retry separate from the profile read", + "status": "passed" + }, + { + "name": "failed recent-CV reads do not imply first-run and retry the same list without writes", + "status": "passed" + }, + { + "name": "the parent exposes failed import-read retry without canonical saves or history restores", + "status": "passed" + }, + { + "name": "overview retry cannot overwrite a dirty canonical draft after a failed source refresh", + "status": "passed" + }, + { + "name": "visited evidence keeps its draft across sections without an unvisited or repeated list request", + "status": "passed" + } + ] + }, + "affectedCommand": { + "record": { + "command": [ + "rtk", + "proxy", + "npm.cmd", + "test", + "--", + "--runInBand", + "--watchAll=false", + "--json", + "--outputFile=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\unit\\career-id-metadata-green-20261012T061027Z.json", + "src/profileCv.test.ts", + "src/profile-page.test.tsx", + "src/career-workspace-page.test.tsx" + ], + "startedUtc": "2026-10-12T06:10:27.310871+00:00", + "finishedUtc": "2026-10-12T06:10:43.298188+00:00", + "exitCode": 0, + "counts": { + "numPassedTests": 46, + "numFailedTests": 0, + "numPendingTests": 0, + "numTodoTests": 0, + "numPassedTestSuites": 3, + "numFailedTestSuites": 0 + } + }, + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z-command.json", + "sha256": "84de6f47db72a7f9226d97ff711acce3561b91d571d9804f0a799cd8f8991c38", + "bytes": 717, + "hashPolicy": "Exact measured raw bytes" + }, + "log": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z.log", + "sha256": "500c3ad8ff26830b813c227cb8f7a21592291285587f653545ac98175258d1a0", + "bytes": 707, + "hashPolicy": "Exact measured raw bytes" + } + }, + "caseDeltas": { + "newNormalizerCases": 8, + "newSuites": 1, + "existingProfile": 24, + "existingWorkspace": 14, + "totalAffected": 46, + "qualification": "Existing canonical payload assertion strengthened without adding case; unrelated early parser cases excluded before bounded RED, original histories retained." + }, + "native": { + "career-source-ids": { + "command": { + "name": "career-source-ids", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/phase7-career-source-ids.spec.ts", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-source-ids-results" + ], + "startedUtc": "2026-10-12T06:12:25.298085+00:00", + "finishedUtc": "2026-10-12T06:12:37.583780+00:00", + "exitCode": 0, + "stats": { + "startTime": "2026-10-12T06:12:25.809Z", + "duration": 11739.815, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "commandRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids-command.json", + "sha256": "780b56d52886a326ff31f04c5f400b2629627e0f03efa391c735ec965b3a87e7", + "bytes": 665, + "hashPolicy": "Exact measured raw bytes" + }, + "reportRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "bytes": 389389, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.log", + "sha256": "7f1cd8aebbb41c1ce75b680fa5a77175094e2783c2cdb702a2659b999b093f6a", + "bytes": 927, + "hashPolicy": "Exact measured raw bytes" + }, + "stats": { + "startTime": "2026-10-12T06:12:25.809Z", + "duration": 11739.815, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "[P7-03 PRES-C01 C03 C06 C07 C10 W05 W06] unrelated canonical UI save preserves four source IDs, existing CV overrides, sibling and frozen package", + "file": "phase7-career-source-ids.spec.ts", + "line": 69, + "expectedStatus": "passed", + "project": "chromium", + "resultStatuses": [ + "passed" + ], + "retries": [ + 0 + ], + "errors": [ + [] + ], + "durationMs": 3978 + }, + { + "title": "[P7-03 PRES-C01 C03 E05 E09] real HTTP bounds canonical last-writer saves and structured-history recovery without claiming stale-write protection", + "file": "phase7-career-source-ids.spec.ts", + "line": 185, + "expectedStatus": "passed", + "project": "chromium", + "resultStatuses": [ + "passed" + ], + "retries": [ + 0 + ], + "errors": [ + [] + ], + "durationMs": 877 + } + ], + "attachments": [ + { + "test": "[P7-03 PRES-C01 C03 C06 C07 C10 W05 W06] unrelated canonical UI save preserves four source IDs, existing CV overrides, sibling and frozen package", + "name": "native-career-source-id-readbacks", + "contentType": "application/json", + "raw": { + "storage": "Base64 attachment in raw report", + "sha256": "463027b1e9b25842e69541aaadd3e6a4830d2ec2c743ebc2811c0b32a21c5b1f", + "bytes": 89557 + }, + "manualReview": "No individual inspection claimed by collector" + }, + { + "test": "[P7-03 PRES-C01 C03 C06 C07 C10 W05 W06] unrelated canonical UI save preserves four source IDs, existing CV overrides, sibling and frozen package", + "name": "native-career-source-id-editor", + "contentType": "image/png", + "raw": { + "storage": "Base64 attachment in raw report", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "bytes": 189632, + "extractedPNG": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/effe56f6ea9a/native-career-source-id-editor.png", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "bytes": 189632, + "hashPolicy": "Exact measured raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "bytes": 389389, + "hashPolicy": "Exact measured raw bytes" + } + }, + "manualReview": "No individual inspection claimed by collector" + }, + { + "test": "[P7-03 PRES-C01 C03 E05 E09] real HTTP bounds canonical last-writer saves and structured-history recovery without claiming stale-write protection", + "name": "native-canonical-stale-contract-characterization", + "contentType": "application/json", + "raw": { + "storage": "Base64 attachment in raw report", + "sha256": "36aa851d09b68c8b6705e707a8385d1dd3d3141faf34e4293938b2fb344e76f7", + "bytes": 8996 + }, + "manualReview": "No individual inspection claimed by collector" + } + ], + "reportErrors": [], + "configuration": { + "version": "1.62.1", + "workers": 1, + "projects": [ + { + "name": "chromium", + "retries": 0 + } + ] + }, + "accessibility": { + "scans": 0, + "ruleNodeCounts": [], + "contexts": [], + "qualification": "No axe attachments means no new axe coverage; retained P70299 incomplete contexts/manual gates remain. Full vectors stay in raw report where present." + } + }, + "career-preservation": { + "command": { + "name": "career-preservation", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/redesign-preservation.spec.ts", + "--grep", + "mobile CV override|legacy workspace preserves frozen", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-preservation-results" + ], + "startedUtc": "2026-10-12T06:12:37.590840+00:00", + "finishedUtc": "2026-10-12T06:12:52.605547+00:00", + "exitCode": 0, + "stats": { + "startTime": "2026-10-12T06:12:38.101Z", + "duration": 14471.283000000001, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "commandRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation-command.json", + "sha256": "98cf49f4855f153f785908ce33c8f2a64bdda314c37f5ed9b53660595726b910", + "bytes": 751, + "hashPolicy": "Exact measured raw bytes" + }, + "reportRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.json", + "sha256": "b155c1c4645f9085b71723305bfc0fd831287e150665f1f4de563771fd1565d2", + "bytes": 130872, + "hashPolicy": "Exact measured raw bytes" + }, + "logRaw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.log", + "sha256": "06ae9d36d33e1971bcb628d99d25109b7adf06fb1ad7acf8b9f73b2995be951c", + "bytes": 866, + "hashPolicy": "Exact measured raw bytes" + }, + "stats": { + "startTime": "2026-10-12T06:12:38.101Z", + "duration": 14471.283000000001, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "[PRES-C01 PRES-C06 PRES-C07 PRES-C10] mobile CV override persists without changing the canonical profile or sibling CV", + "file": "redesign-preservation.spec.ts", + "line": 43, + "expectedStatus": "passed", + "project": "chromium", + "resultStatuses": [ + "passed" + ], + "retries": [ + 0 + ], + "errors": [ + [] + ], + "durationMs": 3719 + }, + { + "title": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change", + "file": "redesign-preservation.spec.ts", + "line": 73, + "expectedStatus": "passed", + "project": "chromium", + "resultStatuses": [ + "passed" + ], + "retries": [ + 0 + ], + "errors": [ + [] + ], + "durationMs": 3721 + } + ], + "attachments": [ + { + "test": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change", + "name": "native-frozen-package", + "contentType": "image/png", + "raw": { + "storage": "Base64 attachment in raw report", + "sha256": "1fcd650af0f5e913abd2635aafeb8c41042cfd5c42936de8928a44c5f47b27ea", + "bytes": 94122, + "extractedPNG": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/b155c1c4645f/native-frozen-package.png", + "sha256": "1fcd650af0f5e913abd2635aafeb8c41042cfd5c42936de8928a44c5f47b27ea", + "bytes": 94122, + "hashPolicy": "Exact measured raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.json", + "sha256": "b155c1c4645f9085b71723305bfc0fd831287e150665f1f4de563771fd1565d2", + "bytes": 130872, + "hashPolicy": "Exact measured raw bytes" + } + }, + "manualReview": "No individual inspection claimed by collector" + }, + { + "test": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change", + "name": "native-preservation-invariants", + "contentType": "application/json", + "raw": { + "storage": "Base64 attachment in raw report", + "sha256": "3686ad95bbc0b6b9a554d67bc94e34b44c164f2f839567a19a3b2000f980b5f6", + "bytes": 348 + }, + "manualReview": "No individual inspection claimed by collector" + } + ], + "reportErrors": [], + "configuration": { + "version": "1.62.1", + "workers": 1, + "projects": [ + { + "name": "chromium", + "retries": 0 + } + ] + }, + "accessibility": { + "scans": 0, + "ruleNodeCounts": [], + "contexts": [], + "qualification": "No axe attachments means no new axe coverage; retained P70299 incomplete contexts/manual gates remain. Full vectors stay in raw report where present." + } + } + }, + "unitHistory": [ + { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z.json", + "sha256": "bccd0cd98270c61f52f1d34967fcf08d346912bdf077dde6568666bce17ce466", + "bytes": 18991, + "hashPolicy": "Exact measured raw bytes" + }, + "startedUnixMs": 1791785428247, + "passed": 46, + "failed": 0, + "pending": 0, + "total": 46, + "suites": 3, + "cases": [ + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function CareerProfilePage]", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function ProfilePage]", + "status": "passed" + }, + { + "name": "Career Profile section headings describe the visible hierarchy without changing editing fields", + "status": "passed" + }, + { + "name": "account headings separate identity from security sections", + "status": "passed" + }, + { + "name": "account CV text status in en does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "account CV text status in nb does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "[PRES-E02/E09/C01] account save carries four identity fields and keeps career, email and CV writes separate", + "status": "passed" + }, + { + "name": "[PRES-E02/E08/E09] failed account save keeps a scoped error and the identity draft for explicit retry", + "status": "passed" + }, + { + "name": "[PRES-E02/E08] failed password update keeps a scoped error and secret draft until explicit retry succeeds", + "status": "passed" + }, + { + "name": "profile page loads persisted structured cv and can re-parse it", + "status": "passed" + }, + { + "name": "saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)", + "status": "passed" + }, + { + "name": "editing a field in an extracted section updates parent state and flows into save (Phase 1 increment 2)", + "status": "passed" + }, + { + "name": "profile page can reprocess from stored artifact history", + "status": "passed" + }, + { + "name": "active extraction polling refreshes run status without resetting unsaved career fields", + "status": "passed" + }, + { + "name": "profile page shows durable CV operation state and retries a failed run", + "status": "passed" + }, + { + "name": "profile page keeps raw extraction collapsed until expanded", + "status": "passed" + }, + { + "name": "saving the master profile (career) persists the structured profile via /career/profile", + "status": "passed" + }, + { + "name": "/career shows the profile completeness overview", + "status": "passed" + }, + { + "name": "/career profile exposes extraction progress", + "status": "passed" + }, + { + "name": "/career profile can queue a CV upload without visiting import review first", + "status": "passed" + }, + { + "name": "/career localizes completeness and review confidence without changing CV data", + "status": "passed" + }, + { + "name": "/career separates overview, profile and import while preserving unsaved profile edits", + "status": "passed" + }, + { + "name": "pending CV extraction can be reviewed and applied", + "status": "passed" + }, + { + "name": "account email changes require a password and use the confirmation flow", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing jobs", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing education", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing certifications", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing projects", + "status": "passed" + }, + { + "name": "legacy structured items without IDs remain usable and acquire no client-generated IDs", + "status": "passed" + }, + { + "name": "legacy parsed sections keep their facts without inventing structured item IDs", + "status": "passed" + }, + { + "name": "API null and missing numeric metadata remain absent rather than becoming zero", + "status": "passed" + }, + { + "name": "zero, finite numbers and numeric strings keep the established metadata number conversion", + "status": "passed" + }, + { + "name": "first-run workspace presents concise profile, import, general CV and job-specific actions", + "status": "passed" + }, + { + "name": "career workspace overview and import state render in Bokmål", + "status": "passed" + }, + { + "name": "returning workspace shows missing profile information and recent general and job-specific CVs", + "status": "passed" + }, + { + "name": "workspace exposes the pending_review import state as a resumable action", + "status": "passed" + }, + { + "name": "workspace exposes the queued import state as a resumable action", + "status": "passed" + }, + { + "name": "workspace exposes the failed import state as a resumable action", + "status": "passed" + }, + { + "name": "workspace represents loading and profile-load errors without inventing status", + "status": "passed" + }, + { + "name": "a settled failed profile read hides the completeness score and retries only through its existing owner", + "status": "passed" + }, + { + "name": "an unknown import read cannot claim no imports, completion or first-run guidance", + "status": "passed" + }, + { + "name": "a failed import read stays unknown and keeps its own retry separate from the profile read", + "status": "passed" + }, + { + "name": "failed recent-CV reads do not imply first-run and retry the same list without writes", + "status": "passed" + }, + { + "name": "the parent exposes failed import-read retry without canonical saves or history restores", + "status": "passed" + }, + { + "name": "overview retry cannot overwrite a dirty canonical draft after a failed source refresh", + "status": "passed" + }, + { + "name": "visited evidence keeps its draft across sections without an unvisited or repeated list request", + "status": "passed" + } + ] + }, + { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-red-20261012T060859Z.json", + "sha256": "9a6911e75c8ef9877d4edcf9a8601534a94cff658a2867a5bf9b47b5baa5af66", + "bytes": 60108, + "hashPolicy": "Exact measured raw bytes" + }, + "startedUnixMs": 1791785340795, + "passed": 26, + "failed": 6, + "pending": 0, + "total": 32, + "suites": 2, + "cases": [ + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function CareerProfilePage]", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function ProfilePage]", + "status": "passed" + }, + { + "name": "Career Profile section headings describe the visible hierarchy without changing editing fields", + "status": "passed" + }, + { + "name": "account headings separate identity from security sections", + "status": "passed" + }, + { + "name": "account CV text status in en does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "account CV text status in nb does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "[PRES-E02/E09/C01] account save carries four identity fields and keeps career, email and CV writes separate", + "status": "passed" + }, + { + "name": "[PRES-E02/E08/E09] failed account save keeps a scoped error and the identity draft for explicit retry", + "status": "passed" + }, + { + "name": "[PRES-E02/E08] failed password update keeps a scoped error and secret draft until explicit retry succeeds", + "status": "passed" + }, + { + "name": "profile page loads persisted structured cv and can re-parse it", + "status": "passed" + }, + { + "name": "saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)", + "status": "failed" + }, + { + "name": "editing a field in an extracted section updates parent state and flows into save (Phase 1 increment 2)", + "status": "passed" + }, + { + "name": "profile page can reprocess from stored artifact history", + "status": "passed" + }, + { + "name": "active extraction polling refreshes run status without resetting unsaved career fields", + "status": "passed" + }, + { + "name": "profile page shows durable CV operation state and retries a failed run", + "status": "passed" + }, + { + "name": "profile page keeps raw extraction collapsed until expanded", + "status": "passed" + }, + { + "name": "saving the master profile (career) persists the structured profile via /career/profile", + "status": "passed" + }, + { + "name": "/career shows the profile completeness overview", + "status": "passed" + }, + { + "name": "/career profile exposes extraction progress", + "status": "passed" + }, + { + "name": "/career profile can queue a CV upload without visiting import review first", + "status": "passed" + }, + { + "name": "/career localizes completeness and review confidence without changing CV data", + "status": "passed" + }, + { + "name": "/career separates overview, profile and import while preserving unsaved profile edits", + "status": "passed" + }, + { + "name": "pending CV extraction can be reviewed and applied", + "status": "passed" + }, + { + "name": "account email changes require a password and use the confirmation flow", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing jobs", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing education", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing certifications", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing projects", + "status": "failed" + }, + { + "name": "legacy structured items without IDs remain usable and acquire no client-generated IDs", + "status": "passed" + }, + { + "name": "legacy parsed sections keep their facts without inventing structured item IDs", + "status": "passed" + }, + { + "name": "API null and missing numeric metadata remain absent rather than becoming zero", + "status": "failed" + }, + { + "name": "zero, finite numbers and numeric strings keep the established metadata number conversion", + "status": "passed" + } + ] + }, + { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-red-20261012T055246Z.json", + "sha256": "0b3b3f9749e06e794ca802a3c3091a5ce82615c0e83d1fbc28a2124c2f141d1b", + "bytes": 59484, + "hashPolicy": "Exact measured raw bytes" + }, + "startedUnixMs": 1791784369324, + "passed": 28, + "failed": 6, + "pending": 0, + "total": 34, + "suites": 2, + "cases": [ + { + "name": "preserves the server item ID when normalizing jobs", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing education", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing certifications", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing projects", + "status": "failed" + }, + { + "name": "legacy structured items without IDs remain usable and acquire no client-generated IDs", + "status": "passed" + }, + { + "name": "legacy parsed sections keep their facts without inventing structured item IDs", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON undefined retains the empty profile contract", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON \"\" retains the empty profile contract", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON \"not valid JSON\" retains the empty profile contract", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON \"null\" retains the empty profile contract", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function CareerProfilePage]", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function ProfilePage]", + "status": "passed" + }, + { + "name": "Career Profile section headings describe the visible hierarchy without changing editing fields", + "status": "passed" + }, + { + "name": "account headings separate identity from security sections", + "status": "passed" + }, + { + "name": "account CV text status in en does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "account CV text status in nb does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "[PRES-E02/E09/C01] account save carries four identity fields and keeps career, email and CV writes separate", + "status": "passed" + }, + { + "name": "[PRES-E02/E08/E09] failed account save keeps a scoped error and the identity draft for explicit retry", + "status": "passed" + }, + { + "name": "[PRES-E02/E08] failed password update keeps a scoped error and secret draft until explicit retry succeeds", + "status": "passed" + }, + { + "name": "profile page loads persisted structured cv and can re-parse it", + "status": "passed" + }, + { + "name": "saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)", + "status": "failed" + }, + { + "name": "editing a field in an extracted section updates parent state and flows into save (Phase 1 increment 2)", + "status": "failed" + }, + { + "name": "profile page can reprocess from stored artifact history", + "status": "passed" + }, + { + "name": "active extraction polling refreshes run status without resetting unsaved career fields", + "status": "passed" + }, + { + "name": "profile page shows durable CV operation state and retries a failed run", + "status": "passed" + }, + { + "name": "profile page keeps raw extraction collapsed until expanded", + "status": "passed" + }, + { + "name": "saving the master profile (career) persists the structured profile via /career/profile", + "status": "passed" + }, + { + "name": "/career shows the profile completeness overview", + "status": "passed" + }, + { + "name": "/career profile exposes extraction progress", + "status": "passed" + }, + { + "name": "/career profile can queue a CV upload without visiting import review first", + "status": "passed" + }, + { + "name": "/career localizes completeness and review confidence without changing CV data", + "status": "passed" + }, + { + "name": "/career separates overview, profile and import while preserving unsaved profile edits", + "status": "passed" + }, + { + "name": "pending CV extraction can be reviewed and applied", + "status": "passed" + }, + { + "name": "account email changes require a password and use the confirmation flow", + "status": "passed" + } + ] + }, + { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-red-bounded-20261012T055452Z.json", + "sha256": "51606eaed128afce6c5fe21381bbf5e70952d1d4e243c868b35750ab28474b89", + "bytes": 56657, + "hashPolicy": "Exact measured raw bytes" + }, + "startedUnixMs": 1791784493571, + "passed": 25, + "failed": 5, + "pending": 0, + "total": 30, + "suites": 2, + "cases": [ + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function CareerProfilePage]", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function ProfilePage]", + "status": "passed" + }, + { + "name": "Career Profile section headings describe the visible hierarchy without changing editing fields", + "status": "passed" + }, + { + "name": "account headings separate identity from security sections", + "status": "passed" + }, + { + "name": "account CV text status in en does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "account CV text status in nb does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "[PRES-E02/E09/C01] account save carries four identity fields and keeps career, email and CV writes separate", + "status": "passed" + }, + { + "name": "[PRES-E02/E08/E09] failed account save keeps a scoped error and the identity draft for explicit retry", + "status": "passed" + }, + { + "name": "[PRES-E02/E08] failed password update keeps a scoped error and secret draft until explicit retry succeeds", + "status": "passed" + }, + { + "name": "profile page loads persisted structured cv and can re-parse it", + "status": "passed" + }, + { + "name": "saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)", + "status": "failed" + }, + { + "name": "editing a field in an extracted section updates parent state and flows into save (Phase 1 increment 2)", + "status": "passed" + }, + { + "name": "profile page can reprocess from stored artifact history", + "status": "passed" + }, + { + "name": "active extraction polling refreshes run status without resetting unsaved career fields", + "status": "passed" + }, + { + "name": "profile page shows durable CV operation state and retries a failed run", + "status": "passed" + }, + { + "name": "profile page keeps raw extraction collapsed until expanded", + "status": "passed" + }, + { + "name": "saving the master profile (career) persists the structured profile via /career/profile", + "status": "passed" + }, + { + "name": "/career shows the profile completeness overview", + "status": "passed" + }, + { + "name": "/career profile exposes extraction progress", + "status": "passed" + }, + { + "name": "/career profile can queue a CV upload without visiting import review first", + "status": "passed" + }, + { + "name": "/career localizes completeness and review confidence without changing CV data", + "status": "passed" + }, + { + "name": "/career separates overview, profile and import while preserving unsaved profile edits", + "status": "passed" + }, + { + "name": "pending CV extraction can be reviewed and applied", + "status": "passed" + }, + { + "name": "account email changes require a password and use the confirmation flow", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing jobs", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing education", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing certifications", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing projects", + "status": "failed" + }, + { + "name": "legacy structured items without IDs remain usable and acquire no client-generated IDs", + "status": "passed" + }, + { + "name": "legacy parsed sections keep their facts without inventing structured item IDs", + "status": "passed" + } + ] + }, + { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-red-repeat-20261012T055358Z.json", + "sha256": "da9204062cf64248e8d0b182bf3322fc2697eb2d576aece0b4719a6ffe345205", + "bytes": 59484, + "hashPolicy": "Exact measured raw bytes" + }, + "startedUnixMs": 1791784439650, + "passed": 28, + "failed": 6, + "pending": 0, + "total": 34, + "suites": 2, + "cases": [ + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function CareerProfilePage]", + "status": "passed" + }, + { + "name": "meaningful identity initials use a readable foreground/background pair in [Function ProfilePage]", + "status": "passed" + }, + { + "name": "Career Profile section headings describe the visible hierarchy without changing editing fields", + "status": "passed" + }, + { + "name": "account headings separate identity from security sections", + "status": "passed" + }, + { + "name": "account CV text status in en does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "account CV text status in nb does not claim the CV library is empty", + "status": "passed" + }, + { + "name": "[PRES-E02/E09/C01] account save carries four identity fields and keeps career, email and CV writes separate", + "status": "passed" + }, + { + "name": "[PRES-E02/E08/E09] failed account save keeps a scoped error and the identity draft for explicit retry", + "status": "passed" + }, + { + "name": "[PRES-E02/E08] failed password update keeps a scoped error and secret draft until explicit retry succeeds", + "status": "passed" + }, + { + "name": "profile page loads persisted structured cv and can re-parse it", + "status": "passed" + }, + { + "name": "saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)", + "status": "failed" + }, + { + "name": "editing a field in an extracted section updates parent state and flows into save (Phase 1 increment 2)", + "status": "failed" + }, + { + "name": "profile page can reprocess from stored artifact history", + "status": "passed" + }, + { + "name": "active extraction polling refreshes run status without resetting unsaved career fields", + "status": "passed" + }, + { + "name": "profile page shows durable CV operation state and retries a failed run", + "status": "passed" + }, + { + "name": "profile page keeps raw extraction collapsed until expanded", + "status": "passed" + }, + { + "name": "saving the master profile (career) persists the structured profile via /career/profile", + "status": "passed" + }, + { + "name": "/career shows the profile completeness overview", + "status": "passed" + }, + { + "name": "/career profile exposes extraction progress", + "status": "passed" + }, + { + "name": "/career profile can queue a CV upload without visiting import review first", + "status": "passed" + }, + { + "name": "/career localizes completeness and review confidence without changing CV data", + "status": "passed" + }, + { + "name": "/career separates overview, profile and import while preserving unsaved profile edits", + "status": "passed" + }, + { + "name": "pending CV extraction can be reviewed and applied", + "status": "passed" + }, + { + "name": "account email changes require a password and use the confirmation flow", + "status": "passed" + }, + { + "name": "preserves the server item ID when normalizing jobs", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing education", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing certifications", + "status": "failed" + }, + { + "name": "preserves the server item ID when normalizing projects", + "status": "failed" + }, + { + "name": "legacy structured items without IDs remain usable and acquire no client-generated IDs", + "status": "passed" + }, + { + "name": "legacy parsed sections keep their facts without inventing structured item IDs", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON undefined retains the empty profile contract", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON \"\" retains the empty profile contract", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON \"not valid JSON\" retains the empty profile contract", + "status": "passed" + }, + { + "name": "empty or invalid legacy JSON \"null\" retains the empty profile contract", + "status": "passed" + } + ] + } + ], + "baselineHistory": [ + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/identity.json", + "evidence": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/identity.json", + "sha256": "0cdf3e1ab08453e53c702b5e8cda93dd968dd04a303efa129f4831d4f01ba393", + "bytes": 3043, + "hashPolicy": "Exact measured raw bytes" + }, + "record": { + "schemaVersion": 1, + "checkpoint": "P7-03", + "scope": "Source-ID prerequisite repair baseline", + "frozenUtc": "2026-10-12T06:06:36.221265+00:00", + "acceptedCommit": "8b4d5c21125e800199d3ecc2d9c059a80ac5125d", + "sourceRefs": [ + { + "originalSourcePath": "job-tracker-ui/src/profileCv.ts", + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/source/job-tracker-ui/src/profileCv.ts", + "sha256Raw": "a8d96474a6cf0adb66ac04af92bb9c256ea5622eef3c3414ac595348d0312451", + "bytes": 11619, + "canonicalLfSha256": "a398c182d2111e3f2a78d3bbf4005b967eac4b613af2a6f027a29851fd7240e7", + "acceptedGitCanonicalLfSha256": "a398c182d2111e3f2a78d3bbf4005b967eac4b613af2a6f027a29851fd7240e7", + "gitShowCommand": [ + "rtk", + "proxy", + "git", + "show", + "8b4d5c21125e800199d3ecc2d9c059a80ac5125d:job-tracker-ui/src/profileCv.ts" + ], + "gitShowExitCode": 0, + "verified": "Canonical LF bytes equal accepted git show; copied raw bytes unchanged" + }, + { + "originalSourcePath": "job-tracker-ui/src/views/CareerProfilePage.tsx", + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/source/job-tracker-ui/src/views/CareerProfilePage.tsx", + "sha256Raw": "a70c1f6aba86da0c34621b7812b30525dc5f96a67a983c6bf42826c116ad07b4", + "bytes": 48634, + "canonicalLfSha256": "961f992fe9684766abb253f939bf64ca28bd4e671ba3f6efb98904aba6dea091", + "acceptedGitCanonicalLfSha256": "961f992fe9684766abb253f939bf64ca28bd4e671ba3f6efb98904aba6dea091", + "gitShowCommand": [ + "rtk", + "proxy", + "git", + "show", + "8b4d5c21125e800199d3ecc2d9c059a80ac5125d:job-tracker-ui/src/views/CareerProfilePage.tsx" + ], + "gitShowExitCode": 0, + "verified": "Canonical LF bytes equal accepted git show; copied raw bytes unchanged" + } + ], + "frontendExport": { + "buildId": "qG82wPnFf-IsAkFvXkmn6", + "exportFiles": 75, + "exportSha256": "50896e8ad6934b909b83cc487eaf3579516921fde54b19e50a9039db68e04869", + "immutableRoot": ".artifacts/phase7/p7-02/career-final/export", + "qualification": "Existing accepted P7-02 export referenced without duplicate or rebuilt export; native RED outcome pending" + }, + "unitBaseline": { + "status": "REPRODUCED_RED", + "passed": 25, + "failed": 5, + "total": 30, + "rawPrefix": ".artifacts/phase7/current/unit/career-id-red-bounded-20261012T055452Z", + "qualification": "Bounded normalizer6 plus existingProfile24; meaningful missing-ID/payload assertions, no skip-based acceptance; final GREEN not executed yet" + }, + "nativeStatus": "PENDING", + "limitations": [ + "Forward preservation cannot safely remap older orphaned overrides automatically; existing historical records remain and require a separately justified recovery decision.", + "Possible nullable metadata fidelity concern is pending actual native artifact; no additional repair or success claimed.", + "Planned full616/90 is derived only, latest full573/89 remains inherited." + ] + } + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/identity.json", + "evidence": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/identity.json", + "sha256": "93b4098e97085162b18665f59da568b572ff4be16ed228eb0b90ab61f1553c14", + "bytes": 6155, + "hashPolicy": "Exact measured raw bytes" + }, + "record": { + "schemaVersion": 1, + "status": "HISTORICAL_FIRST_NATIVE_DIAGNOSTIC_NOT_ACCEPTANCE", + "command": { + "name": "career-source-ids", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/phase7-career-source-ids.spec.ts", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-source-ids-results" + ], + "startedUtc": "2026-10-12T06:06:22.720694+00:00", + "finishedUtc": "2026-10-12T06:06:36.235817+00:00", + "exitCode": 1, + "failureLog": "E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-source-ids.log", + "stats": { + "startTime": "2026-10-12T06:06:23.250Z", + "duration": 12950.169, + "expected": 1, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + } + }, + "stats": { + "startTime": "2026-10-12T06:06:23.250Z", + "duration": 12950.169, + "expected": 1, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "report": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "bytes": 395866, + "hashPolicy": "Exact saved raw bytes" + }, + "savedFiles": [ + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "bytes": 395866, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.log", + "sha256": "1bad990febabbdce1a915800f93eacd6caf79ce4907809ba597b010271706266", + "bytes": 4362, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-command.json", + "sha256": "06df79985df46274f50f4e1a2ff6df30c775cea0f746dd089d04f4a8b0c4ee9f", + "bytes": 784, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/.last-run.json", + "sha256": "9264dc74ba27f0b8e16a085fa8e59920a6f5b39ae205edfa84d2d7b9da8cf231", + "bytes": 96, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/error-context.md", + "sha256": "b74ff4015ded25cfc32b14846e815aee96b312b59c0c937513db2fd389c8398c", + "bytes": 39658, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/test-failed-1.png", + "sha256": "f653953528b2a8ecffb330af3900c40079c734af10934cf3ec7804eb37e12b20", + "bytes": 36813, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/trace.zip", + "sha256": "9ca53762d499d759f8361845fdb83e2e8883ca2c526e747d8258acb32e0335f3", + "bytes": 926632, + "hashPolicy": "Exact saved raw bytes" + } + ], + "embeddedAttachments": [ + { + "name": "native-career-source-id-readbacks", + "contentType": "application/json", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/embedded/01-native-career-source-id-readbacks.json", + "sha256": "ab91bd8d15a926bf1a39a5adba919ab9a94cd1f3f7d87710a17df1de2fa5d4f8", + "bytes": 89476, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "bytes": 395866, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "native-career-source-id-editor", + "contentType": "image/png", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/embedded/02-native-career-source-id-editor.png", + "sha256": "fed9826625ee6fab043090b95b9b7ffc926438557d4de7588943755079945fca", + "bytes": 189851, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "bytes": 395866, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "native-canonical-stale-contract-characterization", + "contentType": "application/json", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/embedded/03-native-canonical-stale-contract-characterization.json", + "sha256": "0e5157a04c14b4d716736f9e5707b0631989797e41e4f915d8745685cbeb56aa", + "bytes": 9003, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "bytes": 395866, + "hashPolicy": "Exact saved raw bytes" + } + } + ], + "build": "Unchanged accepted qG82wPnFf-IsAkFvXkmn6 export", + "qualification": "Historical first diagnostic one fail/one pass: selected-DTO updatedAtUtc association fixture flaw was corrected for the authoritative native RED. Missing-ID/nullable metadata observations retained; not final acceptance. Original report internal execution paths remain unchanged; copied files/embedded bytes preserved exactly. Zero skip/retry/flaky." + } + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/identity.json", + "evidence": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/identity.json", + "sha256": "278682920aee102d0c01bc855e5d345c7b056a61f3760f70cf8b119be19e0ae1", + "bytes": 6164, + "hashPolicy": "Exact measured raw bytes" + }, + "record": { + "schemaVersion": 1, + "status": "AUTHORITATIVE_NATIVE_RED", + "command": { + "name": "career-source-ids", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/phase7-career-source-ids.spec.ts", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-source-ids-results" + ], + "startedUtc": "2026-10-12T06:08:57.903506+00:00", + "finishedUtc": "2026-10-12T06:09:10.383980+00:00", + "exitCode": 1, + "failureLog": "E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase7\\current\\ui\\career-source-ids.log", + "stats": { + "startTime": "2026-10-12T06:08:58.411Z", + "duration": 11935, + "expected": 1, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + } + }, + "stats": { + "startTime": "2026-10-12T06:08:58.411Z", + "duration": 11935, + "expected": 1, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "report": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "bytes": 395762, + "hashPolicy": "Exact saved raw bytes" + }, + "savedFiles": [ + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "bytes": 395762, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.log", + "sha256": "ffb5a96accdd77ec3765f276c4afae3d8894ed1631b1d04805b0bad70b4604e0", + "bytes": 4363, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-command.json", + "sha256": "357c50d9527c38e45fa5c9ed8773bad8dab861ede685a68c6c8baac2e6f30f36", + "bytes": 780, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/.last-run.json", + "sha256": "9264dc74ba27f0b8e16a085fa8e59920a6f5b39ae205edfa84d2d7b9da8cf231", + "bytes": 96, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/error-context.md", + "sha256": "aff78965b59932b6fc5f5942ef4d7322c7d23fc33a206dc03857050a8d656a36", + "bytes": 39765, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/test-failed-1.png", + "sha256": "0f20757880ffbdb01012a3b6fc411f8dab05cfb7f8930afc87a30af57a2c7a0d", + "bytes": 36818, + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/trace.zip", + "sha256": "d9ec955f1cba282b48a35442a2ad42647adf6170e1397a2cb99ee0a07e4ffc43", + "bytes": 958494, + "hashPolicy": "Exact saved raw bytes" + } + ], + "embeddedAttachments": [ + { + "name": "native-career-source-id-readbacks", + "contentType": "application/json", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/embedded/01-native-career-source-id-readbacks.json", + "sha256": "040d15a0982611e0d3bc8592cc1a1382f53a0fe4425ab6fbcc21d1335f651b73", + "bytes": 89475, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "bytes": 395762, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "native-career-source-id-editor", + "contentType": "image/png", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/embedded/02-native-career-source-id-editor.png", + "sha256": "d84d5b91bc6a617ccce161aca8d0581a9cff1ba21434847ca23abf921121691d", + "bytes": 189778, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "bytes": 395762, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "native-canonical-stale-contract-characterization", + "contentType": "application/json", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/embedded/03-native-canonical-stale-contract-characterization.json", + "sha256": "b56ed3f1e57e02b8042f80cacec64556c243bf2c4453c6f87ced7c8669005243", + "bytes": 9003, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "bytes": 395762, + "hashPolicy": "Exact saved raw bytes" + } + } + ], + "build": "Unchanged accepted qG82wPnFf-IsAkFvXkmn6 export", + "qualification": "Authoritative corrected fixture: requested/persisted IDs false, override title/bullet true→false, selected/sibling DTO+both histories+frozen unchanged TRUE; three nullable metadata fields become0. Actual one fail/one pass; no final repair, PDF/concurrency or whole-checkpoint acceptance. Original report internal execution paths remain unchanged; copied files/embedded bytes preserved exactly. Zero skip/retry/flaky." + } + } + ], + "rawRetention": { + "root": ".artifacts/phase7/p7-03/source-id-repair/final", + "runtimeFiles": 16, + "unitFiles": 15, + "qualification": "All six final root lane receipts/raw, result attachments, relevant unit history, one product owner/three test owners, BUILD_ID/export/runner/config/API identity/entry retained byte-for-byte. Baseline source/RED capsules remain separately immutable; do not rerun collector after subsequent build/source changes." + }, + "derivedExpectationsOnly": { + "frontend": "618/90", + "ordinaryBrowser": 216, + "backend": 1034, + "latestFullFrontend": "Inherited573/89; no new full suite run", + "qualification": "Finite native packs/targeted guards overlap; derived totals are not fresh whole-suite execution." + }, + "preservation": { + "groups": 57, + "partial": 56, + "deferred": 1, + "routes": 32 + }, + "limitations": [ + "Forward optional-ID preservation cannot safely remap older orphaned overrides; historical records remain.", + "Qualified stale200/append-restore/raw-current/owner-denial characterization is not a concurrency repair or new revision/schema protocol.", + "No PDF/renderer/model/provider/automatic extraction action; P703 editor/import presentation remains pending.", + "M01–M12 human/device/zoom/contextual requirements carry; P5-13/C11 deferred, Phase8 separate, main unchanged/production NO-GO." + ], + "pushReceipt": { + "status": "PENDING" + }, + "readbackPayloads": [ + { + "name": "native-career-source-id-readbacks", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/readback/native-career-source-id-readbacks.json", + "sha256": "463027b1e9b25842e69541aaadd3e6a4830d2ec2c743ebc2811c0b32a21c5b1f", + "bytes": 89557, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "bytes": 389389, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "native-canonical-stale-contract-characterization", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/readback/native-canonical-stale-contract-characterization.json", + "sha256": "36aa851d09b68c8b6705e707a8385d1dd3d3141faf34e4293938b2fb344e76f7", + "bytes": 8996, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "bytes": 389389, + "hashPolicy": "Exact saved raw bytes" + } + } + ], + "parentReview": { + "inspectedPNG": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/effe56f6ea9a/native-career-source-id-editor.png", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "bytes": 189632, + "hashPolicy": "Exact saved raw bytes" + }, + "parentReviewedDuplicate": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/parent-reviewed-editor.png", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "bytes": 189632, + "hashPolicy": "Exact saved raw bytes" + }, + "additionalPreservationPNG": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/b155c1c4645f/native-frozen-package.png", + "sha256": "1fcd650af0f5e913abd2635aafeb8c41042cfd5c42936de8928a44c5f47b27ea", + "bytes": 94122, + "hashPolicy": "Exact saved raw bytes" + }, + "originalEmbeddedReport": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "bytes": 389389, + "hashPolicy": "Exact saved raw bytes" + }, + "visualReceipt": "Root opened two final PNGs with view_image: full-page390x4683 original editor (resized display171x2048) and native-frozen-package; separately inspected corrected RED failure viewport image. Final Save/content reaches original editor; presentation migration remains pending.", + "payloadReceipt": "Root checked all11 observed booleans TRUE; all three source-ID snapshots match and nullable metadata before/after are exact.", + "qualification": "Two finite existing-owner samples only. Editor image has sticky chrome at actual scroll capture; frozen-package dialog image blends underlying workspace/chrome, with transition cause not diagnosed. Neither establishes settled dialog/responsive/theme/axe/human/provider/PDF conformance; P706/P711 visual qualification remains. Stale200/append-restore/raw-current/owner-denial case characterizes current protocol; it does not repair concurrency." + }, + "parentHashVerification": { + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/parent-hash-verification.json", + "sha256": "afa1c2731d0c568cd6e6c27e71a3270a816c19a44e739afff06ccd72117ff0f3", + "bytes": 28347, + "hashPolicy": "Exact saved raw bytes" + }, + "record": { + "observedUtc": "2026-10-12T06:19:41.347689+00:00", + "manifest": "docs\\redesign\\phase-7\\p7-03\\evidence\\source-id-results.json", + "referenceCount": 81, + "uniqueFiles": 62, + "errors": [], + "references": [ + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/entry-career-results.json", + "sha256": "1f67cfc3b6d2f34143261bf81a466a28289f21bdbf105ac8ea0b45b4f8446951", + "expected": "1f67cfc3b6d2f34143261bf81a466a28289f21bdbf105ac8ea0b45b4f8446951", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": "job-tracker-ui/src/profileCv.ts", + "sha256": "7e0b8aa13aa6df830f7e508c338c1e2dd995574bbfbd3233602654452f75cdb9", + "expected": "7e0b8aa13aa6df830f7e508c338c1e2dd995574bbfbd3233602654452f75cdb9", + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/source/job-tracker-ui/src/profileCv.ts", + "sha256": "190b3e15ab00741f1e6bea868a79c3ca221e059936406098b693d13f3ef3f1d7", + "expected": "190b3e15ab00741f1e6bea868a79c3ca221e059936406098b693d13f3ef3f1d7", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/tests/job-tracker-ui/src/profileCv.test.ts", + "sha256": "a85cbebacb01d11bb92898d2a9809744fd65c9b8f9a525d7f2050c86815c5e97", + "expected": "a85cbebacb01d11bb92898d2a9809744fd65c9b8f9a525d7f2050c86815c5e97", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": "job-tracker-ui/src/profileCv.test.ts", + "sha256": "a85cbebacb01d11bb92898d2a9809744fd65c9b8f9a525d7f2050c86815c5e97", + "expected": "a85cbebacb01d11bb92898d2a9809744fd65c9b8f9a525d7f2050c86815c5e97", + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/tests/job-tracker-ui/src/profile-page.test.tsx", + "sha256": "84c9f2683e445f8a56de53ec84e2b291792985ea829dcef688aaafa34ddd32a6", + "expected": "84c9f2683e445f8a56de53ec84e2b291792985ea829dcef688aaafa34ddd32a6", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": "job-tracker-ui/src/profile-page.test.tsx", + "sha256": "ac1421ecf0fb4723fa974e4e1f0899d0eb0aa53d3225eb428b11c086d6f22950", + "expected": "ac1421ecf0fb4723fa974e4e1f0899d0eb0aa53d3225eb428b11c086d6f22950", + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/tests/job-tracker-ui/e2e/phase7-career-source-ids.spec.ts", + "sha256": "92bc8f1b4c82210207071c56940813dfece3136832ba09ebd1e6c3471d8d7945", + "expected": "92bc8f1b4c82210207071c56940813dfece3136832ba09ebd1e6c3471d8d7945", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": "job-tracker-ui/e2e/phase7-career-source-ids.spec.ts", + "sha256": "92bc8f1b4c82210207071c56940813dfece3136832ba09ebd1e6c3471d8d7945", + "expected": "92bc8f1b4c82210207071c56940813dfece3136832ba09ebd1e6c3471d8d7945", + "hashPolicy": "UTF-8 text with CRLF normalized to LF" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/BUILD_ID", + "sha256": "49f2090d798c337c72c6937cf6cb5e0c5da5ff528f90b45ee65253b1312af136", + "expected": "49f2090d798c337c72c6937cf6cb5e0c5da5ff528f90b45ee65253b1312af136", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runner/run-ui.py", + "sha256": "0d556c6cb61be6deb930603de9b58df5e14e4763a6f9e31652258e955f7c5f0d", + "expected": "0d556c6cb61be6deb930603de9b58df5e14e4763a6f9e31652258e955f7c5f0d", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runner/e2e-tsconfig.json", + "sha256": "55fa6fffaed1e76a32657edfffcc501cd8bd87330bda2c3a3944f8f89d4019e2", + "expected": "55fa6fffaed1e76a32657edfffcc501cd8bd87330bda2c3a3944f8f89d4019e2", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/api/JobTrackerApi.dll", + "sha256": "d2da64748364880d471d2087d5aa101ce749b26966beed13d9e9dbaa3b92512b", + "expected": "d2da64748364880d471d2087d5aa101ce749b26966beed13d9e9dbaa3b92512b", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/typecheck-command.json", + "sha256": "8234803d8aefa430c8733cbd916b2ff3523c6a5bbf443bf8c2cbc384090b485e", + "expected": "8234803d8aefa430c8733cbd916b2ff3523c6a5bbf443bf8c2cbc384090b485e", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/typecheck.log", + "sha256": "89b0ec97b537eca6560c13ca2dfea9e3a97dd1bb35580c4ff39d2462db25e080", + "expected": "89b0ec97b537eca6560c13ca2dfea9e3a97dd1bb35580c4ff39d2462db25e080", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/browser-typecheck-command.json", + "sha256": "fc559a667c0d9dcd78fa6342a8ab408317688258288b5b9bdcbc0840567edac4", + "expected": "fc559a667c0d9dcd78fa6342a8ab408317688258288b5b9bdcbc0840567edac4", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/browser-typecheck.log", + "sha256": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6", + "expected": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/lint-command.json", + "sha256": "6aad66214ad3235829030b6cb5df758a4bda63d67d07a9d416e684006362ed94", + "expected": "6aad66214ad3235829030b6cb5df758a4bda63d67d07a9d416e684006362ed94", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/lint.log", + "sha256": "b040dbeca9b4adb3f6f4c25ac49de0d37e921375b2d9b57e87b542a10f599913", + "expected": "b040dbeca9b4adb3f6f4c25ac49de0d37e921375b2d9b57e87b542a10f599913", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/build-command.json", + "sha256": "e4fca0a8aded5ada0bcedacceca3651dd4857a74407bba3b9b71d57bb104cb73", + "expected": "e4fca0a8aded5ada0bcedacceca3651dd4857a74407bba3b9b71d57bb104cb73", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/build.log", + "sha256": "1b2c5385cfb901084e87ce46a699b8a71ba6204cdfde56d890305489f0c73ce0", + "expected": "1b2c5385cfb901084e87ce46a699b8a71ba6204cdfde56d890305489f0c73ce0", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids-command.json", + "sha256": "780b56d52886a326ff31f04c5f400b2629627e0f03efa391c735ec965b3a87e7", + "expected": "780b56d52886a326ff31f04c5f400b2629627e0f03efa391c735ec965b3a87e7", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.log", + "sha256": "7f1cd8aebbb41c1ce75b680fa5a77175094e2783c2cdb702a2659b999b093f6a", + "expected": "7f1cd8aebbb41c1ce75b680fa5a77175094e2783c2cdb702a2659b999b093f6a", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation-command.json", + "sha256": "98cf49f4855f153f785908ce33c8f2a64bdda314c37f5ed9b53660595726b910", + "expected": "98cf49f4855f153f785908ce33c8f2a64bdda314c37f5ed9b53660595726b910", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.log", + "sha256": "06ae9d36d33e1971bcb628d99d25109b7adf06fb1ad7acf8b9f73b2995be951c", + "expected": "06ae9d36d33e1971bcb628d99d25109b7adf06fb1ad7acf8b9f73b2995be951c", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z.json", + "sha256": "bccd0cd98270c61f52f1d34967fcf08d346912bdf077dde6568666bce17ce466", + "expected": "bccd0cd98270c61f52f1d34967fcf08d346912bdf077dde6568666bce17ce466", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z-command.json", + "sha256": "84de6f47db72a7f9226d97ff711acce3561b91d571d9804f0a799cd8f8991c38", + "expected": "84de6f47db72a7f9226d97ff711acce3561b91d571d9804f0a799cd8f8991c38", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z.log", + "sha256": "500c3ad8ff26830b813c227cb8f7a21592291285587f653545ac98175258d1a0", + "expected": "500c3ad8ff26830b813c227cb8f7a21592291285587f653545ac98175258d1a0", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids-command.json", + "sha256": "780b56d52886a326ff31f04c5f400b2629627e0f03efa391c735ec965b3a87e7", + "expected": "780b56d52886a326ff31f04c5f400b2629627e0f03efa391c735ec965b3a87e7", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "expected": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.log", + "sha256": "7f1cd8aebbb41c1ce75b680fa5a77175094e2783c2cdb702a2659b999b093f6a", + "expected": "7f1cd8aebbb41c1ce75b680fa5a77175094e2783c2cdb702a2659b999b093f6a", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/effe56f6ea9a/native-career-source-id-editor.png", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "expected": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "expected": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation-command.json", + "sha256": "98cf49f4855f153f785908ce33c8f2a64bdda314c37f5ed9b53660595726b910", + "expected": "98cf49f4855f153f785908ce33c8f2a64bdda314c37f5ed9b53660595726b910", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.json", + "sha256": "b155c1c4645f9085b71723305bfc0fd831287e150665f1f4de563771fd1565d2", + "expected": "b155c1c4645f9085b71723305bfc0fd831287e150665f1f4de563771fd1565d2", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.log", + "sha256": "06ae9d36d33e1971bcb628d99d25109b7adf06fb1ad7acf8b9f73b2995be951c", + "expected": "06ae9d36d33e1971bcb628d99d25109b7adf06fb1ad7acf8b9f73b2995be951c", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/b155c1c4645f/native-frozen-package.png", + "sha256": "1fcd650af0f5e913abd2635aafeb8c41042cfd5c42936de8928a44c5f47b27ea", + "expected": "1fcd650af0f5e913abd2635aafeb8c41042cfd5c42936de8928a44c5f47b27ea", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-preservation.json", + "sha256": "b155c1c4645f9085b71723305bfc0fd831287e150665f1f4de563771fd1565d2", + "expected": "b155c1c4645f9085b71723305bfc0fd831287e150665f1f4de563771fd1565d2", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-green-20261012T061027Z.json", + "sha256": "bccd0cd98270c61f52f1d34967fcf08d346912bdf077dde6568666bce17ce466", + "expected": "bccd0cd98270c61f52f1d34967fcf08d346912bdf077dde6568666bce17ce466", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-metadata-red-20261012T060859Z.json", + "sha256": "9a6911e75c8ef9877d4edcf9a8601534a94cff658a2867a5bf9b47b5baa5af66", + "expected": "9a6911e75c8ef9877d4edcf9a8601534a94cff658a2867a5bf9b47b5baa5af66", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-red-20261012T055246Z.json", + "sha256": "0b3b3f9749e06e794ca802a3c3091a5ce82615c0e83d1fbc28a2124c2f141d1b", + "expected": "0b3b3f9749e06e794ca802a3c3091a5ce82615c0e83d1fbc28a2124c2f141d1b", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-red-bounded-20261012T055452Z.json", + "sha256": "51606eaed128afce6c5fe21381bbf5e70952d1d4e243c868b35750ab28474b89", + "expected": "51606eaed128afce6c5fe21381bbf5e70952d1d4e243c868b35750ab28474b89", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/unit/career-id-red-repeat-20261012T055358Z.json", + "sha256": "da9204062cf64248e8d0b182bf3322fc2697eb2d576aece0b4719a6ffe345205", + "expected": "da9204062cf64248e8d0b182bf3322fc2697eb2d576aece0b4719a6ffe345205", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/identity.json", + "sha256": "0cdf3e1ab08453e53c702b5e8cda93dd968dd04a303efa129f4831d4f01ba393", + "expected": "0cdf3e1ab08453e53c702b5e8cda93dd968dd04a303efa129f4831d4f01ba393", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/identity.json", + "sha256": "93b4098e97085162b18665f59da568b572ff4be16ed228eb0b90ab61f1553c14", + "expected": "93b4098e97085162b18665f59da568b572ff4be16ed228eb0b90ab61f1553c14", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "expected": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "expected": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.log", + "sha256": "1bad990febabbdce1a915800f93eacd6caf79ce4907809ba597b010271706266", + "expected": "1bad990febabbdce1a915800f93eacd6caf79ce4907809ba597b010271706266", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-command.json", + "sha256": "06df79985df46274f50f4e1a2ff6df30c775cea0f746dd089d04f4a8b0c4ee9f", + "expected": "06df79985df46274f50f4e1a2ff6df30c775cea0f746dd089d04f4a8b0c4ee9f", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/.last-run.json", + "sha256": "9264dc74ba27f0b8e16a085fa8e59920a6f5b39ae205edfa84d2d7b9da8cf231", + "expected": "9264dc74ba27f0b8e16a085fa8e59920a6f5b39ae205edfa84d2d7b9da8cf231", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/error-context.md", + "sha256": "b74ff4015ded25cfc32b14846e815aee96b312b59c0c937513db2fd389c8398c", + "expected": "b74ff4015ded25cfc32b14846e815aee96b312b59c0c937513db2fd389c8398c", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/test-failed-1.png", + "sha256": "f653953528b2a8ecffb330af3900c40079c734af10934cf3ec7804eb37e12b20", + "expected": "f653953528b2a8ecffb330af3900c40079c734af10934cf3ec7804eb37e12b20", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/trace.zip", + "sha256": "9ca53762d499d759f8361845fdb83e2e8883ca2c526e747d8258acb32e0335f3", + "expected": "9ca53762d499d759f8361845fdb83e2e8883ca2c526e747d8258acb32e0335f3", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/embedded/01-native-career-source-id-readbacks.json", + "sha256": "ab91bd8d15a926bf1a39a5adba919ab9a94cd1f3f7d87710a17df1de2fa5d4f8", + "expected": "ab91bd8d15a926bf1a39a5adba919ab9a94cd1f3f7d87710a17df1de2fa5d4f8", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "expected": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/embedded/02-native-career-source-id-editor.png", + "sha256": "fed9826625ee6fab043090b95b9b7ffc926438557d4de7588943755079945fca", + "expected": "fed9826625ee6fab043090b95b9b7ffc926438557d4de7588943755079945fca", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "expected": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/embedded/03-native-canonical-stale-contract-characterization.json", + "sha256": "0e5157a04c14b4d716736f9e5707b0631989797e41e4f915d8745685cbeb56aa", + "expected": "0e5157a04c14b4d716736f9e5707b0631989797e41e4f915d8745685cbeb56aa", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-first/career-source-ids.json", + "sha256": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "expected": "31019c3b6b3b826f7e637ff85df8e7726f90e61a8f1ea1ca44ae2357a11f4635", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/identity.json", + "sha256": "278682920aee102d0c01bc855e5d345c7b056a61f3760f70cf8b119be19e0ae1", + "expected": "278682920aee102d0c01bc855e5d345c7b056a61f3760f70cf8b119be19e0ae1", + "hashPolicy": "Exact measured raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "expected": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "expected": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.log", + "sha256": "ffb5a96accdd77ec3765f276c4afae3d8894ed1631b1d04805b0bad70b4604e0", + "expected": "ffb5a96accdd77ec3765f276c4afae3d8894ed1631b1d04805b0bad70b4604e0", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-command.json", + "sha256": "357c50d9527c38e45fa5c9ed8773bad8dab861ede685a68c6c8baac2e6f30f36", + "expected": "357c50d9527c38e45fa5c9ed8773bad8dab861ede685a68c6c8baac2e6f30f36", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/.last-run.json", + "sha256": "9264dc74ba27f0b8e16a085fa8e59920a6f5b39ae205edfa84d2d7b9da8cf231", + "expected": "9264dc74ba27f0b8e16a085fa8e59920a6f5b39ae205edfa84d2d7b9da8cf231", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/error-context.md", + "sha256": "aff78965b59932b6fc5f5942ef4d7322c7d23fc33a206dc03857050a8d656a36", + "expected": "aff78965b59932b6fc5f5942ef4d7322c7d23fc33a206dc03857050a8d656a36", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/test-failed-1.png", + "sha256": "0f20757880ffbdb01012a3b6fc411f8dab05cfb7f8930afc87a30af57a2c7a0d", + "expected": "0f20757880ffbdb01012a3b6fc411f8dab05cfb7f8930afc87a30af57a2c7a0d", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids-results/phase7-career-source-ids---bfbe4--sibling-and-frozen-package-chromium/trace.zip", + "sha256": "d9ec955f1cba282b48a35442a2ad42647adf6170e1397a2cb99ee0a07e4ffc43", + "expected": "d9ec955f1cba282b48a35442a2ad42647adf6170e1397a2cb99ee0a07e4ffc43", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/embedded/01-native-career-source-id-readbacks.json", + "sha256": "040d15a0982611e0d3bc8592cc1a1382f53a0fe4425ab6fbcc21d1335f651b73", + "expected": "040d15a0982611e0d3bc8592cc1a1382f53a0fe4425ab6fbcc21d1335f651b73", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "expected": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/embedded/02-native-career-source-id-editor.png", + "sha256": "d84d5b91bc6a617ccce161aca8d0581a9cff1ba21434847ca23abf921121691d", + "expected": "d84d5b91bc6a617ccce161aca8d0581a9cff1ba21434847ca23abf921121691d", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "expected": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/embedded/03-native-canonical-stale-contract-characterization.json", + "sha256": "b56ed3f1e57e02b8042f80cacec64556c243bf2c4453c6f87ced7c8669005243", + "expected": "b56ed3f1e57e02b8042f80cacec64556c243bf2c4453c6f87ced7c8669005243", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/baseline/native-red/career-source-ids.json", + "sha256": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "expected": "d3f284813f9b774de4db3ec13cf2ab762e2a60ba6374f0d7f81293ca65863161", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/readback/native-career-source-id-readbacks.json", + "sha256": "463027b1e9b25842e69541aaadd3e6a4830d2ec2c743ebc2811c0b32a21c5b1f", + "expected": "463027b1e9b25842e69541aaadd3e6a4830d2ec2c743ebc2811c0b32a21c5b1f", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "expected": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/readback/native-canonical-stale-contract-characterization.json", + "sha256": "36aa851d09b68c8b6705e707a8385d1dd3d3141faf34e4293938b2fb344e76f7", + "expected": "36aa851d09b68c8b6705e707a8385d1dd3d3141faf34e4293938b2fb344e76f7", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "expected": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/visuals/effe56f6ea9a/native-career-source-id-editor.png", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "expected": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/parent-reviewed-editor.png", + "sha256": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "expected": "a24e34a3d8fe47364b2d6a786542555f3711593bd5bccf6a1a16d179382bb466", + "hashPolicy": "Exact saved raw bytes" + }, + { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/runtime/career-source-ids.json", + "sha256": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "expected": "effe56f6ea9ab69bb4074e9afcbfc40b4e02d7626c56660a68992ed4704de20f", + "hashPolicy": "Exact saved raw bytes" + } + ], + "export": { + "files": 75, + "actual": "812182947b7af96a00f9568a83de1098f2824c53550c7119c76ec41803e71fbf", + "expected": "812182947b7af96a00f9568a83de1098f2824c53550c7119c76ec41803e71fbf", + "rawHashPolicy": "Sorted original export path TAB exact raw SHA LF records" + } + }, + "qualification": "Root independently verified81 references/62 unique files plus75-file frozen export at this observation; later review/receipt metadata references do not change measured runtime/source/export. Own final checker subsequently verified84 references/64 unique files before this receipt reference." + }, + "staticGate": { + "status": "PASS", + "checkedUtc": "2026-10-12T06:21:53.962988+00:00", + "evidence": { + "path": "docs/redesign/phase-7/p7-03/evidence/source-id-static-checks.json", + "sha256": "3a910cd0041f2cf855484c161b21bc4f4b1de7446af80600315b4fcf18e76863", + "bytes": 3166, + "hashPolicy": "Portable JSON UTF-8 with CRLF normalized to LF" + }, + "immutableRawSnapshot": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/static/source-id-static-checks.json", + "sha256": "3a910cd0041f2cf855484c161b21bc4f4b1de7446af80600315b4fcf18e76863", + "bytes": 3166, + "hashPolicy": "Exact saved raw bytes" + }, + "logs": [ + { + "name": "secret-scan", + "originalLog": ".artifacts/phase7/current/static/20261012T062150Z/secret-scan.log", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/static/secret-scan.log", + "sha256": "c5a88d5ebdc042adba125c1eaacbe44f9f4a5c19898c0f195573c00d511aa28d", + "bytes": 153, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "working-whitespace", + "originalLog": ".artifacts/phase7/current/static/20261012T062150Z/working-whitespace.log", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/static/working-whitespace.log", + "sha256": "436a42b59983ec462f084c8728fedaff39a8c806159aac9a1a729531aa7fda5b", + "bytes": 1104, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "staged-whitespace", + "originalLog": ".artifacts/phase7/current/static/20261012T062150Z/staged-whitespace.log", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/static/staged-whitespace.log", + "sha256": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6", + "bytes": 78, + "hashPolicy": "Exact saved raw bytes" + } + }, + { + "name": "phase7-whitespace", + "originalLog": ".artifacts/phase7/current/static/20261012T062150Z/phase7-whitespace.log", + "raw": { + "path": ".artifacts/phase7/p7-03/source-id-repair/final/static/phase7-whitespace.log", + "sha256": "5ca1538c7d0fbd5ad380f1af7ce928e68c7e7158dd2cddaa077fcf07d7105a00", + "bytes": 1104, + "hashPolicy": "Exact saved raw bytes" + } + } + ], + "record": { + "schemaVersion": 1, + "checkpoint": "p7-03", + "status": "PASS", + "checkedUtc": "2026-10-12T06:21:53.962988+00:00", + "commands": [ + { + "name": "secret-scan", + "command": [ + "rtk", + "proxy", + "C:\\Users\\Connor\\AppData\\Local\\Programs\\Python\\Python312\\python.exe", + "-X", + "utf8", + "scripts/supply-chain.py", + "scan-secrets" + ], + "startedUtc": "2026-10-12T06:21:50.989006+00:00", + "finishedUtc": "2026-10-12T06:21:53.334042+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/secret-scan.log", + "logSha256Raw": "c5a88d5ebdc042adba125c1eaacbe44f9f4a5c19898c0f195573c00d511aa28d" + }, + { + "name": "working-whitespace", + "command": [ + "rtk", + "proxy", + "git", + "diff", + "--check" + ], + "startedUtc": "2026-10-12T06:21:53.334561+00:00", + "finishedUtc": "2026-10-12T06:21:53.432831+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/working-whitespace.log", + "logSha256Raw": "436a42b59983ec462f084c8728fedaff39a8c806159aac9a1a729531aa7fda5b" + }, + { + "name": "staged-whitespace", + "command": [ + "rtk", + "proxy", + "git", + "diff", + "--cached", + "--check" + ], + "startedUtc": "2026-10-12T06:21:53.433325+00:00", + "finishedUtc": "2026-10-12T06:21:53.510414+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/staged-whitespace.log", + "logSha256Raw": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6" + }, + { + "name": "phase7-whitespace", + "command": [ + "rtk", + "proxy", + "git", + "diff", + "--check", + "b5319981ad3d1bd635daff861453d23c0de5320b" + ], + "startedUtc": "2026-10-12T06:21:53.510414+00:00", + "finishedUtc": "2026-10-12T06:21:53.638067+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/phase7-whitespace.log", + "logSha256Raw": "5ca1538c7d0fbd5ad380f1af7ce928e68c7e7158dd2cddaa077fcf07d7105a00" + } + ], + "untrackedSecretScan": { + "files": 5, + "findings": 0 + }, + "documentation": { + "files": 10, + "relativeLinks": 370, + "errors": [] + }, + "preservation": { + "groups": 57, + "statuses": { + "PARTIAL": 56, + "PASS": 0, + "FAIL": 0, + "DEFERRED": 1 + }, + "originalRoutesPreserved": true, + "currentConcreteRoutes": 32 + }, + "production": { + "main": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "originMain": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "status": "NO-GO", + "qualification": "Local fetched refs; direct push observation recorded separately." + }, + "hashPolicy": "Portable JSON UTF8 LF; raw log hashes measure exact saved bytes.", + "limits": [ + "Pattern scanner skips binary and files over2MiB; not historical Git/production secrets.", + "Local links check target existence, not URL/heading anchors.", + "Static evidence is not runtime/manual/device/provider/production acceptance." + ] + }, + "qualification": "Final staged finite static check at recorded observation. Runtime/manual/source/export evidence unchanged; normal push pending." + } +} diff --git a/docs/redesign/phase-7/p7-03/evidence/source-id-static-checks.json b/docs/redesign/phase-7/p7-03/evidence/source-id-static-checks.json new file mode 100644 index 0000000..2f0de5a --- /dev/null +++ b/docs/redesign/phase-7/p7-03/evidence/source-id-static-checks.json @@ -0,0 +1,104 @@ +{ + "schemaVersion": 1, + "checkpoint": "p7-03", + "status": "PASS", + "checkedUtc": "2026-10-12T06:21:53.962988+00:00", + "commands": [ + { + "name": "secret-scan", + "command": [ + "rtk", + "proxy", + "C:\\Users\\Connor\\AppData\\Local\\Programs\\Python\\Python312\\python.exe", + "-X", + "utf8", + "scripts/supply-chain.py", + "scan-secrets" + ], + "startedUtc": "2026-10-12T06:21:50.989006+00:00", + "finishedUtc": "2026-10-12T06:21:53.334042+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/secret-scan.log", + "logSha256Raw": "c5a88d5ebdc042adba125c1eaacbe44f9f4a5c19898c0f195573c00d511aa28d" + }, + { + "name": "working-whitespace", + "command": [ + "rtk", + "proxy", + "git", + "diff", + "--check" + ], + "startedUtc": "2026-10-12T06:21:53.334561+00:00", + "finishedUtc": "2026-10-12T06:21:53.432831+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/working-whitespace.log", + "logSha256Raw": "436a42b59983ec462f084c8728fedaff39a8c806159aac9a1a729531aa7fda5b" + }, + { + "name": "staged-whitespace", + "command": [ + "rtk", + "proxy", + "git", + "diff", + "--cached", + "--check" + ], + "startedUtc": "2026-10-12T06:21:53.433325+00:00", + "finishedUtc": "2026-10-12T06:21:53.510414+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/staged-whitespace.log", + "logSha256Raw": "d2993bc68ad9a63f711c8f5473155e2ba00fdcd461220cc3849185f2f9ad93e6" + }, + { + "name": "phase7-whitespace", + "command": [ + "rtk", + "proxy", + "git", + "diff", + "--check", + "b5319981ad3d1bd635daff861453d23c0de5320b" + ], + "startedUtc": "2026-10-12T06:21:53.510414+00:00", + "finishedUtc": "2026-10-12T06:21:53.638067+00:00", + "exitCode": 0, + "log": ".artifacts/phase7/current/static/20261012T062150Z/phase7-whitespace.log", + "logSha256Raw": "5ca1538c7d0fbd5ad380f1af7ce928e68c7e7158dd2cddaa077fcf07d7105a00" + } + ], + "untrackedSecretScan": { + "files": 5, + "findings": 0 + }, + "documentation": { + "files": 10, + "relativeLinks": 370, + "errors": [] + }, + "preservation": { + "groups": 57, + "statuses": { + "PARTIAL": 56, + "PASS": 0, + "FAIL": 0, + "DEFERRED": 1 + }, + "originalRoutesPreserved": true, + "currentConcreteRoutes": 32 + }, + "production": { + "main": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "originMain": "27657f31131cd95d42f0e1290853ec9c9b3959a4", + "status": "NO-GO", + "qualification": "Local fetched refs; direct push observation recorded separately." + }, + "hashPolicy": "Portable JSON UTF8 LF; raw log hashes measure exact saved bytes.", + "limits": [ + "Pattern scanner skips binary and files over2MiB; not historical Git/production secrets.", + "Local links check target existence, not URL/heading anchors.", + "Static evidence is not runtime/manual/device/provider/production acceptance." + ] +} diff --git a/docs/roadmap/todo.md b/docs/roadmap/todo.md index 30334ec..316cc06 100644 --- a/docs/roadmap/todo.md +++ b/docs/roadmap/todo.md @@ -84,8 +84,8 @@ Follow the approved [Phase 7 handoff](../redesign/phase-6/p6-05/PHASE7_HANDOFF.m - [x] P7-00 fresh scope inventory and unchanged-source fixture baseline; finite static checks pass. Commit and remote receipt in the Phase 7 ledger. - [x] P7-01 public authentication and separate account/security presentation (implemented scope CONDITIONAL GO; account pushedad7b419/direct receipt19:16:15UTC): public sub-slice CONDITIONAL GO, pushed `8ad720d`, direct remote=HEAD verified2026-10-11 18:50:24UTC, main unchanged; affected61/native22/isolated SMTP2/helper6/auth subset87 pass. [Checkpoint record](../redesign/phase-7/p7-01/README.md) retains manual/provider/production gates. Fresh account full573/89, native6/public22/auth-boundaries10 and types/lint/build pass; all eight final post-copy PNGs actually inspected and source/context evidence frozen. Account85 and public31 current axe incompletes remain qualified; final staged finite hygiene passed; normal account pushad7b419 directly verified2026-10-11 19:16:15UTC with localHEAD=origin=live equality and clean worktree at observation, main unchanged. -- [ ] P7-02 [onboarding guidance and Career overview/evidence](../redesign/phase-7/p7-02/README.md): entryad7b419 pushed/verified; onboarding implemented-scope CONDITIONAL GO32/13/4+types/lint/build/13 actual PNG inspections/hygiene, pushedd21501aa/direct receipt23:55:12UTC. Separate actual SQLite evidence-list repair91 guards/HTTP1/Release passed and pushed01281f52/direct receipt00:06:47UTC; unfinished Career work preserved/main unchanged. Career affected46/3/native14/fresh preservation2/types/lint/build and22 actual PNG inspections pass; implemented P7-02 CONDITIONAL GO, final Career hygiene PASS (four commands0,9docs347links0errors) and normal push pending. Career0/99 axe incompletes/manual gates retained; fullfrontend610/backend1,034 are derived only, latest fresh full573/89 unchanged. -- [ ] P7-03 Career structured editor and import/history: after P7-02 push, separately RED/prove/repair optional stable source-ID preservation before presentation; prove dirty-locale/held-PUT pending-write ownership/recovery and resolve or bound RD21 concurrency before save/history expansion. +- [x] P7-02 [onboarding guidance and Career overview/evidence](../redesign/phase-7/p7-02/README.md): entryad7b419 pushed/verified; onboarding implemented-scope CONDITIONAL GO32/13/4+types/lint/build/13 actual PNG inspections/hygiene, pushedd21501aa/direct receipt23:55:12UTC. Separate actual SQLite evidence-list repair91 guards/HTTP1/Release passed and pushed01281f52/direct receipt00:06:47UTC; unfinished Career work preserved/main unchanged. Career affected46/3/native14/fresh preservation2/types/lint/build and22 actual PNG inspections pass; implemented P7-02 CONDITIONAL GO, final Career hygiene PASS (four commands0,9docs347links0errors) and normal push8b4d5c2 directly verified05:51:04UTC, localHEAD=origin=live/clean worktree/main unchanged. Career0/99 axe incompletes/manual gates retained; fullfrontend610/backend1,034 are derived only, latest fresh full573/89 unchanged. +- [ ] P7-03 Career structured editor and import/history: P7-02 pushed8b4d5c2; bounded source-ID/null-metadata repair46/3+native2/preservation2/types/lint/build and readback review pass, final hygiene PASS (four commands0,10docs370links0errors), normal push pending. Old orphan recovery/concurrency remains open; prove dirty-locale/held-PUT pending-write ownership/recovery before structured/import presentation. Full618/90/browser216 derived only. - [ ] P7-04 CV library and public entry. - [ ] P7-05 Discovery, Companies, Offers and Reminders. - [ ] P7-06 remaining Application forms and global correspondence. diff --git a/job-tracker-ui/e2e/phase7-career-source-ids.spec.ts b/job-tracker-ui/e2e/phase7-career-source-ids.spec.ts new file mode 100644 index 0000000..d996e84 --- /dev/null +++ b/job-tracker-ui/e2e/phase7-career-source-ids.spec.ts @@ -0,0 +1,254 @@ +import { expect, test as base, type APIRequestContext, type APIResponse } from '@playwright/test'; +import { translations } from '../src/i18n/translations'; +import type { CvVariant } from '../src/cvBuilder'; + +const apiUrl = 'http://localhost:5302/api'; +const password = 'E2ePassword123!'; +type Owner = { id: string; email: string; headers: Record }; +type SourceItem = { id?: string; [key: string]: unknown }; +type CareerProfile = Record & { + contact: Record; + jobs: SourceItem[]; + education: SourceItem[]; + projects: SourceItem[]; + certifications: SourceItem[]; +}; +type CareerReadback = { profile: CareerProfile; completeness: unknown; cvText: string | null }; +type CareerVersion = { version: number; source: string; createdAtUtc: string; isCurrent: boolean }; +type Preview = { themeId: string; html: string; suggestedFileName: string }; + +async function json(response: APIResponse, status = 200): Promise { + expect(response.status(), `${response.url()} must return ${status}`).toBe(status); + return response.json(); +} + +async function login(api: APIRequestContext, email: string): Promise { + expect((await api.post(`${apiUrl}/auth/login`, { data: { email, password } })).status()).toBe(200); + const me = await json<{ id: string; sessionContext: string }>(await api.get(`${apiUrl}/auth/me`)); + const csrf = (await api.storageState()).cookies.find(cookie => cookie.name === 'XSRF-TOKEN'); + expect(csrf).toBeDefined(); + return { id: me.id, email, headers: { 'X-CSRF-TOKEN': csrf!.value, 'X-Session-Context': me.sessionContext } }; +} + +async function createOwner(admin: APIRequestContext, headers: Record) { + const email = `p7-career-ids-${Date.now()}-${Math.random().toString(36).slice(2)}@example.test`; + expect((await admin.post(`${apiUrl}/users`, { headers, data: { email, password, roles: [] } })).status()).toBe(200); + return email; +} + +const test = base.extend<{ owner: Owner }>({ + owner: async ({ page, context, playwright }, provide) => { + const admin = await playwright.request.newContext(); + try { + const adminOwner = await login(admin, 'e2e@example.test'); + const owner = await login(page.request, await createOwner(admin, adminOwner.headers)); + expect((await page.request.put(`${apiUrl}/auth/preferences/language`, { headers: owner.headers, data: { language: 'en' } })).status()).toBe(204); + await context.route('**/*', route => { + const url = new URL(route.request().url()); + return ['localhost', '127.0.0.1'].includes(url.hostname) || ['data:', 'blob:', 'about:'].includes(url.protocol) + ? route.continue() : route.abort(); + }); + await context.addInitScript(() => { + localStorage.setItem('uiLanguage', 'en'); + localStorage.setItem('jobtracker.themeMode', 'light'); + }); + await provide(owner); + } finally { await admin.dispose(); } + }, +}); + +function sourceIds(profile: CareerProfile) { + return Object.fromEntries((['jobs', 'education', 'projects', 'certifications'] as const) + .map(key => [key, profile[key].map(item => item.id)])); +} + +function historyMetadata(versions: CareerVersion[]) { + return versions.map(({ version, source, createdAtUtc }) => ({ version, source, createdAtUtc })); +} + +test('[P7-03 PRES-C01 C03 C06 C07 C10 W05 W06] unrelated canonical UI save preserves four source IDs, existing CV overrides, sibling and frozen package', async ({ page, owner }, info) => { + test.setTimeout(120_000); + const raw = 'Exact owner source — æøå\nReviewed work and qualifications.\n'; + const profile = { + version: '1', + metadata: { fields: { 'contact.fullName': { confidence: 0.9, method: 'manual', sourceSnippet: 'Owner-reviewed contact', reviewState: 'reviewed' } } }, + contact: { fullName: 'Åse Source-ID', headline: 'Canonical engineer', phone: '+47 900 00 001', location: 'Oslo, Norge', + website: 'https://example.test/portfolio', linkedIn: 'https://www.linkedin.com/in/source-fixture', gitHub: 'https://github.com/source-fixture', + links: [{ label: 'Reviewed work', url: 'https://example.test/work' }] }, + summary: ['A source-backed professional summary.'], + jobs: [{ id: 'job-source', title: 'Canonical role', company: 'Nordlys AS', start: 'Jan 2020', end: 'Dec 2022', + bullets: ['Canonical work evidence.'], skills: ['C#'] }], + education: [{ id: 'education-source', qualification: 'Computer science', qualificationLevel: 'Bachelor', institution: 'Fixture University', + location: 'Oslo', start: 'Aug 2016', end: 'Jun 2019', details: ['Reviewed qualification.'] }], + projects: [{ id: 'project-source', name: 'Recorded project', role: 'Developer', location: 'Remote', start: '2023-01', end: '2023-12', + bullets: ['Reviewed project evidence.'], skills: ['React'] }], + certifications: [{ id: 'cert-source', name: 'Recorded certification', issuer: 'Fixture Academy', location: 'Remote', date: 'Jun 2022', + details: ['Reviewed certification detail.'] }], + skills: ['C#', 'Norsk'], languages: [{ name: 'Norwegian Sign Language', level: 'Professional working proficiency', notes: 'Reviewed language note.' }], + interests: ['Documented community work'], awards: ['Reviewed award'], publications: ['Reviewed publication'], + organisations: ['Reviewed organisation'], references: ['Available by owner agreement'], + otherSections: [{ title: 'Custom factual section', items: ['Recorded custom fact.', 'Another reviewed custom fact.'] }], + }; + await json(await page.request.put(`${apiUrl}/career/profile`, { headers: owner.headers, data: { profile, cvText: raw } })); + const before = await json(await page.request.get(`${apiUrl}/career/profile`)); + expect(sourceIds(before.profile)).toEqual({ jobs: ['job-source'], education: ['education-source'], projects: ['project-source'], certifications: ['cert-source'] }); + const company = await json<{ id: number }>(await page.request.post(`${apiUrl}/companies`, { headers: owner.headers, data: { name: 'Source-ID fixture AS' } }), 201); + const job = await json<{ id: number }>(await page.request.post(`${apiUrl}/jobapplications`, { headers: owner.headers, + data: { companyId: company.id, jobTitle: 'Source-ID preservation', status: 'Saved' } }), 201); + const retainedTitle = 'CV-only retained role'; + const retainedBullet = 'CV-only retained evidence'; + let selected = await json(await page.request.post(`${apiUrl}/cv/variants`, { headers: owner.headers, + data: { name: 'Selected source-ID CV', jobApplicationId: job.id, settings: { themeId: 'minimal', + overrides: { [before.profile.jobs[0].id!]: { title: retainedTitle, bullets: [retainedBullet] } } } } })); + const sibling = await json(await page.request.post(`${apiUrl}/cv/variants`, { headers: owner.headers, + data: { name: 'Untouched source-ID sibling', settings: { themeId: 'minimal' } } })); + const selectedHistoryBefore = await json(await page.request.get(`${apiUrl}/cv/variants/${selected.id}/versions`)); + const siblingHistoryBefore = await json(await page.request.get(`${apiUrl}/cv/variants/${sibling.id}/versions`)); + const selectedPreviewBefore = await json(await page.request.get(`${apiUrl}/cv/variants/${selected.id}/preview`)); + const siblingPreviewBefore = await json(await page.request.get(`${apiUrl}/cv/variants/${sibling.id}/preview`)); + expect(selectedPreviewBefore.html).toContain(retainedTitle); + expect(selectedPreviewBefore.html).toContain(retainedBullet); + expect(siblingPreviewBefore.html).toContain('Canonical role'); + expect((await page.request.put(`${apiUrl}/jobapplications/${job.id}/cv`, { headers: owner.headers, data: { variantId: selected.id } })).status()).toBe(200); + const packageSummary = await json<{ id: number }>(await page.request.post(`${apiUrl}/jobapplications/${job.id}/submitted-packages`, { headers: owner.headers })); + const packageUrl = `${apiUrl}/jobapplications/${job.id}/submitted-packages/${packageSummary.id}`; + const frozenBefore = await json(await page.request.get(packageUrl)); + // Linking the selected CV updates its timestamp during setup. The preservation + // baseline must include that setup mutation before the unrelated career edit. + selected = await json(await page.request.get(`${apiUrl}/cv/variants/${selected.id}`)); + + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto('/career?section=profile'); + const t = translations.en; + const phone = page.getByLabel(t.profileCvContactPhone, { exact: true }); + await expect(phone).toHaveValue(String(before.profile.contact.phone)); + await phone.fill('+47 900 00 002'); + const requestPromise = page.waitForRequest(request => request.url() === `${apiUrl}/career/profile` && request.method() === 'PUT'); + const responsePromise = page.waitForResponse(response => response.url() === `${apiUrl}/career/profile` && response.request().method() === 'PUT'); + await page.getByRole('button', { name: t.profileSaveChanges, exact: true }).focus(); + await page.keyboard.press('Enter'); + const savedRequest = await requestPromise; + const savedResponse = await responsePromise; + const savedStatus = savedResponse.status(); + const requested = savedRequest.postDataJSON() as { profile: CareerProfile; cvText: string }; + const after = await json(await page.request.get(`${apiUrl}/career/profile`)); + const selectedAfter = await json(await page.request.get(`${apiUrl}/cv/variants/${selected.id}`)); + const siblingAfter = await json(await page.request.get(`${apiUrl}/cv/variants/${sibling.id}`)); + const selectedHistoryAfter = await json(await page.request.get(`${apiUrl}/cv/variants/${selected.id}/versions`)); + const siblingHistoryAfter = await json(await page.request.get(`${apiUrl}/cv/variants/${sibling.id}/versions`)); + const selectedPreviewAfter = await json(await page.request.get(`${apiUrl}/cv/variants/${selected.id}/preview`)); + const siblingPreviewAfter = await json(await page.request.get(`${apiUrl}/cv/variants/${sibling.id}/preview`)); + const frozenAfter = await json(await page.request.get(packageUrl)); + + // Collect the persisted IDs AND effective override output before the first preservation + // assertion, so the RED attempt retains both consequences of the existing browser save. + await info.attach('native-career-source-id-readbacks', { body: JSON.stringify({ savedStatus, requested, + ids: { before: sourceIds(before.profile), requested: sourceIds(requested.profile), after: sourceIds(after.profile) }, + observed: { + requestedIdsEqual: JSON.stringify(sourceIds(requested.profile)) === JSON.stringify(sourceIds(before.profile)), + persistedIdsEqual: JSON.stringify(sourceIds(after.profile)) === JSON.stringify(sourceIds(before.profile)), + overrideTitleBefore: selectedPreviewBefore.html.includes(retainedTitle), overrideTitleAfter: selectedPreviewAfter.html.includes(retainedTitle), + overrideBulletBefore: selectedPreviewBefore.html.includes(retainedBullet), overrideBulletAfter: selectedPreviewAfter.html.includes(retainedBullet), + selectedDtoUnchanged: JSON.stringify(selectedAfter) === JSON.stringify(selected), siblingDtoUnchanged: JSON.stringify(siblingAfter) === JSON.stringify(sibling), + selectedHistoryUnchanged: JSON.stringify(selectedHistoryAfter) === JSON.stringify(selectedHistoryBefore), + siblingHistoryUnchanged: JSON.stringify(siblingHistoryAfter) === JSON.stringify(siblingHistoryBefore), + frozenDetailUnchanged: JSON.stringify(frozenAfter) === JSON.stringify(frozenBefore), + }, + canonical: { before, after }, selected: { before: selected, after: selectedAfter, historyBefore: selectedHistoryBefore, historyAfter: selectedHistoryAfter, + previewBefore: selectedPreviewBefore, previewAfter: selectedPreviewAfter }, + sibling: { before: sibling, after: siblingAfter, historyBefore: siblingHistoryBefore, historyAfter: siblingHistoryAfter, + previewBefore: siblingPreviewBefore, previewAfter: siblingPreviewAfter }, frozen: { before: frozenBefore, after: frozenAfter }, + qualification: 'Actual canonical browser Save and local SQLite HTTP readbacks. No PDF/model/provider call; frozen full-detail/HTML proof only, no new attachment-byte proof or concurrency-protection claim.' }), contentType: 'application/json' }); + await info.attach('native-career-source-id-editor', { body: await page.screenshot({ fullPage: true }), contentType: 'image/png' }); + expect(savedStatus).toBe(200); + expect(sourceIds(requested.profile)).toEqual(sourceIds(before.profile)); + expect(sourceIds(after.profile)).toEqual(sourceIds(before.profile)); + const { contact: beforeContact, ...nonContactBefore } = before.profile; + const { contact: afterContact, ...nonContactAfter } = after.profile; + expect(nonContactAfter).toEqual(nonContactBefore); + expect(afterContact).toEqual({ ...beforeContact, phone: '+47 900 00 002' }); + expect(requested.cvText).toBe(raw); + expect(after.cvText).toBe(raw); + expect(selectedAfter).toEqual(selected); + expect(siblingAfter).toEqual(sibling); + expect(selectedHistoryAfter).toEqual(selectedHistoryBefore); + expect(siblingHistoryAfter).toEqual(siblingHistoryBefore); + expect(selectedPreviewAfter.html).toContain(retainedTitle); + expect(selectedPreviewAfter.html).toContain(retainedBullet); + expect(siblingPreviewAfter.html).toContain('Canonical role'); + expect(siblingPreviewAfter.html).not.toContain(retainedTitle); + expect(frozenAfter).toEqual(frozenBefore); + await page.reload(); + await expect(page.getByLabel(t.profileCvContactPhone, { exact: true })).toHaveValue('+47 900 00 002'); +}); + +test('[P7-03 PRES-C01 C03 E05 E09] real HTTP bounds canonical last-writer saves and structured-history recovery without claiming stale-write protection', async ({ page, owner, playwright }, info) => { + test.setTimeout(90_000); + const initialProfile = { version: '1', contact: { fullName: 'Canonical recovery owner', headline: 'Initial source' }, + jobs: [{ id: 'recovery-source', title: 'Recorded role', company: 'Fixture AS', bullets: ['Recorded evidence.'] }], skills: ['Norsk'] }; + const initialRaw = 'Initial raw source — æøå\n'; + await json(await page.request.put(`${apiUrl}/career/profile`, { headers: owner.headers, data: { profile: initialProfile, cvText: initialRaw } })); + const staleSnapshot = await json(await page.request.get(`${apiUrl}/career/profile`)); + const initialHistory = await json(await page.request.get(`${apiUrl}/career/profile/versions`)); + expect(initialHistory.map(row => row.version)).toEqual([1]); + const secondSession = await playwright.request.newContext(); + const admin = await playwright.request.newContext(); + const other = await playwright.request.newContext(); + const anonymous = await playwright.request.newContext(); + try { + const secondOwner = await login(secondSession, owner.email); + expect(secondOwner.id).toBe(owner.id); + const secondSnapshot = await json(await secondSession.get(`${apiUrl}/career/profile`)); + expect(secondSnapshot).toEqual(staleSnapshot); + const remoteRaw = 'Remote current raw source — æøå\n'; + const remote = await json(await secondSession.put(`${apiUrl}/career/profile`, { headers: secondOwner.headers, + data: { profile: { ...secondSnapshot.profile, contact: { ...secondSnapshot.profile.contact, headline: 'Remote reviewed source' } }, cvText: remoteRaw } })); + const remoteHistory = await json(await page.request.get(`${apiUrl}/career/profile/versions`)); + expect(remoteHistory.map(row => row.version)).toEqual([2, 1]); + const currentRaw = 'Last writer raw source remains current after structured restore — æøå\n'; + const staleBody = { profile: { ...staleSnapshot.profile, contact: { ...staleSnapshot.profile.contact, headline: 'Stale snapshot accepted as last writer' } }, cvText: currentRaw }; + const staleWrite = await page.request.put(`${apiUrl}/career/profile`, { headers: owner.headers, data: staleBody }); + const staleStatus = staleWrite.status(); + const lastWriter = await json(staleWrite); + const afterStale = await json(await secondSession.get(`${apiUrl}/career/profile`)); + const historyAfterStale = await json(await secondSession.get(`${apiUrl}/career/profile/versions`)); + expect(staleStatus).toBe(200); + expect(staleBody).not.toHaveProperty('expectedVersion'); + expect(afterStale).toEqual(lastWriter); + expect(afterStale.profile.contact.headline).toBe('Stale snapshot accepted as last writer'); + expect(historyAfterStale.map(row => row.version)).toEqual([3, 2, 1]); + expect(historyMetadata(historyAfterStale.slice(1))).toEqual(historyMetadata(remoteHistory)); + const restored = await json(await secondSession.post(`${apiUrl}/career/profile/versions/2/restore`, { headers: secondOwner.headers })); + const recovered = await json(await page.request.get(`${apiUrl}/career/profile`)); + const restoredHistory = await json(await page.request.get(`${apiUrl}/career/profile/versions`)); + expect(restored.profile).toEqual(remote.profile); + expect(recovered).toEqual(restored); + expect(recovered.cvText).toBe(currentRaw); + expect(recovered.cvText).not.toBe(remoteRaw); + expect(restoredHistory.map(row => row.version)).toEqual([4, 3, 2, 1]); + expect(restoredHistory[0]).toMatchObject({ source: 'restore:v2', isCurrent: true }); + expect(restoredHistory.slice(1).every(row => !row.isCurrent)).toBe(true); + expect(historyMetadata(restoredHistory.slice(1))).toEqual(historyMetadata(historyAfterStale)); + expect((await page.request.post(`${apiUrl}/career/profile/versions/99999/restore`, { headers: owner.headers })).status()).toBe(404); + + const adminOwner = await login(admin, 'e2e@example.test'); + const otherOwner = await login(other, await createOwner(admin, adminOwner.headers)); + const otherBefore = await json(await other.get(`${apiUrl}/career/profile`)); + expect(await json(await other.get(`${apiUrl}/career/profile?ownerUserId=${encodeURIComponent(owner.id)}`))).toEqual(otherBefore); + expect(await json(await other.get(`${apiUrl}/career/profile/versions?ownerUserId=${encodeURIComponent(owner.id)}`))).toEqual([]); + expect((await other.post(`${apiUrl}/career/profile/versions/2/restore`, { headers: otherOwner.headers })).status()).toBe(404); + await json(await other.put(`${apiUrl}/career/profile`, { headers: otherOwner.headers, + data: { ownerUserId: owner.id, profile: { version: '1', contact: { fullName: 'Other account only' }, skills: ['Other owner fact'] }, cvText: 'Other owner raw source' } })); + expect((await json(await other.get(`${apiUrl}/career/profile`))).profile.contact.fullName).toBe('Other account only'); + expect((await anonymous.get(`${apiUrl}/career/profile`)).status()).toBe(401); + expect((await anonymous.get(`${apiUrl}/career/profile/versions`)).status()).toBe(401); + expect((await anonymous.put(`${apiUrl}/career/profile`, { data: staleBody })).status()).toBe(401); + expect((await anonymous.post(`${apiUrl}/career/profile/versions/2/restore`)).status()).toBe(401); + expect(await json(await page.request.get(`${apiUrl}/career/profile`))).toEqual(recovered); + expect(await json(await page.request.get(`${apiUrl}/career/profile/versions`))).toEqual(restoredHistory); + await info.attach('native-canonical-stale-contract-characterization', { body: JSON.stringify({ initial: staleSnapshot, remote, + staleRequest: staleBody, staleStatus, lastWriter: afterStale, historyAfterStale, recovered, restoredHistory, + ownerIsolation: { forgedOwnerQueryCannotReadForeign: true, foreignStructuredVersion404: true, forgedBodyWritesOnlyOwnProfile: true, anonymous401: true }, + qualification: 'Two real authenticated HTTP sessions in disposable SQLite. Canonical stale saves remain accepted last-writer replacements; history recovery appends a structured revision and does not restore raw cvText. No conflict prevention, browser draft-recovery, attachment-byte, model/provider or production acceptance is claimed.' }), contentType: 'application/json' }); + } finally { await secondSession.dispose(); await admin.dispose(); await other.dispose(); await anonymous.dispose(); } +}); diff --git a/job-tracker-ui/src/profile-page.test.tsx b/job-tracker-ui/src/profile-page.test.tsx index 3409afd..da85192 100644 --- a/job-tracker-ui/src/profile-page.test.tsx +++ b/job-tracker-ui/src/profile-page.test.tsx @@ -348,6 +348,17 @@ test('profile page loads persisted structured cv and can re-parse it', async () }); test('saving the career profile PUTs the structured profile and cv text unchanged (Phase 1 refactor invariant)', async () => { + const keyedProfile = { + ...structuredCv, + jobs: [{ ...structuredCv.jobs[0], id: 'recorded-job-id' }], + education: [{ id: 'recorded-education-id', qualification: 'Recorded degree', details: ['Recorded distinction'] }], + certifications: [{ id: 'recorded-certification-id', name: 'Recorded certification', details: ['Recorded detail'] }], + projects: [{ id: 'recorded-project-id', name: 'Recorded project', bullets: ['Recorded outcome'], skills: ['SQL'] }], + }; + const originalGet = mockedApi.get.getMockImplementation()!; + mockedApi.get.mockImplementation((url: string) => url === '/career/profile' + ? Promise.resolve({ data: { profile: keyedProfile, cvText: 'Professional Summary\nBuilt backend systems', completeness: { percent: 70, missing: [], sections: [] } } } as any) + : originalGet(url)); renderPage(); const saveButton = await screen.findByRole('button', { name: /save changes/i }); @@ -358,7 +369,13 @@ test('saving the career profile PUTs the structured profile and cv text unchange expect(mockedApi.put).toHaveBeenCalledWith( '/career/profile', expect.objectContaining({ - profile: expect.objectContaining({ contact: expect.objectContaining({ fullName: 'Demo User' }) }), + profile: expect.objectContaining({ + contact: expect.objectContaining({ fullName: 'Demo User' }), + jobs: [expect.objectContaining(keyedProfile.jobs[0])], + education: [expect.objectContaining(keyedProfile.education[0])], + certifications: [expect.objectContaining(keyedProfile.certifications[0])], + projects: [expect.objectContaining(keyedProfile.projects[0])], + }), cvText: 'Professional Summary\nBuilt backend systems', }), ); @@ -370,7 +387,7 @@ test('editing a field in an extracted section updates parent state and flows int // Renders existing data through the extracted PersonalInformationSection. const nameField = await screen.findByLabelText(/full name/i); - expect(nameField).toHaveValue('Demo User'); + await waitFor(() => expect(nameField).toHaveValue('Demo User')); // Editing the child field updates the parent's structuredCv (controlled input reflects it back). fireEvent.change(nameField, { target: { value: 'Edited Name' } }); diff --git a/job-tracker-ui/src/profileCv.test.ts b/job-tracker-ui/src/profileCv.test.ts new file mode 100644 index 0000000..dd2862e --- /dev/null +++ b/job-tracker-ui/src/profileCv.test.ts @@ -0,0 +1,75 @@ +import { normalizeStructuredCv, parseStructuredCvJson } from "./profileCv"; + +const keyedItems = [ + ["jobs", { id: "job:recorded-Æ_01", title: "Engineer", bullets: ["Recorded delivery"], skills: ["C#"] }], + ["education", { id: "education/server:key-02", qualification: "Recorded degree", details: ["Recorded distinction"] }], + ["certifications", { id: "certification:key-03", name: "Recorded certification", details: ["Recorded detail"] }], + ["projects", { id: "project:key-04", name: "Recorded project", bullets: ["Recorded outcome"], skills: ["SQL"] }], +] as const; + +test.each(keyedItems)("preserves the server item ID when normalizing %s", (collection, item) => { + const profile = normalizeStructuredCv({ [collection]: [item] }); + expect(profile[collection]).toHaveLength(1); + expect(profile[collection][0]).toMatchObject(item); + expect(parseStructuredCvJson(JSON.stringify(profile))[collection][0]).toMatchObject(item); +}); + +test("legacy structured items without IDs remain usable and acquire no client-generated IDs", () => { + const legacy = Object.fromEntries(keyedItems.map(([collection, item]) => { + const { id: _id, ...fields } = item; + return [collection, [fields]]; + })); + const profile = normalizeStructuredCv(legacy); + const serialized = JSON.parse(JSON.stringify(profile)); + for (const [collection] of keyedItems) { + expect(profile[collection]).toHaveLength(1); + expect(serialized[collection][0]).toMatchObject(legacy[collection][0]); + expect(serialized[collection][0]).not.toHaveProperty("id"); + } +}); + +test("legacy parsed sections keep their facts without inventing structured item IDs", () => { + const profile = parseStructuredCvJson(JSON.stringify([ + { name: "Professional Summary", content: "Recorded delivery\nRecorded support", wordCount: 4 }, + { name: "Skills", content: "C#, SQL", wordCount: 2 }, + { name: "Languages", content: "Norwegian: Native", wordCount: 2 }, + ])); + expect(profile.summary).toEqual(["Recorded delivery", "Recorded support"]); + expect(profile.skills).toEqual(["C#", "SQL"]); + expect(profile.languages).toEqual([{ name: "Norwegian", level: "Native", notes: undefined }]); + for (const [collection] of keyedItems) expect(profile[collection]).toEqual([]); +}); + +test("API null and missing numeric metadata remain absent rather than becoming zero", () => { + const inputs = [ + { metadata: { profileVersion: null, appliedExtractionRunId: null, fields: { "contact.fullName": { confidence: null, sourcePage: null } } } }, + { metadata: { fields: { "contact.fullName": {} } } }, + ]; + for (const input of inputs) { + for (const profile of [normalizeStructuredCv(input), parseStructuredCvJson(JSON.stringify(input))]) { + expect(profile.metadata.profileVersion).toBeUndefined(); + expect(profile.metadata.appliedExtractionRunId).toBeUndefined(); + expect(profile.metadata.fields["contact.fullName"].confidence).toBeUndefined(); + expect(profile.metadata.fields["contact.fullName"].sourcePage).toBeUndefined(); + const serialized = JSON.parse(JSON.stringify(profile)); + expect(serialized.metadata).not.toHaveProperty("profileVersion"); + expect(serialized.metadata).not.toHaveProperty("appliedExtractionRunId"); + expect(serialized.metadata.fields["contact.fullName"]).not.toHaveProperty("confidence"); + expect(serialized.metadata.fields["contact.fullName"]).not.toHaveProperty("sourcePage"); + } + } +}); + +test("zero, finite numbers and numeric strings keep the established metadata number conversion", () => { + for (const values of [[0, 0, 0, 0], [5, 3, 0.8, 2], ["6", "4", "0.65", "3"]]) { + const [profileVersion, appliedExtractionRunId, confidence, sourcePage] = values; + const input = { metadata: { profileVersion, appliedExtractionRunId, fields: { "contact.fullName": { confidence, sourcePage } } } }; + for (const profile of [normalizeStructuredCv(input), parseStructuredCvJson(JSON.stringify(input))]) { + expect(profile.metadata.profileVersion).toBe(Number(profileVersion)); + expect(profile.metadata.appliedExtractionRunId).toBe(Number(appliedExtractionRunId)); + expect(profile.metadata.fields["contact.fullName"].confidence).toBe(Number(confidence)); + expect(profile.metadata.fields["contact.fullName"].sourcePage).toBe(Number(sourcePage)); + } + } +}); + diff --git a/job-tracker-ui/src/profileCv.ts b/job-tracker-ui/src/profileCv.ts index b661666..5e56a68 100644 --- a/job-tracker-ui/src/profileCv.ts +++ b/job-tracker-ui/src/profileCv.ts @@ -34,6 +34,7 @@ export type StructuredCvContact = { }; export type StructuredCvJob = { + id?: string; title?: string; company?: string; location?: string; @@ -45,6 +46,7 @@ export type StructuredCvJob = { }; export type StructuredCvEducation = { + id?: string; qualification?: string; qualificationLevel?: string; institution?: string; @@ -55,6 +57,7 @@ export type StructuredCvEducation = { }; export type StructuredCvCertification = { + id?: string; name?: string; issuer?: string; location?: string; @@ -63,6 +66,7 @@ export type StructuredCvCertification = { }; export type StructuredCvProject = { + id?: string; name?: string; role?: string; location?: string; @@ -211,15 +215,15 @@ export function normalizeStructuredCv(value: unknown): StructuredCvProfile { const normalized: StructuredCvProfile = { version: normalizeString(source.version) ?? "1", metadata: { - profileVersion: Number.isFinite(Number(source.metadata?.profileVersion)) ? Number(source.metadata.profileVersion) : undefined, - appliedExtractionRunId: Number.isFinite(Number(source.metadata?.appliedExtractionRunId)) ? Number(source.metadata.appliedExtractionRunId) : undefined, + profileVersion: source.metadata?.profileVersion != null && Number.isFinite(Number(source.metadata.profileVersion)) ? Number(source.metadata.profileVersion) : undefined, + appliedExtractionRunId: source.metadata?.appliedExtractionRunId != null && Number.isFinite(Number(source.metadata.appliedExtractionRunId)) ? Number(source.metadata.appliedExtractionRunId) : undefined, updatedAtUtc: normalizeString(source.metadata?.updatedAtUtc), fields: source.metadata?.fields && typeof source.metadata.fields === "object" ? Object.fromEntries(Object.entries(source.metadata.fields as Record).map(([key, value]) => [key, { - confidence: Number.isFinite(Number(value?.confidence)) ? Number(value.confidence) : undefined, + confidence: value?.confidence != null && Number.isFinite(Number(value.confidence)) ? Number(value.confidence) : undefined, method: normalizeString(value?.method), sourceSnippet: normalizeString(value?.sourceSnippet), - sourcePage: Number.isFinite(Number(value?.sourcePage)) ? Number(value.sourcePage) : undefined, + sourcePage: value?.sourcePage != null && Number.isFinite(Number(value.sourcePage)) ? Number(value.sourcePage) : undefined, sourceBlockId: normalizeString(value?.sourceBlockId), reviewState: normalizeString(value?.reviewState), lastUpdatedAtUtc: normalizeString(value?.lastUpdatedAtUtc), @@ -240,6 +244,7 @@ export function normalizeStructuredCv(value: unknown): StructuredCvProfile { summary: normalizeList(source.summary), jobs: Array.isArray(source.jobs) ? source.jobs.map((job: any) => ({ + id: typeof job?.id === "string" ? job.id : undefined, title: normalizeString(job?.title), company: normalizeString(job?.company), location: normalizeString(job?.location), @@ -252,6 +257,7 @@ export function normalizeStructuredCv(value: unknown): StructuredCvProfile { : [], education: Array.isArray(source.education) ? source.education.map((education: any) => ({ + id: typeof education?.id === "string" ? education.id : undefined, qualification: normalizeString(education?.qualification), qualificationLevel: normalizeString(education?.qualificationLevel), institution: normalizeString(education?.institution), @@ -263,6 +269,7 @@ export function normalizeStructuredCv(value: unknown): StructuredCvProfile { : [], certifications: Array.isArray(source.certifications) ? source.certifications.map((certification: any) => ({ + id: typeof certification?.id === "string" ? certification.id : undefined, name: normalizeString(certification?.name), issuer: normalizeString(certification?.issuer), location: normalizeString(certification?.location), @@ -272,6 +279,7 @@ export function normalizeStructuredCv(value: unknown): StructuredCvProfile { : [], projects: Array.isArray(source.projects) ? source.projects.map((project: any) => ({ + id: typeof project?.id === "string" ? project.id : undefined, name: normalizeString(project?.name), role: normalizeString(project?.role), location: normalizeString(project?.location),