diff --git a/docs/ui-modernisation/AI_SETTINGS_VALIDATION.md b/docs/ui-modernisation/AI_SETTINGS_VALIDATION.md new file mode 100644 index 00000000..ac285fa0 --- /dev/null +++ b/docs/ui-modernisation/AI_SETTINGS_VALIDATION.md @@ -0,0 +1,31 @@ +# A3-IM08 AI and automation validation + +3 November 2026. Owner approved **"Approve calendar/documents/mail and A3-IM08"**. Isolated `codex/a3-ui-08` starts at accepted IM07 `fba80ef346bc021e675024638dacf9ccef7243db`, with published acceptance receipt `e5a979386d6377138e7ea7fd44958adb22838886`. First bounded context fix `a88310481fbfa7701478043e8bf192ee45c7c28e` is published and independently remotely verified. Its immutable source/evidence record remains `AI_CONTEXT_VALIDATION.md` at that commit. + +## Result and preservation + +Settings now has an Automation entry on desktop and mobile, using existing notification preference state and its explicit Save action. Its email-reminder switch is the same persisted preference shown in Notifications; changing sections preserves drafts. Links lead to AI privacy/usage, follow-up thresholds and individual saved-search alerts. Keyboard activation of the AI link focuses the existing settings group. Existing numeric section values and routes remain stable. + +The copy follows actual service contracts: optional email delivery checks roughly every six hours, confirmed account address, at most one email per application per day. Six day thresholds influence reminders and optional Ghosted status processing; they are not pause switches. Per-search alerts and AI privacy have their existing owners. No workers, providers or backlog orchestration were activated or configured. + +Section AI proposals now invalidate when context or section name changes, for pending responses and displayed reviews. Whole-document proposals now invalidate when output language changes, without generating again or applying the old result. A Pro account without AI entitlement sees manual-editing guidance and a Settings link instead of an upgrade prompt. Free-plan upgrade behavior and session dismissal remain intact. + +The existing Career Profile owner, CV null-as-inherit settings, save queue, undo/history, revision preconditions, opaque proposal token and explicit review/apply remain authoritative. UI language stays separate from document output language. No renderer, API, schema, dependency, model configuration or provider permissions changed. Reverting IM08 source commits restores prior presentation; no database rollback is required. + +## Evidence + +- **131 distinct frontend cases across eight suites PASSED**. This is the union of Automation45, whole-document studio60, section assistant23, and notice/catalogue6 with three catalogue cases overlapping Automation45. Reports are under `evidence/ai-settings/frontend` and the published `evidence/ai-context/a3-ai-context-green.json`. Older baseline58, parent59, pilot and independent-review reruns are not extra cases. Studio tests emit existing direct-focus React act warnings; this is not a warning-free test claim. +- **68 local backend cases PASSED**, no failures/skips: notification settings, tenant-bound worker fixtures, AI privacy policy, usage metering and CV AI readiness. Native TRX under `evidence/ai-settings/backend`. InMemory/temp SQLite and mocked/captured providers; no MariaDB, model inference, real email or hosted CI qualification. +- **16 controlled browser journeys and96 scoped axe scans/captures PASSED**. EN/NB, light/dark,320/390/768/1440. Final report is `evidence/ai-settings/browser/BROWSER.json`; capture refreshes overlap the same cases. Final captures wait for instant scroll-to-top; phones use viewport captures, tablets/desktop full-page captures. Representative phone EN/light and desktop NB/dark images were visually inspected. Six states exercise saved reminder preference, AI preference disabled, manual CV save without inference, proposal review, language-change discard and explicit token apply. Each journey intercepts five mutations and two proposal responses. No canonical-profile write is accepted by the fixture. Actual API/model responses are synthetic; this is not backend end-to-end or semantic AI/translation acceptance. +- Typecheck, full ESLint, static-export build and scoped browser-script lint PASSED. One initial import-casing error failed build/typecheck and was corrected to tracked `accountPlan`; subsequent checks passed. Initial browser pilot failed because a Select accessible name includes its value; selector corrected, pilot passed. An earlier unavailable export server and an accidental wrong test-runner invocation are not test evidence; package files are unchanged. +- Independent source review found the same import-casing issue, corrected before final build. No remaining findings in shared drafts/save guards, AI focus, entitlement presentation or language invalidation. Its27 selected tests overlap the131 total. Final harness review found no actionable issues in interception or count assertions. AST-only graph refresh completed; optional SQL parser and symbol-less-file limits remain explicit. Generated graph stays local. + +Red regressions remain available: context/name changes four failures before the fix; document-language one failure; missing Automation contract three failures; paid-plan notice two failures. Filtered cases were not executed in those red runs. Initial capture/pilot reports do not inflate final coverage. + +## Open qualifications and next gate + +Granular user pause for automatic Ghosted status processing is not represented by the existing six-number rules contract. It remains a capability gap; no fake switch or silent schema expansion was introduced. Existing AI preference changes are reflected by server-backed entitlement hydration on a full page reload, as exercised here. The card does not currently refresh the mounted App entitlement context after saving, so internal navigation alone can retain stale presentation until reload; backend enforcement remains authoritative. This existing UX gap is OPEN. Reusing the auth-changed event blindly would set authResolved false and risks unmounting drafts; investigate a safe refresh separately. This increment adds no new session or entitlement authority. + +NOT RUN: live models, semantic output quality, paid/real providers, physical PDF, native device/screen reader, full integrated security, recovery/restore, hosted CI or production checks. Complete European localisation, Phase10 acceptance, Global Jobs dependencies, public launch and release readiness remain open. Root security policy remains on its isolated security branch. + +The approved implementation proposal requires **Gate F: owner milestone review before the next increment**. After final publication/readback, request acceptance of IM08 and progression to IM09 account/session/connections/data/admin/processing presentation, preserving RBAC, owner isolation, last-admin/session safeguards and explicit destructive-action confirmation. No main merge, deployment, live-model activation or additional provider authority is included. diff --git a/docs/ui-modernisation/UI-08.md b/docs/ui-modernisation/UI-08.md index 616745af..b5dcfc0b 100644 --- a/docs/ui-modernisation/UI-08.md +++ b/docs/ui-modernisation/UI-08.md @@ -4,11 +4,11 @@ - [x] Inspect SettingsView, rules/notification owners, AI privacy/usage and contextual section-assistant callers. - [x] Initial selected baseline:58 cases/5 suites passed, not blanket AI quality or full roadmap acceptance. -- [ ] Contextual assistance: preserve manual editing, source/document-language separation, explicit review/apply, stale-input discard, quota/consent/failure/retry/close. Investigate context and section-name changes while a proposal is pending or under review. -- [ ] Settings automation: expose current supported controls and explain effects/timing/disable behavior under Settings; preserve existing rules drafts and notification/AI preference writers. Inspect actual worker/data contracts before promising independent per-rule switches not represented in current six numeric thresholds. No fake controls, worker activation or policy/infrastructure change. -- [ ] Scoped EN/NB, responsive/focus/accessibility presentation; types/lint/build, controlled browser and applicable local backend tests; independent review. +- [x] Contextual assistance: context/section-name invalidation published at a8831048; output-language invalidation reproduced and fixed. Manual editing, explicit review/token apply, source/document-language separation and existing quota/consent/failure/retry/close retained. +- [x] Settings Automation entry exposes the existing persisted email-reminder switch and links to AI privacy, numeric follow-up thresholds and individual saved-search alerts. Shared drafts and preference writers retained. Service timing/disable limits are explicit; granular Ghosted processing pause remains a data-contract gap, not a fake control. +- [x] Scoped EN/NB, responsive/focus/accessibility presentation;131 distinct frontend cases/eight suites,68 local backend cases,16 controlled journeys/96 scoped scans. Types/full lint/build and independent review passed after correcting an import-casing error. Capture reruns overlap, not extra coverage. See AI_SETTINGS_VALIDATION.md. - [ ] Publish validated checkpoints and exact evidence; update durable handoff. Next Gate F before IM09 account/session/connections/admin/processing views. -Current source findings:rules expose only six integer day thresholds1–365, not independent enable flags; email-follow-up notifications and AI/privacy preferences have actual existing boolean controls. Do not represent thresholds as disable switches or imply a general worker-control API. Contextual assistant invalidation currently covers source text, target ID, language and entitlement; generation also consumes context and sectionName, which need compatibility review. +Remaining source limitation:rules expose only six integer day thresholds1–365, not independent enable flags; email-follow-up notifications and AI/privacy preferences have actual existing boolean controls. Do not represent thresholds as disable switches or imply a general worker-control API. A Pro account with unavailable AI now receives manual-editing/settings guidance while free-tier upgrade behavior remains intact. No schema/dependency/migration planned for presentation and bounded stale-proposal fix. Existing canonical Career Profile, CV/letter history/settings, RD21, per-owner data, quota/consent and server review/apply stay authoritative. Rollback reverts this UI increment; no database rollback. Full integrated AI/security/native/provider/release qualifications remain separate. diff --git a/docs/ui-modernisation/evidence/ai-settings/CHECKS.json b/docs/ui-modernisation/evidence/ai-settings/CHECKS.json new file mode 100644 index 00000000..f779a8de --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/CHECKS.json @@ -0,0 +1,15 @@ +{ + "date": "2026-11-03", + "branch": "codex/a3-ui-08", + "base": "e5a979386d6377138e7ea7fd44958adb22838886", + "publishedContextFix": "a88310481fbfa7701478043e8bf192ee45c7c28e", + "frontend": { "status": "PASSED", "distinctCases": 131, "suites": 8, "union": "45 Automation + 60 studio + 23 assistant + 6 notice/catalogue - 3 overlapping catalogue", "warnings": "Existing direct-focus React act warnings in studio tests; not warning-free." }, + "backend": { "status": "PASSED", "cases": 68, "failed": 0, "notExecuted": 0, "classes": ["NotificationSettingsControllerTests", "BackgroundWorkerTenantTests", "AiPrivacyPolicyTests", "AiUsageMeterTests", "CvAiReadinessTests"], "environment": "InMemory/temp SQLite; mocked/captured providers, no real model or email." }, + "typecheck": { "command": "npm run typecheck", "status": "PASSED", "initialFailure": "Incorrect AccountPlan import casing; corrected to tracked accountPlan." }, + "lint": { "command": "npm run lint", "status": "PASSED" }, + "build": { "command": "npm run build", "status": "PASSED", "initialFailure": "Incorrect AccountPlan import casing; corrected before passing static export." }, + "browser": { "command": "node scripts/verify-a3-ai-settings.mjs", "status": "PASSED", "distinctJourneys": 16, "distinctScans": 96, "configuration": "320/390/768/1440 x EN/NB x light/dark", "mutations": "80 intercepted fixture writes", "proposals": "32 synthetic proposal responses", "overlap": "Pilot and capture refreshes repeat these same conditions; do not add them to the distinct totals." }, + "independentReview": { "status": "PASSED_AFTER_CORRECTION", "source": "Import-casing finding corrected; no remaining findings.", "harness": "No actionable findings; interception and exact nonzero count assertions reviewed.", "reruns": "27 tests overlap the frontend total." }, + "notRun": ["Original real-backend Settings e2e specs", "MariaDB/hosted CI", "Live models/semantic AI or translation quality", "Provider activation/real email", "Physical PDF/native devices/screen readers", "Full integrated security/recovery/release/production qualification"], + "limitations": ["Six numeric rules thresholds do not support per-user Ghosted processing pause.", "Final entitlement refresh remains server-backed; no new authority or model activation.", "Optional SQL graph parser absent; 144 files yielded no graph symbols.", "Wrong test-runner invocation and an unavailable export server produced no qualifying test evidence; package files unchanged."] +} diff --git a/docs/ui-modernisation/evidence/ai-settings/SOURCE_MANIFEST.json b/docs/ui-modernisation/evidence/ai-settings/SOURCE_MANIFEST.json new file mode 100644 index 00000000..75f6d72b --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/SOURCE_MANIFEST.json @@ -0,0 +1,233 @@ +{ + "base": "e5a979386d6377138e7ea7fd44958adb22838886", + "policy": "LF-normalised text, raw PNG SHA256", + "sources": { + "job-tracker-ui/src/components/SettingsView.tsx": "a7416d754027ccf0fe108b17c2417d0218b332e43df9d65b57c6e6bbc731e007", + "job-tracker-ui/src/components/AiPrivacySettingsCard.tsx": "32b63b8bf85cd20576952e93bf4b9cf449a8389a2969bad9fe58bc584abc3868", + "job-tracker-ui/src/components/AiUsageCard.tsx": "1c6c081c360b8f628bb7f0f7cf9bf6e730358c37734c47c2f300acab2802ba54", + "job-tracker-ui/src/components/RulesSettingsCard.tsx": "969c389ba1581293509853fd5a41a60a9b569ef0d23eafd7f2fc0077ca25d922", + "job-tracker-ui/src/components/ProFeatureNotice.tsx": "72503e24463ca12661c21b860a2a86b1b27f0615b696221c3f603d7dddfe282a", + "job-tracker-ui/src/components/cv/AiSectionAssistant.tsx": "40475ae87da5a1966bdd52a5107b4c54e34a28a4be31687dc5471217105c4d7a", + "job-tracker-ui/src/views/CvBuilderEditor.tsx": "ee9cad661cd85591c7e8bfad084f15ec033e7791c987b6afaeee8a58526909fb", + "job-tracker-ui/src/i18n/translations.ts": "d41b8a0a8eedd9e53e0f6ffe22bae32bef88493fdc9d72309603019b9d757ec2", + "job-tracker-ui/src/accountPlan.tsx": "37e21dd83f277a18f1b593f2c379846ed0517e78f069a34a9e23549a88ae0511", + "job-tracker-ui/src/App.tsx": "a176e52d81c4b6ded63c5f38cb27e853aa09312f2cc45fc7e5b5e44573e0fef3", + "job-tracker-ui/src/settings-view.test.tsx": "21461bffbf5ec684889900e12731334b15bf16ef1e8949e2c3b273774ae0f92d", + "job-tracker-ui/src/settings-import-lifetime.test.tsx": "24af2a5954533087ddbff40659ff9f8dcf70805435dca772314c2be7d8bf6133", + "job-tracker-ui/src/ai-privacy-settings.test.tsx": "a53eda1c305cc9e3ab16a4f52603a8cb6d881aa58e88a22e112eb33103c5a404", + "job-tracker-ui/src/ai-usage-card.test.tsx": "b894953ab331341c0920aa71b667eb7c30659da95744cafcbbf825f35eef7d02", + "job-tracker-ui/src/translation-catalogue.test.ts": "f20e8099f2c4dda76574ea3ed1e95b743eef5da82507d7cbc3f9925d52356b98", + "job-tracker-ui/src/pro-feature-notice.test.tsx": "514e2094aeff267e95be302e29271576a4e36487dba14063d04df95fe24def47", + "job-tracker-ui/src/ai-section-assistant.test.tsx": "bcf642a670c5b2741ba8dd46fbf1b1f231c4801b4f1c8bebec6eab6dabd31396", + "job-tracker-ui/src/cv-builder-deep-link.test.tsx": "a612b6bfeb6ce9d8cade323b3237f389c4255e55e294752aaf23e96f9cc97039", + "job-tracker-ui/e2e/phase7-settings-preferences.spec.ts": "4ea0de6562a476ae3d8c4732cddd730241e1e6dbea752543242542de2edef677", + "job-tracker-ui/e2e/settings-page-layout.spec.ts": "564469c82a5dccc0d99a81964fbd2ad0115947d8d840280e6bb8f80b0b947b4e", + "job-tracker-ui/scripts/verify-a3-ai-settings.mjs": "7001bbea1e54833e2fa205d2e0fb135cd2a9ea637deffb3706904a7a8094abc3", + "job-tracker-ui/package.json": "3745394e406cefa40d30a87e840bccb359be147bac6ffba736e2ae90898a8626", + "job-tracker-ui/package-lock.json": "bf31e90d7af03e8af059db2aaf893925b9e8881a30a1688034ed88ef45d4fcab", + "docs/ui-modernisation/UI-08.md": "f52ebdb2f6b51304223aa9f17dc0e58f8ccf9c3033e00023c94ccc68da27fd86", + "docs/ui-modernisation/AI_SETTINGS_VALIDATION.md": "52afabc9adc12d8d3af2534e8ad389a4bd9afdd69fed6cae1e98b8ffc197900d", + "JobTrackerApi.Tests/AiPrivacyPolicyTests.cs": "4d3bafe9dfba41b4fb3aa86b47f7785460e7d05523c5411394bb4783aec09c9b", + "JobTrackerApi.Tests/AiUsageMeterTests.cs": "d74da4e8a6d334e90cb85806715e56d5e0646ce5b1f002e7d307bc5140f7b3c3", + "JobTrackerApi.Tests/BackgroundWorkerTenantTests.cs": "3ccba5b6c77275f6f0fbb2c26973e57c45523ff93cff604d82d9f0b710bcbadb", + "JobTrackerApi.Tests/CvAiReadinessTests.cs": "0cb080aa20981c2a980bd5d85401773e6b1943400fe0b6eb8fae0900b7fb81ff", + "JobTrackerApi.Tests/NotificationSettingsControllerTests.cs": "9dc9849425b71adda0ce64b404a6edd02d0389a1f6ee42561fea32e008e6103c", + "JobTrackerApi/Controllers/NotificationSettingsController.cs": "101130256b15432e41a32312f67bfa2f147c556e996869fced036cba92ad9517", + "JobTrackerApi/Controllers/AiSettingsController.cs": "32611dd8e4e928478d9691676d15fdc6bbc26c9416c2a7c823fe88198378af3e", + "JobTrackerApi/Services/AiPrivacyPolicy.cs": "f88360d8c631c7ffc7646e3647e569f2ff697c2b98fb3e7605c6bf75b29b79db", + "JobTrackerApi/Services/RulesHostedService.cs": "2e2eb32614c302d0c2093f1835e7290bd9ff83450c6f792cb0cec78fc6e20bb5", + "JobTrackerApi/Services/FollowUpReminderHostedService.cs": "7166eb611e134472718f451b0ac94ca55dcb75d251a1dec7b447447fe4cad1f0" + }, + "evidence": { + "backend/a3-ai-settings.trx": "c8e62df86b0b4b8a4057fa77118795ee499ee8154e0486b2428cdd145ae5914b", + "browser/ai-disabled-en-dark-1440.png": "b8e623a347cd7bf789e12b8dedd0d667d3ae726835b0f00072659479cee34be2", + "browser/ai-disabled-en-dark-320.png": "4a1e55710c5ac056eb2695d5866aa0f3226ef85bb400cf217b5a3849d4aa82c8", + "browser/ai-disabled-en-dark-390.png": "af7f444be624cf8ebdba167c9b6ac5ff0e41a89804f60908fd714afe09e196c9", + "browser/ai-disabled-en-dark-768.png": "cfdc5cc254505fb14ee5bc76a99f66c15f8358ff727b8c97cd0b9644718bafaa", + "browser/ai-disabled-en-light-1440.png": "217d2b69cea6607664760c64f4d1da576239e16ba71791c575e0927b968ef49a", + "browser/ai-disabled-en-light-320.png": "34c2e1c53abd2a5b642613f5309122e1be3bfc631c9e10768e6c4cf19489e45a", + "browser/ai-disabled-en-light-390.png": "b67f45eed9148f20821cad2ac502b3dcddd472cd3ab30bbf271427ddf082c5b4", + "browser/ai-disabled-en-light-768.png": "9409d1187bcb4dc724682939be8b324720da4dadfbb6ec3bdb76defaafaf2e47", + "browser/ai-disabled-nb-dark-1440.png": "f3287ca40e3016521086fab3ce52d58f2d9cc3d86559604345973ec2b188f25f", + "browser/ai-disabled-nb-dark-320.png": "6fd597ed8c3aec1dcbe5b476ca92262e9c663b33c1c7bae056f50ee52d56e669", + "browser/ai-disabled-nb-dark-390.png": "a390c6b9f21c4b02b1148ebab4844720798f65f7b6e143141b66377509c90587", + "browser/ai-disabled-nb-dark-768.png": "1d8c718747d80202b8813cc1e23a9c21787fdacd1b0b358e5b0cbacc3e182fcb", + "browser/ai-disabled-nb-light-1440.png": "2b110a6b945c2ebde126c050b25a81e5f9e2edf6ba9c2ef87467bcd13279c64f", + "browser/ai-disabled-nb-light-320.png": "bacbf5f1ffee5ca7b77ec5c03e19ed0cf26366a1258fef9936fd717b54831dd2", + "browser/ai-disabled-nb-light-390.png": "ebc1a7f7834b5f0d11d89fa27127de5843720542ea41d8d1453914f8999cc0a4", + "browser/ai-disabled-nb-light-768.png": "cee901de6a98b7951126a547c75726f71640bed81ea8b9cf752a82f84650d621", + "browser/ai-review-en-dark-1440.png": "813132f2bf2e5175436587004dcf2c97a6e05e71ff667db011b8b8e7133a06e8", + "browser/ai-review-en-dark-320.png": "4aa17b023a325772b5cfcf65c671ac5538c32a9bc3d0df6113e976eb755904f9", + "browser/ai-review-en-dark-390.png": "a6d419db6ba6350f5fb2873042022d7025c8bc5873ecc8a854678bc6f5e2454b", + "browser/ai-review-en-dark-768.png": "4bef5f4410d56c37bbe451e93ff470c97691e96e33fd98a365e7f54bb3e75529", + "browser/ai-review-en-light-1440.png": "fa66a0f49bb5d6cd017018228279b5807d698bb231b561a33054db866d89ab77", + "browser/ai-review-en-light-320.png": "9c19c24e98f30576185f841fbc69a560c7a6867b77f78bbc6735911ab9bbd810", + "browser/ai-review-en-light-390.png": "09f3186b3fe88e469b560a4133d7e50dfa5854ff8ea571684e62fe229dfa9d3d", + "browser/ai-review-en-light-768.png": "e2c3f55e588a1e290260eb53b5f9b78cdcae647ed1bfba0ad295eace0787f3de", + "browser/ai-review-nb-dark-1440.png": "84a6dc039e6e7a67fbdd5a6a67e019b9ac9a2a37f77e87e183a2a8fea8bc8834", + "browser/ai-review-nb-dark-320.png": "b7d65d5d529f401f6ff72117a33030f8e009c942d7f353e27aa13451bb98623d", + "browser/ai-review-nb-dark-390.png": "1cfff2924646728d30e85e6b63266d5938d1e084353fd202526c7186e744454d", + "browser/ai-review-nb-dark-768.png": "30fc8aaed961add5c13ae35ce5df6b11ea38f6538dc6188931e55c041317376c", + "browser/ai-review-nb-light-1440.png": "05acf5d4e400050dfa46179d4d66e2fa7b67c3fe046373d106dbe32d961d81cc", + "browser/ai-review-nb-light-320.png": "f43f7fff823059d92083a2caa71ef3b3304d41d609fafa5b878b8647414b910d", + "browser/ai-review-nb-light-390.png": "8efc147a5514e14e39e8d08d4d6c592b12a55cf4692a9bc4ec540e78ba118da9", + "browser/ai-review-nb-light-768.png": "436d236b560193b60722a043606f6b80c856b7b4f5df7ff4e09153690777b9ba", + "browser/automation-en-dark-1440.png": "fcd0c567c9cc2308d88cdf208ca9efdab3b51753f0df1a4af1ac15b77a1c4c1f", + "browser/automation-en-dark-320.png": "f8d2b98ae34662efb402d09cf00b521fac27d57d86b7e58dd55a938102b42d01", + "browser/automation-en-dark-390.png": "1164a1c6a433ae36a93f01cf13020929f9de2be8d851f1e7eaa7cee7495af340", + "browser/automation-en-dark-768.png": "1e7e11a67a8a14c5bfdbe10745977dd3b6829a46578046071cdb4d5b5f8cdff4", + "browser/automation-en-light-1440.png": "2ae7a75677054da57254e0a542ab91d70c0120e67d928401c58225942b2bcd8b", + "browser/automation-en-light-320.png": "101ca0259d64f95291336525872ca83b3211b15e8a916bdf237cb3b13ddf88ac", + "browser/automation-en-light-390.png": "53a9acb832edb687c5623e047e16f61178487a4fbb501000fddf3aede9543734", + "browser/automation-en-light-768.png": "5590a1f411e226fc77318dfe970b355bb4e31741fd5c9fa809b8566d319b5119", + "browser/automation-nb-dark-1440.png": "02392395f2d782b2cb29791b5b2fa09752bf44ccc26f8c2e226601eb3f255dbd", + "browser/automation-nb-dark-320.png": "119569450c8fb138c05b629ea3519582307c3151ee817295788d64b406eb0048", + "browser/automation-nb-dark-390.png": "ed54c340d4c6106e410870e8c34bafa01ae633164c388470beac991ac7384dd5", + "browser/automation-nb-dark-768.png": "dc0ec849781acdd57b5f756033e85a5d4b5297345fedbcda0af44676a66010c4", + "browser/automation-nb-light-1440.png": "1063a281a92549c7b484f898d99c50662803dd54ebc57950297226be5ac4f6d9", + "browser/automation-nb-light-320.png": "2a85c706eae447b79dd6b3e3e530e02fe0e8fffde27db9a30f63029a8808bc06", + "browser/automation-nb-light-390.png": "977183745324452aaac36bea7cec35b1ec9d482c800df331e7e36aa5a5b2dff0", + "browser/automation-nb-light-768.png": "4ec1a37b763bff457a379cdf2f04a08a2d9ef2d76a3174f7295844b72018e825", + "browser/BROWSER-BEFORE-CAPTURE-NORMALISATION.json": "312cbbf436f2e46fdadece4bfafea89a7409541c7f0a6f0277f6d2fe8cda3fd6", + "browser/BROWSER.json": "312cbbf436f2e46fdadece4bfafea89a7409541c7f0a6f0277f6d2fe8cda3fd6", + "browser/explicit-apply-en-dark-1440.png": "28e9646b5e5f8146f4bf5380543e10162714063279e4b338873bc2d7bf623b35", + "browser/explicit-apply-en-dark-320.png": "30d0978e846005b66ea2fbf0d31e5bf782bb3180c02b7de43c84ac18f6cc487c", + "browser/explicit-apply-en-dark-390.png": "538132cc23ac653b384a88d2490804066f0496eb64931aabfa45652b17820e84", + "browser/explicit-apply-en-dark-768.png": "7a97df34a743f12e07a382e9ab7721dcd6a2e9acc80940342d696c4c57137dfd", + "browser/explicit-apply-en-light-1440.png": "90e5777d5c5066aa0996dc052a2fe162f4bd8059e2b7756f4ef9ac2795163492", + "browser/explicit-apply-en-light-320.png": "55f4f848bbd8cce5e3c7e15c5900af4eaa7a9ef5041e5fcc53d2926cdfeb00f0", + "browser/explicit-apply-en-light-390.png": "ad2c00866e638932feb357c9727dff7fa39069779cd64ee03493be09006ee4db", + "browser/explicit-apply-en-light-768.png": "c960791ed6721e9c10c2eb4ab2873ab149af2d111ac73a1559e5b4204b2a3c6b", + "browser/explicit-apply-nb-dark-1440.png": "881b3edda9380aec0eeaa4389dbb0c297010430824b5c042667def344f479f73", + "browser/explicit-apply-nb-dark-320.png": "b347e9d7c82bbd27092c6ddee689ec4560f3b46e62c461759bbfa5f18c9ad24f", + "browser/explicit-apply-nb-dark-390.png": "550f791634beb07cb6bd37b35233252da83f47ae4ed941d4771cd3d401d83094", + "browser/explicit-apply-nb-dark-768.png": "03880e69728d425f3236bedeac5afcbd68283d1d0853b6b1cb5c57d7f57f8c11", + "browser/explicit-apply-nb-light-1440.png": "edc360d33502d2833d4ee503517c4a8d55c76a7eab1c37567c2f809285a265e3", + "browser/explicit-apply-nb-light-320.png": "8feed702c56acd002bf8898e605a0be33858467a2b9ba6fba8fe4170ba271a11", + "browser/explicit-apply-nb-light-390.png": "0677d84a4cf792983651318ec434978d6ca4a32debacdc9ee50dc08ab36b0d4f", + "browser/explicit-apply-nb-light-768.png": "a7757beb694150bfea50272087bdf226e14b970d55d0b9ec33e039124a1876fb", + "browser/language-discard-en-dark-1440.png": "a63f1716cfee7dca8f55896965db6a576248032719f50fe2be169b269b7192e6", + "browser/language-discard-en-dark-320.png": "7b40f0119a3cebe34018068de93a8410fac659d3667f4b99370884475429b0ed", + "browser/language-discard-en-dark-390.png": "7cc2ef66c255594b8b09b88afb2cd7633baccab9e961394cb7a7ef6e2a58a0e7", + "browser/language-discard-en-dark-768.png": "eca82ce9b4471fb795d482d8c80d1b3c4ec3e37040fd8e8da34bfa0bf8bd0ff4", + "browser/language-discard-en-light-1440.png": "3e5a864a12e96ae2ea14e224b6bea132e55afe2281bec7310f1a6d46e6ebd602", + "browser/language-discard-en-light-320.png": "d47d83f1f06a6b3cfee95d166cde3eb0691d303b1429321cca6a9a944627d3de", + "browser/language-discard-en-light-390.png": "60c38f2e28a925e80e9747975fa5f81392376f3fb39e12f5e21db559c81b83f4", + "browser/language-discard-en-light-768.png": "9278e19cf731025c155c49822be7b860818149a77c9b2af5b66617785edd1f16", + "browser/language-discard-nb-dark-1440.png": "ba4fc4f75dacb00dbb59877f381be66207987e500ae328250ebd973c81bd0012", + "browser/language-discard-nb-dark-320.png": "8aa750c53162f1d3a5604ed0249cac15089efcc7686686023ac8996c6103fb53", + "browser/language-discard-nb-dark-390.png": "8b9dc5adfc06bc721a6ad23e77c5cd142936d15f3dfa0224845a9980f872d223", + "browser/language-discard-nb-dark-768.png": "9b1d33fbfdf8c9a905a80c4a83f07cead1fbfbe6fa88146c33941b2a46f16966", + "browser/language-discard-nb-light-1440.png": "ccb7911758aead08482542642ede99803242335e5015c204546977fe6cff8af8", + "browser/language-discard-nb-light-320.png": "f16ce139a8a770fe1ffb697c48228f81a61c826ac842cafd4527570b07a0d218", + "browser/language-discard-nb-light-390.png": "236c26153968dbc83c1fc88c95e1a80129d9de24db4149d6e96011e3d9a1a1af", + "browser/language-discard-nb-light-768.png": "c23848a638950dd605e415a122c7d8f46add7ececfcad59555c4a6f1570226a3", + "browser/manual-fallback-en-dark-1440.png": "5624131a8ede6fcc4ad5918f6af6128249a858ab3d6f0fb46a48557a097840dd", + "browser/manual-fallback-en-dark-320.png": "f1c5487faf7c095af4646182c585505f1064a90c29374486c2342a643b8f1f6a", + "browser/manual-fallback-en-dark-390.png": "a9881ec752c64636834fd9af54187d048464459be29be5cd147b847972aed117", + "browser/manual-fallback-en-dark-768.png": "2b63e9edef62630e79ed2256e1cce80d024a92ad691ba9e9ef0b8a2f70cde222", + "browser/manual-fallback-en-light-1440.png": "333c9fb53db3ea1b572e49f7a7feccbf8b0aa6a716e2f77bf44dda4a45b194e0", + "browser/manual-fallback-en-light-320.png": "66badc525f324b5ad90f41ae6c69ef40367bfd9c4a2a265810166ceb640c039c", + "browser/manual-fallback-en-light-390.png": "81f4551a7d6a4afe41d4a18c1028c816e0d4b7757b1a4276ca105043a97cb0cf", + "browser/manual-fallback-en-light-768.png": "9836087d9f4b08d1eb561bba5cb3742f656d18084e3fbd511974d7b41f9568fc", + "browser/manual-fallback-nb-dark-1440.png": "ac3f77edefd88a4d981c2f7df3a1bd5dd38876257b63bf71be19772e6c550b8a", + "browser/manual-fallback-nb-dark-320.png": "e3f62792a3c7ff07b1ee87e4cc0f3a172de1f1a9cd1207c02844387af9e41c38", + "browser/manual-fallback-nb-dark-390.png": "633959d488024ddadc996e56c2d572ac3af0866656047940c961b3cc4790b4e4", + "browser/manual-fallback-nb-dark-768.png": "071cef4abdc294111649f60319198d29a64a40603ca822a4b7a0661754ec5419", + "browser/manual-fallback-nb-light-1440.png": "9f96f9a2d78f1275d1ff6aafe20ad8128ff326c9ba3acabf48b113d8abcded77", + "browser/manual-fallback-nb-light-320.png": "7a088d27ac7244be5bfa9ed4169014d31abf535caa5f1bdc8ecb207f0afe1058", + "browser/manual-fallback-nb-light-390.png": "de6db8906a6b714618cc02c0189b56e37de630c23f0ece4933aead9d5143a80b", + "browser/manual-fallback-nb-light-768.png": "ff393ebdab93706c9bdd10bbcaebe0be201b897da8b4a38fba49224cca3d5609", + "browser/PILOT-INITIAL.json": "fffd4116bfa2f49d79ce5f2f20171d2c329c2a03c5761cf17d90c6eec392ede5", + "browser/PILOT.json": "6f8d2315f581035eb75fc81810bc047575f4e88c3e5684d37204667b942f93ee", + "CHECKS.json": "22223359847755ca0b9d99ed53d6764b62d6913903d6ccdaf06c19dc3c11b88c", + "frontend/a3-ai-notice-red.json": "d084189d58211accf431f7836ec4cf0f28730901a8750810a1e07006a3220c98", + "frontend/a3-ai-notice-tests.json": "462ed8dfb06cb89a6822257c6adcfd4f6fed17e51c812f33682db1d0488f57d9", + "frontend/a3-automation-red.json": "cb9132707fbb7f77d1f56661355d84a1d7c8dea85d6809e540ba00cf61b3254d", + "frontend/a3-automation-tests.json": "8afb46dc3a8ea5eb5dab6a6f2853731ea6e36b178976e3240064ba0fa1805fc5", + "frontend/a3-document-ai-language-red.json": "777d390e7e35072706e310f8286c52df5038effce42ae2ca5e3dcb76951c46cc", + "frontend/a3-document-ai-language-tests.json": "cee6f87cad31b8b9a32d88d15061a514a8eb6b248e125123d4663bc119273388" + }, + "export": { + "404.html": "0cf63dd2f060ea1eab3bc0fa8f9e5daf1ba46d5db73f34aac59987ff4a8bb124", + "__next.__PAGE__.txt": "50a493b1b4ff05f480d22a4202fc8aa438264c5be96bd9a9cea08aae18aebdbf", + "__next._full.txt": "b9ff0bc85c77e020d3d77f03790250785ca7dbb0a9c655fdd26ef0f627df4680", + "__next._tree.txt": "b7455bba1e4d6928b6de6770cbbad0dd8b3e2a1a025c33a8b42f04a4a3ad0a4d", + "_next/static/chunks/0-_aq6ipzcshj.js": "39f90c215bf52aef6274ed3dcc0f8af32e21a37fe8845b3bca0d6ea60da6a8c2", + "_next/static/chunks/000fqw4ou6pgt.js": "bc5a2bc2899224e7629ab70670860e52697f71eae5f4935e80e63f63eabed87f", + "_next/static/chunks/0ah1fzqmie05a.js": "5c65505a7dcbac63ac71d254e619a4c800943bfb4fa16cd40c10cdbe7e9b6e31", + "_next/static/chunks/0bdt7ln111t48.js": "6184b1a61f22e2a640c17941634fdc75678ce93d142848d9f07f163e0d1fd201", + "_next/static/chunks/0bwvt3mysnclc.js": "7705667a1b75812b7833d9c9dff47fe023015e58e382c40f4507d9948c973af4", + "_next/static/chunks/0cz1d0mv5g_q7.js": "0973c1d64c88adc8e3c950410cb58b288f72118d5965b78049438deb8f2f9683", + "_next/static/chunks/0gamdsp7ql8cu.js": "f641cd9e2957f5c01234df02211a085f8e8fe2009cf84817e4143f3c477e1dc2", + "_next/static/chunks/0h_-smu-bk788.js": "970ef0fa47ce6dfff261c624e08054841b6969b4afc5b0ebfad89126d7543bbc", + "_next/static/chunks/0jcvc3qm6-lyk.js": "7c27e1fe373b822adc68c63096a5bf38444ad605b9743f0920271652989c56f1", + "_next/static/chunks/0lpz-x0nc-gyb.js": "4d900c4168865d653fb0f1e93a1851bd185486f46447095d34ff2cc2284f9dfa", + "_next/static/chunks/0q1wd_b10phzr.js": "307f4a4ed0f1ef2d87b9de51dbcac2382a39aa8bab359994ee7aa41529215b4e", + "_next/static/chunks/0q20g9o8x-k8z.js": "3d4d9086985419aa8866b032158196c774acb8bf318f3c8245508c8daa9c5148", + "_next/static/chunks/0q_pwu9jxv4-d.js": "42a43b3d7245a413c7c29b4cbe87823037a6dbc637e2e282c92405470e0f575d", + "_next/static/chunks/0yg1x7i96lj87.js": "2aad3c0f9e8b7b5a5123a2a439970c49db0be353236e22f9b6eafaaf01328c15", + "_next/static/chunks/0yst6obzycohr.js": "9a7613ed81e0b5e9dd45d551d30c59b881139034580cbbf4aaac700921a6d3d1", + "_next/static/chunks/11-48p8kygxgp.js": "57eb9059599b5a5a30598d0a334912d58af571c0ffe28448ca76ad77c8ea8df9", + "_next/static/chunks/14-lfugawba2w.js": "6a5780ca3c84d7f130f3c0a14431c85c7a1e799e2645b8c171161dab40a64360", + "_next/static/chunks/1435in_k_-dhc.js": "4757476512d5c4dd25f9264a18b304ed4824b23aff1c09e134fcbff21d9c36b6", + "_next/static/chunks/145oicobmjvm7.js": "d6bbbdeed1381652dc7412e5ce673a077579ecd5cee8934cb6b533c814098764", + "_next/static/chunks/14e7ovj0s3elm.js": "070567dd4d23fb9fa0b9ba132185a697af6578045d43b2b1c7bbb2a1594d935d", + "_next/static/chunks/16lfece6cnlln.js": "716363ba044f30b0e70440756b4e5eafa2d25f2e1628e855e3bc4ab9eabee3d3", + "_next/static/chunks/19zh-dmyml5oj.js": "2ab304f9b4155cdbac4d22e1b0b56b1c1f775c4bbb3ee93c425e297182bf522e", + "_next/static/chunks/1d0xrdyyzw7qc.js": "c11668ff1e152008e0d7b4454af12eb36c97df46a5860938e2eb5d8429b374a8", + "_next/static/chunks/1ke8pzecwofrg.css": "32e9ab963ebadebcbe2c68dffb24cfbfc8cc24255ad91b48b7941fc777bf7439", + "_next/static/chunks/1m4qrvmbq_fq9.js": "4d36c8ec83dc817f273178dc22f329ab026578075f58de68b6f133bcf911a8a1", + "_next/static/chunks/1req80b9jj38r.js": "eee4d2e3789e1215195dba99ad0f09d34f8c83da848322b76054722233e9dae3", + "_next/static/chunks/1xn023_28rgzj.js": "4f7f2108d030a48d039930736c92a55710975dddf419fe673f84d92899b1f575", + "_next/static/chunks/1xwc-b795syag.css": "f73c002233f931ca14d0ae58815c47ca9f2659f25b1547a6d1fdca12a2a00b3f", + "_next/static/chunks/1zi8i6dnxiac_.js": "8aea28bbe6a138e5d4b619429ca71570883a7aee974b86d5a4a746d90f704dbc", + "_next/static/chunks/22wx8--1b9tnq.js": "3f7d8e762371262c6a740b4dac21725b424847319afac46055e97074a99ff5f5", + "_next/static/chunks/2b2nivoqiaper.js": "f20a0bfbfc4fd335a0e8fa6abf552d24c94a81a2b01690fad1ea088c22fd2086", + "_next/static/chunks/2b49wlharl6fd.js": "40619f8a5a03fc7479b0679717b1e5ec0dea0a1944ce77f4ce9d29d2486fdb5c", + "_next/static/chunks/2br3ad_-bc7k9.js": "80fa55f7a32db4d743fda36747c36994fde00a0f53f2eb25b2a6d07c6fb97cd7", + "_next/static/chunks/2dmc6iqxm14fz.js": "3b20898e0cde315c48d6fd46abd562269bbf73c850528a4be2cfc2b9aa0c8f5e", + "_next/static/chunks/2ghgf2s9b2iou.js": "23d8ff31e2128d0541c1887785fb75885323fea7c5d4f35826513b75c12c2ae3", + "_next/static/chunks/2itnratrnd9c5.js": "8be0b191c2d54f7233ebf2f1e169b3bfef680fa93da21c08d8c43b05c3ec174f", + "_next/static/chunks/2kpcazmi6n6mk.js": "bea0de681fceff50056bfeccc5d035aff54d20918288051cb64bb259edd250c7", + "_next/static/chunks/2s2gjr6ro25dj.js": "7489e2ac285a05b563c2bcb4eaf9274bf930f2a7385f17d6d5e6850064b88b10", + "_next/static/chunks/2u5qve004opku.js": "be388d9a6aa423082bafb4584c3facc65ddfed71bcfa5c1d06b097b408c5ff97", + "_next/static/chunks/2z42el0b2mp8_.js": "86ff990ef32c90c4839583e4f1d1bcbddb165dad3141b9fcd2ecec67f4ff24b8", + "_next/static/chunks/2z9e_b61gtc22.js": "b9d717dad26828438d4ff56cabca41a8055f5eaa54420fd0aeb6b4ba7d5baa0d", + "_next/static/chunks/31n24zcvyae0y.js": "110921bad10425af1d689cb939d97be75c7c0af9c35f8b16c5ff237db6fce893", + "_next/static/chunks/32_ah983ce851.js": "0c3cd0d2a5ad789e31226a9ea0506c50016804311a58548c7784b7b45aaecd14", + "_next/static/chunks/3329nxgnx3721.js": "ceedc7c69bf0617733b65bbf9f6a682a5d53177d4e8fdb86b8982cda2175f232", + "_next/static/chunks/357yqeklh7414.js": "0192ab7198ebbe299d34a934c504dd4b562d1cccebb6e9d4c5163930c881b14c", + "_next/static/chunks/3721l8sfm8icl.js": "06b67611b3a93515a375b803b54fe7063c049824f1ebf5c7f7db8701b5091e7c", + "_next/static/chunks/3ad6g1hxq589h.js": "6ac2de4fa0366167a95bb14f4847bc8f7227eb7e23abab34d62b884664153ded", + "_next/static/chunks/3bqn9b34na0b9.js": "f1b8ebcc1b22251c33c9f3a5d11c1f893cad2da2e8744a441e790f7347aa9e73", + "_next/static/chunks/3ckk_j5ril9ag.js": "87f631dae7b648d32171e9e05a3e000753ecb54f8d3b86a4401c0e4ab4d73553", + "_next/static/chunks/3gkylew_qn7cw.js": "7e6c74c81be0c41ab433e36d65b914f62c48f332922e27f7cc953476f4dd78cb", + "_next/static/chunks/3la4obitihzpv.js": "9a5a57b46db389b98f1fd5baa86eba1a360300dae9d1ff3ffeae7bc3378135b9", + "_next/static/chunks/3q4v10rrqy40n.js": "d87ff7b7a0f07d0d92eab3876481eb686a12d9c43d8b92cbe406aefa227a11c1", + "_next/static/chunks/3u61o8t7m_jza.js": "86231c12e0f8cacc8638bed0bc4b34f645fc35e60de342dc154d3cce0c9a5afa", + "_next/static/chunks/40y_aqqilokr2.js": "1f5a5260316134d6bffe949400752ee6b42addf908ae714ef4ae4ebde916dddd", + "_next/static/chunks/43b5x8qjjh3ax.js": "6ee7261cf9a63e0e6ea181bbb09125e09948588b6e10b5c02727c686a6062a3a", + "_next/static/chunks/442d7ylb3po0z.js": "d95cedfbdcd00c674fd718cbbf391ec01c0728018b0db2461a06df7074049132", + "_next/static/chunks/turbopack-25fzg9ay_1ss-.js": "c40f39e993a30c96d6247bb3a7b581538bb046efe8ef8ec07bea3ba32291750f", + "_next/static/pXb0nCm833Ye4Wwj4s328/_buildManifest.js": "9476e0afd3f9da68a64e6ec58631191fd3eaca62c9f5a377e7517fe9a89e59ea", + "_next/static/pXb0nCm833Ye4Wwj4s328/_clientMiddlewareManifest.js": "5483e3295dc35dfe29ea932efc85341c916f10ff78ff5b0e965e003710893a4a", + "_next/static/pXb0nCm833Ye4Wwj4s328/_ssgManifest.js": "678f6ce2cb80b1fe72fc67e7412be6e2ab6ada083111b64f7c40d35e3cba5e00", + "_not-found/__next._full.txt": "580fef17cab8f107e51dc34a9ebd9e2ab3deb05bff63799713559353997cc3e7", + "_not-found/__next._not-found/__PAGE__.txt": "aad469db7c4f7eddae1d549b32efebae77c3639cad36b7ec011d6d2f7fb1b90f", + "_not-found/__next._tree.txt": "e4806d6655dd97942ced49641e856609e35821e18e530689e9b5fb2d6de26161", + "_not-found.html": "0cf63dd2f060ea1eab3bc0fa8f9e5daf1ba46d5db73f34aac59987ff4a8bb124", + "_not-found.txt": "580fef17cab8f107e51dc34a9ebd9e2ab3deb05bff63799713559353997cc3e7", + "favicon.ico": "8d4923e2c487805ea9f852a685b2cf0fb10512ded8290d2a5c37d1cc8fd0702a", + "favicon.svg": "63ecf8f37f8bb146ecfae3917187c6b692d4e801641e8a314486a4007912f3a3", + "index.html": "fda82f5f1cd89ec78fe7f57a9e696b2529b05a307fdfeabb8abf211e8acacbab", + "index.txt": "b9ff0bc85c77e020d3d77f03790250785ca7dbb0a9c655fdd26ef0f627df4680", + "logo192.png": "bc652031597fabd19b9f14e22a71f809490d218037521b3b64d013418c1390b4", + "logo512.png": "5129e9bc1ba812b711fd9a646d3a38a906d365a26ee685df183b8752458944d4", + "manifest.json": "2667ce63c2e0835b7007239816a5597639321d333da396a78638dfa9e8a7c935", + "mockups/dashboard.svg": "318be3adb1324c26eb30f05572a29528a3e38331c6a604652eef75b54f8c29dc", + "mockups/pipeline.svg": "db2ef41faabeb90e7ce85413e168581686c54535d970fc7d8deda3888a479de4", + "mockups/workspace.svg": "9bbab22349147c7b01d6e18c93c622a6f8aed6dedaf23715189ab54d60e1ddbd", + "robots.txt": "e5ab0d231eeb01b4a982d1c79a6729cac9797ad15a69247e4f28ba6afc149b4c" + } +} diff --git a/docs/ui-modernisation/evidence/ai-settings/backend/a3-ai-settings.trx b/docs/ui-modernisation/evidence/ai-settings/backend/a3-ai-settings.trx new file mode 100644 index 00000000..950c306d --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/backend/a3-ai-settings.trx @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 9.0.19) +[xUnit.net 00:00:00.29] Discovering: JobTrackerApi.Tests +[xUnit.net 00:00:00.51] Discovered: JobTrackerApi.Tests +[xUnit.net 00:00:00.52] Starting: JobTrackerApi.Tests +[xUnit.net 00:00:08.48] Finished: JobTrackerApi.Tests + + + + \ No newline at end of file diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/BROWSER-BEFORE-CAPTURE-NORMALISATION.json b/docs/ui-modernisation/evidence/ai-settings/browser/BROWSER-BEFORE-CAPTURE-NORMALISATION.json new file mode 100644 index 00000000..47da9a14 --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/browser/BROWSER-BEFORE-CAPTURE-NORMALISATION.json @@ -0,0 +1,1636 @@ +{ + "screens": [ + { + "width": 320, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + } + ], + "journeys": [ + { + "width": 320, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + } + ], + "errors": [], + "unexpectedWrites": [], + "writes": [ + { + "width": 320, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + } + ], + "proposals": [ + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + } + ], + "unavailableReads": [ + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies" + ], + "blockedExternal": [ + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com" + ], + "limits": [ + "All API, AI and preview results are synthetic fixtures. No model activation, semantic translation quality, backend end-to-end or physical PDF qualification.", + "No native device, screen reader, provider, integrated security, deployment or release acceptance." + ] +} \ No newline at end of file diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/BROWSER.json b/docs/ui-modernisation/evidence/ai-settings/browser/BROWSER.json new file mode 100644 index 00000000..47da9a14 --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/browser/BROWSER.json @@ -0,0 +1,1636 @@ +{ + "screens": [ + { + "width": 320, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "state": "explicit-apply", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "automation", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "ai-review", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "language-discard", + "violations": [] + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "state": "explicit-apply", + "violations": [] + } + ], + "journeys": [ + { + "width": 320, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + } + ], + "errors": [], + "unexpectedWrites": [], + "writes": [ + { + "width": 320, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "action": "explicitAiApply" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "notificationPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "manualCvSave" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "aiPreference" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "action": "explicitAiApply" + } + ], + "proposals": [ + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 390, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 768, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "en", + "mode": "dark", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "nb", + "mode": "light", + "outputLanguage": "nb-NO" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "outputLanguage": "en" + }, + { + "width": 1440, + "language": "nb", + "mode": "dark", + "outputLanguage": "nb-NO" + } + ], + "unavailableReads": [ + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies" + ], + "blockedExternal": [ + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com" + ], + "limits": [ + "All API, AI and preview results are synthetic fixtures. No model activation, semantic translation quality, backend end-to-end or physical PDF qualification.", + "No native device, screen reader, provider, integrated security, deployment or release acceptance." + ] +} \ No newline at end of file diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/PILOT-INITIAL.json b/docs/ui-modernisation/evidence/ai-settings/browser/PILOT-INITIAL.json new file mode 100644 index 00000000..4e81119b --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/browser/PILOT-INITIAL.json @@ -0,0 +1,85 @@ +{ + "screens": [ + { + "width": 320, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + } + ], + "journeys": [], + "errors": [], + "unexpectedWrites": [], + "writes": [ + { + "width": 320, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + } + ], + "proposals": [ + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "en" + } + ], + "unavailableReads": [ + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies" + ], + "blockedExternal": [ + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com" + ], + "limits": [ + "All API, AI and preview results are synthetic fixtures. No model activation, semantic translation quality, backend end-to-end or physical PDF qualification.", + "No native device, screen reader, provider, integrated security, deployment or release acceptance." + ] +} \ No newline at end of file diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/PILOT.json b/docs/ui-modernisation/evidence/ai-settings/browser/PILOT.json new file mode 100644 index 00000000..506f776e --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/browser/PILOT.json @@ -0,0 +1,121 @@ +{ + "screens": [ + { + "width": 320, + "language": "en", + "mode": "light", + "state": "automation", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-disabled", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "manual-fallback", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "ai-review", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "language-discard", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "explicit-apply", + "violations": [] + } + ], + "journeys": [ + { + "width": 320, + "language": "en", + "mode": "light", + "manualFallback": "PASS", + "languageDiscardWithoutApply": "PASS", + "explicitTokenApply": "PASS", + "aiSettingsKeyboardFocus": "PASS" + } + ], + "errors": [], + "unexpectedWrites": [], + "writes": [ + { + "width": 320, + "language": "en", + "mode": "light", + "action": "notificationPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "manualCvSave" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "aiPreference" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "action": "explicitAiApply" + } + ], + "proposals": [ + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "en" + }, + { + "width": 320, + "language": "en", + "mode": "light", + "outputLanguage": "nb-NO" + } + ], + "unavailableReads": [ + "/api/companies", + "/api/companies", + "/api/companies", + "/api/companies" + ], + "blockedExternal": [ + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com" + ], + "limits": [ + "All API, AI and preview results are synthetic fixtures. No model activation, semantic translation quality, backend end-to-end or physical PDF qualification.", + "No native device, screen reader, provider, integrated security, deployment or release acceptance." + ] +} \ No newline at end of file diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-1440.png new file mode 100644 index 00000000..5c088e08 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-320.png new file mode 100644 index 00000000..7fab849c Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-390.png new file mode 100644 index 00000000..cc6f784e Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-768.png new file mode 100644 index 00000000..1a1f6739 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-1440.png new file mode 100644 index 00000000..77926762 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-320.png new file mode 100644 index 00000000..891fbc0d Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-390.png new file mode 100644 index 00000000..6477d7b2 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-768.png new file mode 100644 index 00000000..680ab274 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-en-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-1440.png new file mode 100644 index 00000000..4892b1b0 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-320.png new file mode 100644 index 00000000..0f380026 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-390.png new file mode 100644 index 00000000..31b5973b Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-768.png new file mode 100644 index 00000000..4f2eec98 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-1440.png new file mode 100644 index 00000000..6a8936f4 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-320.png new file mode 100644 index 00000000..afe8d0ba Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-390.png new file mode 100644 index 00000000..6b3b8df4 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-768.png new file mode 100644 index 00000000..8522a964 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-disabled-nb-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-1440.png new file mode 100644 index 00000000..82358ab3 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-320.png new file mode 100644 index 00000000..df7046fe Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-390.png new file mode 100644 index 00000000..aa2476ef Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-768.png new file mode 100644 index 00000000..a07a873f Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-1440.png new file mode 100644 index 00000000..7caddc91 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-320.png new file mode 100644 index 00000000..f02fda01 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-390.png new file mode 100644 index 00000000..d432f035 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-768.png new file mode 100644 index 00000000..edd1dbb9 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-en-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-1440.png new file mode 100644 index 00000000..d02a5666 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-320.png new file mode 100644 index 00000000..e3a70db1 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-390.png new file mode 100644 index 00000000..f7636ed3 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-768.png new file mode 100644 index 00000000..b657b852 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-1440.png new file mode 100644 index 00000000..c8c97174 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-320.png new file mode 100644 index 00000000..e3350440 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-390.png new file mode 100644 index 00000000..3e03dc51 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-768.png new file mode 100644 index 00000000..a367e48e Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/ai-review-nb-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-1440.png new file mode 100644 index 00000000..9a53522b Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-320.png new file mode 100644 index 00000000..d860876f Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-390.png new file mode 100644 index 00000000..015d2586 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-768.png new file mode 100644 index 00000000..7f765bb5 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-1440.png new file mode 100644 index 00000000..330d7cf3 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-320.png new file mode 100644 index 00000000..9f72736e Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-390.png new file mode 100644 index 00000000..bdc5d110 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-768.png new file mode 100644 index 00000000..c0b00edc Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-en-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-1440.png new file mode 100644 index 00000000..eb945a23 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-320.png new file mode 100644 index 00000000..93cb7db0 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-390.png new file mode 100644 index 00000000..c8ff4adb Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-768.png new file mode 100644 index 00000000..d3eec47d Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-1440.png new file mode 100644 index 00000000..b1dfab42 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-320.png new file mode 100644 index 00000000..fbcc778c Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-390.png new file mode 100644 index 00000000..3f199464 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-768.png new file mode 100644 index 00000000..9c6e9f94 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/automation-nb-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-1440.png new file mode 100644 index 00000000..39f25d9d Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-320.png new file mode 100644 index 00000000..44b5a3bc Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-390.png new file mode 100644 index 00000000..74c38635 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-768.png new file mode 100644 index 00000000..b9ee2249 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-1440.png new file mode 100644 index 00000000..e0def2f9 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-320.png new file mode 100644 index 00000000..ee7304ea Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-390.png new file mode 100644 index 00000000..7ce1ddaa Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-768.png new file mode 100644 index 00000000..677318e6 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-en-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-1440.png new file mode 100644 index 00000000..ccf19781 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-320.png new file mode 100644 index 00000000..d7ff3d86 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-390.png new file mode 100644 index 00000000..0a6d0ac6 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-768.png new file mode 100644 index 00000000..6fe0f029 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-1440.png new file mode 100644 index 00000000..f20b71b3 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-320.png new file mode 100644 index 00000000..529b2a94 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-390.png new file mode 100644 index 00000000..8c26d1ad Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-768.png new file mode 100644 index 00000000..2282b1d5 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/explicit-apply-nb-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-1440.png new file mode 100644 index 00000000..ef8579c7 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-320.png new file mode 100644 index 00000000..126b43c6 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-390.png new file mode 100644 index 00000000..cc53d65b Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-768.png new file mode 100644 index 00000000..c949c492 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-1440.png new file mode 100644 index 00000000..e238fc63 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-320.png new file mode 100644 index 00000000..a599e0b1 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-390.png new file mode 100644 index 00000000..2e02fe00 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-768.png new file mode 100644 index 00000000..6e009011 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-en-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-1440.png new file mode 100644 index 00000000..3b5fbb72 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-320.png new file mode 100644 index 00000000..feec65e4 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-390.png new file mode 100644 index 00000000..bab32ed4 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-768.png new file mode 100644 index 00000000..bda3565c Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-1440.png new file mode 100644 index 00000000..57f5e7db Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-320.png new file mode 100644 index 00000000..7781811c Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-390.png new file mode 100644 index 00000000..39410936 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-768.png new file mode 100644 index 00000000..c661bd1f Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/language-discard-nb-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-1440.png new file mode 100644 index 00000000..a4254828 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-320.png new file mode 100644 index 00000000..7aca67d8 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-390.png new file mode 100644 index 00000000..0c8a3431 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-768.png new file mode 100644 index 00000000..26ac527c Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-1440.png new file mode 100644 index 00000000..224d7eef Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-320.png new file mode 100644 index 00000000..162b5b49 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-390.png new file mode 100644 index 00000000..19b0aec4 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-768.png new file mode 100644 index 00000000..b4526bc5 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-en-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-1440.png new file mode 100644 index 00000000..d4428381 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-320.png new file mode 100644 index 00000000..c7f10add Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-390.png new file mode 100644 index 00000000..7ebdd392 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-768.png new file mode 100644 index 00000000..35331c62 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-dark-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-1440.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-1440.png new file mode 100644 index 00000000..ce189915 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-1440.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-320.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-320.png new file mode 100644 index 00000000..3729f797 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-320.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-390.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-390.png new file mode 100644 index 00000000..5fe54725 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-390.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-768.png b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-768.png new file mode 100644 index 00000000..ce9e1dc6 Binary files /dev/null and b/docs/ui-modernisation/evidence/ai-settings/browser/manual-fallback-nb-light-768.png differ diff --git a/docs/ui-modernisation/evidence/ai-settings/frontend/a3-ai-notice-red.json b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-ai-notice-red.json new file mode 100644 index 00000000..5547def6 --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-ai-notice-red.json @@ -0,0 +1 @@ +{"numFailedTestSuites":1,"numFailedTests":2,"numPassedTestSuites":0,"numPassedTests":1,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":1,"numTotalTests":3,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793729306588,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":76,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Unable to find an element with the text: AI assistance is unavailable. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mUpgrade prompt\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[0m \u001b[0m\n \u001b[0mUpgrade body\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mView Pro\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\u001b[36m\u001b[39m\n at Object.getElementError (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\config.js:37:19)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:76:38\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:52:17\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:95:19\n at getByText (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\pro-feature-notice.test.tsx:23:17)\n at Object. (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"keeps paid users on the manual path without an upgrade prompt (en)","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793729321804,"status":"failed","title":"keeps paid users on the manual path without an upgrade prompt (en)"},{"ancestorTitles":[],"duration":12,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Unable to find an element with the text: KI-hjelp er utilgjengelig. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mUpgrade prompt\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[0m \u001b[0m\n \u001b[0mUpgrade body\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSe Pro\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\u001b[36m\u001b[39m\n at Object.getElementError (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\config.js:37:19)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:76:38\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:52:17\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:95:19\n at getByText (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\pro-feature-notice.test.tsx:23:17)\n at Object. (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"keeps paid users on the manual path without an upgrade prompt (nb)","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793729321896,"status":"failed","title":"keeps paid users on the manual path without an upgrade prompt (nb)"},{"ancestorTitles":[],"duration":109,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"shows a respectful upgrade action and remembers dismissal for the session","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793729321909,"status":"passed","title":"shows a respectful upgrade action and remembers dismissal for the session"}],"endTime":1793729322037,"message":" ● keeps paid users on the manual path without an upgrade prompt (en)\n\n TestingLibraryElementError: Unable to find an element with the text: AI assistance is unavailable. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mUpgrade prompt\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[0m \u001b[0m\n \u001b[0mUpgrade body\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mView Pro\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\n 21 | ,\n 22 | );\n > 23 | expect(screen.getByText(title)).toBeInTheDocument();\n | ^\n 24 | expect(screen.getByRole(\"link\", { name: action })).toHaveAttribute(\"href\", \"/settings\");\n 25 | expect(screen.queryByText(\"Upgrade body\")).not.toBeInTheDocument();\n 26 | fireEvent.click(screen.getByRole(\"button\", { name: new RegExp(title) }));\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at node_modules/@testing-library/dom/dist/query-helpers.js:76:38\n at node_modules/@testing-library/dom/dist/query-helpers.js:52:17\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at getByText (src/pro-feature-notice.test.tsx:23:17)\n\n ● keeps paid users on the manual path without an upgrade prompt (nb)\n\n TestingLibraryElementError: Unable to find an element with the text: KI-hjelp er utilgjengelig. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mUpgrade prompt\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[0m \u001b[0m\n \u001b[0mUpgrade body\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSe Pro\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\n 21 | ,\n 22 | );\n > 23 | expect(screen.getByText(title)).toBeInTheDocument();\n | ^\n 24 | expect(screen.getByRole(\"link\", { name: action })).toHaveAttribute(\"href\", \"/settings\");\n 25 | expect(screen.queryByText(\"Upgrade body\")).not.toBeInTheDocument();\n 26 | fireEvent.click(screen.getByRole(\"button\", { name: new RegExp(title) }));\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at node_modules/@testing-library/dom/dist/query-helpers.js:76:38\n at node_modules/@testing-library/dom/dist/query-helpers.js:52:17\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at getByText (src/pro-feature-notice.test.tsx:23:17)\n","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\pro-feature-notice.test.tsx","startTime":1793729309478,"status":"failed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/evidence/ai-settings/frontend/a3-ai-notice-tests.json b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-ai-notice-tests.json new file mode 100644 index 00000000..9a7755b8 --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-ai-notice-tests.json @@ -0,0 +1 @@ +{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":2,"numPassedTests":6,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":2,"numTotalTests":6,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793729337837,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":139,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps paid users on the manual path without an upgrade prompt (en)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793729343257,"status":"passed","title":"keeps paid users on the manual path without an upgrade prompt (en)"},{"ancestorTitles":[],"duration":26,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps paid users on the manual path without an upgrade prompt (nb)","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793729343397,"status":"passed","title":"keeps paid users on the manual path without an upgrade prompt (nb)"},{"ancestorTitles":[],"duration":22,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"shows a respectful upgrade action and remembers dismissal for the session","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793729343423,"status":"passed","title":"shows a respectful upgrade action and remembers dismissal for the session"}],"endTime":1793729343447,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\pro-feature-notice.test.tsx","startTime":1793729339253,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":10,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"English and Bokmål expose the same UI message keys","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793729343841,"status":"passed","title":"English and Bokmål expose the same UI message keys"},{"ancestorTitles":[],"duration":5,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål preserves every English substitution variable","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793729343851,"status":"passed","title":"Bokmål preserves every English substitution variable"},{"ancestorTitles":[],"duration":6,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"supported UI catalogues contain no blank messages","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793729343856,"status":"passed","title":"supported UI catalogues contain no blank messages"}],"endTime":1793729343862,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\translation-catalogue.test.ts","startTime":1793729343468,"status":"passed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/evidence/ai-settings/frontend/a3-automation-red.json b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-automation-red.json new file mode 100644 index 00000000..4901167f --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-automation-red.json @@ -0,0 +1 @@ +{"numFailedTestSuites":1,"numFailedTests":3,"numPassedTestSuites":0,"numPassedTests":0,"numPendingTestSuites":0,"numPendingTests":21,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":1,"numTotalTests":24,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793716189064,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"each selected Settings section has a named panel linked to its tab and remains selectable on phones","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"each selected Settings section has a named panel linked to its tab and remains selectable on phones"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"settings view has no accent picker and uses one follow-up section, one notification section","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"settings view has no accent picker and uses one follow-up section, one notification section"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"AI privacy settings are server-backed and external processing is local-only by default","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"AI privacy settings are server-backed and external processing is local-only by default"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] failed notification save preserves the draft for an explicit retry","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] failed notification save preserves the draft for an explicit retry"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 PRES-W11] saving one follow-up rule preserves the other scenarios","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03 PRES-W11] saving one follow-up rule preserves the other scenarios"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 PRES-J05] table and theme preferences keep their independent callbacks","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03 PRES-J05] table and theme preferences keep their independent callbacks"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 W11] the Settings session retains independent pending Rules fields across tab unmounts","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03 W11] the Settings session retains independent pending Rules fields across tab unmounts"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] failed Rules save remains actionable after tab return and explicit retry clears dirty state","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] failed Rules save remains actionable after tab return and explicit retry clears dirty state"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] invalid and empty Rules input and associated validation survive internal navigation","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] invalid and empty Rules input and associated validation survive internal navigation"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] explicit discard resets only the Rules draft to its saved baseline without writing","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] explicit discard resets only the Rules draft to its saved baseline without writing"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] later edits stay dirty when an earlier Rules save completes after a tab switch","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] later edits stay dirty when an earlier Rules save completes after a tab switch"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 E09] leaving the Settings session disposes its draft and pending responses","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03 E09] leaving the Settings session disposes its draft and pending responses"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] switching locale while Rules is hidden does not reload or overwrite its pending draft","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] switching locale while Rules is hidden does not reload or overwrite its pending draft"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] Rules draft updates do not refetch an unrelated notification preference","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"pending","title":"[PRES-S03] Rules draft updates do not refetch an unrelated notification preference"},{"ancestorTitles":[],"duration":360,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Found multiple elements with the role \"tab\"\n\nHere are the matching elements:\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n\u001b[36m\u001b[39m\n\n(If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"en Automation reuses the saved notification preference and explicit save","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194520,"status":"failed","title":"en Automation reuses the saved notification preference and explicit save"},{"ancestorTitles":[],"duration":142,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Found multiple elements with the role \"tab\"\n\nHere are the matching elements:\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mGenerelt\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mOppfølging\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mVarsler\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mSikkerhetskopi\u001b[0m\n\u001b[36m\u001b[39m\n\n(If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mInnstillingsområde\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGenerelt\u001b[0m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mInnstillingsområde\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGenerelt\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOppfølging\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mVarsler\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSikkerhetskopi\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"nb Automation reuses the saved notification preference and explicit save","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716194903,"status":"failed","title":"nb Automation reuses the saved notification preference and explicit save"},{"ancestorTitles":[],"duration":121,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Found multiple elements with the role \"tab\"\n\nHere are the matching elements:\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n\u001b[36m\u001b[39m\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n\u001b[36m\u001b[39m\n\n(If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m)\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"Automation AI entry moves focus into existing settings without an AI request","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195045,"status":"failed","title":"Automation AI entry moves focus into existing settings without an AI request"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] initial notification failure offers a single GET Retry and recovers its vanished focused action","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] initial notification failure offers a single GET Retry and recovers its vanished focused action"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] notification drafts survive internal sections and locale changes without a GET or save","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] notification drafts survive internal sections and locale changes without a GET or save"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] one held notification save acknowledges its snapshot and preserves later edits across sections","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] one held notification save acknowledges its snapshot and preserves later edits across sections"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] failed notification save keeps its current-locale draft and retries only the original Save","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] failed notification save keeps its current-locale draft and retries only the original Save"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] discarding a notification draft leaves the independent Rules draft untouched","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] discarding a notification draft leaves the independent Rules draft untouched"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] a disposed notification save cannot publish into surviving providers or a new Settings session","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] a disposed notification save cannot publish into surviving providers or a new Settings session"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] Rules load failure follows locale without reloading and Retry retains the six-field contract","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716195167,"status":"pending","title":"[P7-09 preferences] Rules load failure follows locale without reloading and Retry retains the six-field contract"}],"endTime":1793716195191,"message":" ● en Automation reuses the saved notification preference and explicit save\n\n TestingLibraryElementError: Found multiple elements with the role \"tab\"\n\n Here are the matching elements:\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n \u001b[36m\u001b[39m\n\n (If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m {\n 323 | localStorage.setItem('uiLanguage', language); renderView();\n > 324 | fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabAutomation') }));\n | ^\n 325 | const panel = within(screen.getByRole('tabpanel', { name: preferenceCopy('settingsTabAutomation') }));\n 326 | const toggle = await panel.findByRole('switch', { name: preferenceCopy('settingsNotificationsFollowUpReminders') });\n 327 | expect(toggle).toBeChecked(); fireEvent.click(toggle); expect(mockedApi.put).not.toHaveBeenCalled();\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at getElementError (node_modules/@testing-library/dom/dist/query-helpers.js:20:35)\n at getMultipleElementsFoundError (node_modules/@testing-library/dom/dist/query-helpers.js:23:10)\n at node_modules/@testing-library/dom/dist/query-helpers.js:55:13\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at getByRole (src/settings-view.test.tsx:324:26)\n\n ● nb Automation reuses the saved notification preference and explicit save\n\n TestingLibraryElementError: Found multiple elements with the role \"tab\"\n\n Here are the matching elements:\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mGenerelt\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mOppfølging\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mVarsler\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mSikkerhetskopi\u001b[0m\n \u001b[36m\u001b[39m\n\n (If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mInnstillingsområde\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGenerelt\u001b[0m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mInnstillingsområde\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGenerelt\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOppfølging\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mVarsler\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSikkerhetskopi\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m {\n 323 | localStorage.setItem('uiLanguage', language); renderView();\n > 324 | fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabAutomation') }));\n | ^\n 325 | const panel = within(screen.getByRole('tabpanel', { name: preferenceCopy('settingsTabAutomation') }));\n 326 | const toggle = await panel.findByRole('switch', { name: preferenceCopy('settingsNotificationsFollowUpReminders') });\n 327 | expect(toggle).toBeChecked(); fireEvent.click(toggle); expect(mockedApi.put).not.toHaveBeenCalled();\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at getElementError (node_modules/@testing-library/dom/dist/query-helpers.js:20:35)\n at getMultipleElementsFoundError (node_modules/@testing-library/dom/dist/query-helpers.js:23:10)\n at node_modules/@testing-library/dom/dist/query-helpers.js:55:13\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at getByRole (src/settings-view.test.tsx:324:26)\n\n ● Automation AI entry moves focus into existing settings without an AI request\n\n TestingLibraryElementError: Found multiple elements with the role \"tab\"\n\n Here are the matching elements:\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n \u001b[36m\u001b[39m\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n \u001b[36m\u001b[39m\n\n (If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSettings section\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mGeneral\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mFollow-ups\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mNotifications\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mBackup\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m {\n > 335 | renderView(); fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabAutomation') }));\n | ^\n 336 | fireEvent.click(await screen.findByRole('button', { name: preferenceCopy('settingsAutomationAi') }));\n 337 | await waitFor(() => expect(document.getElementById('settings-ai-controls')).toHaveFocus());\n 338 | expect(mockedApi.post).not.toHaveBeenCalled();\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at getElementError (node_modules/@testing-library/dom/dist/query-helpers.js:20:35)\n at getMultipleElementsFoundError (node_modules/@testing-library/dom/dist/query-helpers.js:23:10)\n at node_modules/@testing-library/dom/dist/query-helpers.js:55:13\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at Object.getByRole (src/settings-view.test.tsx:335:40)\n","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\settings-view.test.tsx","startTime":1793716190429,"status":"failed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/evidence/ai-settings/frontend/a3-automation-tests.json b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-automation-tests.json new file mode 100644 index 00000000..9e15ca5f --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-automation-tests.json @@ -0,0 +1 @@ +{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":5,"numPassedTests":45,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":5,"numTotalTests":45,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793716330310,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":1046,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"each selected Settings section has a named panel linked to its tab and remains selectable on phones","invocations":1,"location":null,"numPassingAsserts":16,"retryReasons":[],"startAt":1793716336267,"status":"passed","title":"each selected Settings section has a named panel linked to its tab and remains selectable on phones"},{"ancestorTitles":[],"duration":629,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"settings view has no accent picker and uses one follow-up section, one notification section","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793716337314,"status":"passed","title":"settings view has no accent picker and uses one follow-up section, one notification section"},{"ancestorTitles":[],"duration":291,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"AI privacy settings are server-backed and external processing is local-only by default","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716337943,"status":"passed","title":"AI privacy settings are server-backed and external processing is local-only by default"},{"ancestorTitles":[],"duration":4508,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] failed notification save preserves the draft for an explicit retry","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716338235,"status":"passed","title":"[PRES-S03] failed notification save preserves the draft for an explicit retry"},{"ancestorTitles":[],"duration":644,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 PRES-W11] saving one follow-up rule preserves the other scenarios","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716342744,"status":"passed","title":"[PRES-S03 PRES-W11] saving one follow-up rule preserves the other scenarios"},{"ancestorTitles":[],"duration":416,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 PRES-J05] table and theme preferences keep their independent callbacks","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716343388,"status":"passed","title":"[PRES-S03 PRES-J05] table and theme preferences keep their independent callbacks"},{"ancestorTitles":[],"duration":880,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 W11] the Settings session retains independent pending Rules fields across tab unmounts","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716343804,"status":"passed","title":"[PRES-S03 W11] the Settings session retains independent pending Rules fields across tab unmounts"},{"ancestorTitles":[],"duration":1259,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] failed Rules save remains actionable after tab return and explicit retry clears dirty state","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793716344684,"status":"passed","title":"[PRES-S03] failed Rules save remains actionable after tab return and explicit retry clears dirty state"},{"ancestorTitles":[],"duration":1577,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] invalid and empty Rules input and associated validation survive internal navigation","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716345943,"status":"passed","title":"[PRES-S03] invalid and empty Rules input and associated validation survive internal navigation"},{"ancestorTitles":[],"duration":995,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] explicit discard resets only the Rules draft to its saved baseline without writing","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716347520,"status":"passed","title":"[PRES-S03] explicit discard resets only the Rules draft to its saved baseline without writing"},{"ancestorTitles":[],"duration":1408,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] later edits stay dirty when an earlier Rules save completes after a tab switch","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716348516,"status":"passed","title":"[PRES-S03] later edits stay dirty when an earlier Rules save completes after a tab switch"},{"ancestorTitles":[],"duration":950,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03 E09] leaving the Settings session disposes its draft and pending responses","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716349924,"status":"passed","title":"[PRES-S03 E09] leaving the Settings session disposes its draft and pending responses"},{"ancestorTitles":[],"duration":909,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] switching locale while Rules is hidden does not reload or overwrite its pending draft","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716350874,"status":"passed","title":"[PRES-S03] switching locale while Rules is hidden does not reload or overwrite its pending draft"},{"ancestorTitles":[],"duration":673,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-S03] Rules draft updates do not refetch an unrelated notification preference","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716351784,"status":"passed","title":"[PRES-S03] Rules draft updates do not refetch an unrelated notification preference"},{"ancestorTitles":[],"duration":792,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en Automation reuses the saved notification preference and explicit save","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716352457,"status":"passed","title":"en Automation reuses the saved notification preference and explicit save"},{"ancestorTitles":[],"duration":696,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb Automation reuses the saved notification preference and explicit save","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716353250,"status":"passed","title":"nb Automation reuses the saved notification preference and explicit save"},{"ancestorTitles":[],"duration":481,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Automation AI entry moves focus into existing settings without an AI request","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716353946,"status":"passed","title":"Automation AI entry moves focus into existing settings without an AI request"},{"ancestorTitles":[],"duration":558,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] initial notification failure offers a single GET Retry and recovers its vanished focused action","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793716354427,"status":"passed","title":"[P7-09 preferences] initial notification failure offers a single GET Retry and recovers its vanished focused action"},{"ancestorTitles":[],"duration":1114,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] notification drafts survive internal sections and locale changes without a GET or save","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716354985,"status":"passed","title":"[P7-09 preferences] notification drafts survive internal sections and locale changes without a GET or save"},{"ancestorTitles":[],"duration":1311,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] one held notification save acknowledges its snapshot and preserves later edits across sections","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793716356099,"status":"passed","title":"[P7-09 preferences] one held notification save acknowledges its snapshot and preserves later edits across sections"},{"ancestorTitles":[],"duration":1039,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] failed notification save keeps its current-locale draft and retries only the original Save","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793716357411,"status":"passed","title":"[P7-09 preferences] failed notification save keeps its current-locale draft and retries only the original Save"},{"ancestorTitles":[],"duration":1031,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] discarding a notification draft leaves the independent Rules draft untouched","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716358450,"status":"passed","title":"[P7-09 preferences] discarding a notification draft leaves the independent Rules draft untouched"},{"ancestorTitles":[],"duration":1006,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] a disposed notification save cannot publish into surviving providers or a new Settings session","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716359481,"status":"passed","title":"[P7-09 preferences] a disposed notification save cannot publish into surviving providers or a new Settings session"},{"ancestorTitles":[],"duration":701,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 preferences] Rules load failure follows locale without reloading and Retry retains the six-field contract","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793716360487,"status":"passed","title":"[P7-09 preferences] Rules load failure follows locale without reloading and Retry retains the six-field contract"}],"endTime":1793716361190,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\settings-view.test.tsx","startTime":1793716331747,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":1109,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 lifetime] an accepted import continues once across Notifications and Rules while a real Settings unmount stops queued writes","invocations":1,"location":null,"numPassingAsserts":17,"retryReasons":[],"startAt":1793716362928,"status":"passed","title":"[P7-09 lifetime] an accepted import continues once across Notifications and Rules while a real Settings unmount stops queued writes"},{"ancestorTitles":[],"duration":1051,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 lifetime] the General privacy owner keeps its draft and read across internal tabs while Backup remains lazy and disposable","invocations":1,"location":null,"numPassingAsserts":21,"retryReasons":[],"startAt":1793716364037,"status":"passed","title":"[P7-09 lifetime] the General privacy owner keeps its draft and read across internal tabs while Backup remains lazy and disposable"}],"endTime":1793716365088,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\settings-import-lifetime.test.tsx","startTime":1793716361213,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":124,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps its heading and named loading state, then retries only a failed usage GET","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716366292,"status":"passed","title":"keeps its heading and named loading state, then retries only a failed usage GET"},{"ancestorTitles":[],"duration":94,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"billing failure remains visible beside usage and its Retry only reads billing","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716366417,"status":"passed","title":"billing failure remains visible beside usage and its Retry only reads billing"},{"ancestorTitles":[],"duration":45,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"locale changes format numbers and byte decimals without reloading; zero storage limit stays finite","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716366511,"status":"passed","title":"locale changes format numbers and byte decimals without reloading; zero storage limit stays finite"},{"ancestorTitles":[],"duration":58,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"one billing POST ignores a late failure after unmount","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716366556,"status":"passed","title":"one billing POST ignores a late failure after unmount"},{"ancestorTitles":[],"duration":44,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"one billing POST ignores a late failure after session","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716366614,"status":"passed","title":"one billing POST ignores a late failure after session"},{"ancestorTitles":[],"duration":46,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"late billing success after unmount never consumes the redirect URL","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716366658,"status":"passed","title":"late billing success after unmount never consumes the redirect URL"},{"ancestorTitles":[],"duration":45,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"late billing success after session never consumes the redirect URL","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716366705,"status":"passed","title":"late billing success after session never consumes the redirect URL"},{"ancestorTitles":[],"duration":116,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a failed billing POST offers the existing explicit action without automatic replay","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716366750,"status":"passed","title":"a failed billing POST offers the existing explicit action without automatic replay"},{"ancestorTitles":[],"duration":60,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"shows monthly AI call and token limits","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716366866,"status":"passed","title":"shows monthly AI call and token limits"},{"ancestorTitles":[],"duration":48,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"does not offer a false upgrade action when billing is not configured","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716366927,"status":"passed","title":"does not offer a false upgrade action when billing is not configured"}],"endTime":1793716366977,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\ai-usage-card.test.tsx","startTime":1793716365100,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":128,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 privacy] failed initial read has a read-only Retry and no perpetual loading","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716368291,"status":"passed","title":"[P7-09 privacy] failed initial read has a read-only Retry and no perpetual loading"},{"ancestorTitles":[],"duration":130,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 privacy] submitted acknowledgement preserves a newer edit and serializes Save","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716368419,"status":"passed","title":"[P7-09 privacy] submitted acknowledgement preserves a newer edit and serializes Save"},{"ancestorTitles":[],"duration":170,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 privacy] a failed save retains the draft and never replays through read recovery","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716368549,"status":"passed","title":"[P7-09 privacy] a failed save retains the draft and never replays through read recovery"},{"ancestorTitles":[],"duration":74,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 privacy] unmount ignores an old save acknowledgement and success notification","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716368719,"status":"passed","title":"[P7-09 privacy] unmount ignores an old save acknowledgement and success notification"},{"ancestorTitles":[],"duration":122,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 privacy] pending save uses the current language without refetching the draft","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716368793,"status":"passed","title":"[P7-09 privacy] pending save uses the current language without refetching the draft"},{"ancestorTitles":[],"duration":63,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-09 privacy] local-only capability permits revoking a historical external consent","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716368915,"status":"passed","title":"[P7-09 privacy] local-only capability permits revoking a historical external consent"}],"endTime":1793716368978,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\ai-privacy-settings.test.tsx","startTime":1793716366988,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":14,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"English and Bokmål expose the same UI message keys","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716369522,"status":"passed","title":"English and Bokmål expose the same UI message keys"},{"ancestorTitles":[],"duration":7,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål preserves every English substitution variable","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716369536,"status":"passed","title":"Bokmål preserves every English substitution variable"},{"ancestorTitles":[],"duration":4,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"supported UI catalogues contain no blank messages","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716369543,"status":"passed","title":"supported UI catalogues contain no blank messages"}],"endTime":1793716369548,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\translation-catalogue.test.ts","startTime":1793716368991,"status":"passed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/evidence/ai-settings/frontend/a3-document-ai-language-red.json b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-document-ai-language-red.json new file mode 100644 index 00000000..b9e22c6a --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-document-ai-language-red.json @@ -0,0 +1 @@ +{"numFailedTestSuites":1,"numFailedTests":1,"numPassedTestSuites":0,"numPassedTests":0,"numPendingTestSuites":0,"numPendingTests":59,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":1,"numTotalTests":60,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793716607608,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Strict Mode groups a typing burst into one undo step and preserves redo through autosave","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"Strict Mode groups a typing burst into one undo step and preserves redo through autosave"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a pause between typing bursts leaves a separate undo step","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"a pause between typing bursts leaves a separate undo step"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"tablet width keeps both editing and preview available in the stacked document flow","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"tablet width keeps both editing and preview available in the stacked document flow"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"document shortcuts undo and redo renaming, preserve native input undo and discard branched redo","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"document shortcuts undo and redo renaming, preserve native input undo and discard branched redo"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a revision conflict disables document history without silently writing an undo","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"a revision conflict disables document history without silently writing an undo"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"switching documents hides the previous draft while loading and starts fresh history","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"switching documents hides the previous draft while loading and starts fresh history"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"explicit blank editing excludes master content and includes a profile section only after an Add action","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"explicit blank editing excludes master content and includes a profile section only after an Add action"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a blank CV can deliberately add an additional Career Profile section","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"a blank CV can deliberately add an additional Career Profile section"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a historical restore response from the previous document cannot change the newly opened CV","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"a historical restore response from the previous document cannot change the newly opened CV"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"content sections follow the editing-region heading without mutating CV settings","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"content sections follow the editing-region heading without mutating CV settings"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"settings history explains current Career Profile resolution without writing data","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"settings history explains current Career Profile resolution without writing data"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"PDF export locks immediately, rejects a newer unsaved draft, and keeps that draft recoverable","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"PDF export locks immediately, rejects a newer unsaved draft, and keeps that draft recoverable"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"edits during a held PDF response prevent an older document download","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"edits during a held PDF response prevent an older document download"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"moving a section to the first position announces its actual order and focuses its row","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613832,"status":"pending","title":"moving a section to the first position announces its actual order and focuses its row"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"section navigation opens and focuses omitted/custom sections without changing their data","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"section navigation opens and focuses omitted/custom sections without changing their data"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keyboard move controls retain focus and persist the same section order shown by navigation","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"keyboard move controls retain focus and persist the same section order shown by navigation"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"secondary duplicate action saves the current draft before creating the copy","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"secondary duplicate action saves the current draft before creating the copy"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"pane navigation focuses the existing preview without changing the pending draft","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"pane navigation focuses the existing preview without changing the pending draft"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"deep link loads the exact variant named in the route","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"deep link loads the exact variant named in the route"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a variant that does not exist shows a safe error instead of an empty editor","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"a variant that does not exist shows a safe error instead of an empty editor"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"another user's variant is refused by the server and never rendered","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"another user's variant is refused by the server and never rendered"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a denied CV read has localized permission context without a write or retry","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"a denied CV read has localized permission context without a write or retry"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a temporary CV opening failure retries reads and restores focus to the editor without saving","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"a temporary CV opening failure retries reads and restores focus to the editor without saving"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål history localizes known sources while preserving unknown metadata and versions","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"Bokmål history localizes known sources while preserving unknown metadata and versions"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"invalid names are explained and are not silently autosaved","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"invalid names are explained and are not silently autosaved"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"failed autosave is visible and can be retried with the latest data","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"failed autosave is visible and can be retried with the latest data"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"session undo and redo restore content edits before autosave","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"session undo and redo restore content edits before autosave"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"queued saves use acknowledged server versions without replacing newer local editing state","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"queued saves use acknowledged server versions without replacing newer local editing state"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"revision conflict retains the draft and blocks later autosaves until explicit reload","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"revision conflict retains the draft and blocks later autosaves until explicit reload"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"edits made while a confirmed reload is in flight remain recoverable","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"edits made while a confirmed reload is in flight remain recoverable"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"restoring history uses the current version and never replaces edits made during the request","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"restoring history uses the current version and never replaces edits made during the request"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Content is the primary studio panel and all advanced tabs retain their controls","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"Content is the primary studio panel and all advanced tabs retain their controls"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"choosing a template restores its own structure instead of inheriting the previous template layout","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"choosing a template restores its own structure instead of inheriting the previous template layout"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"editor sections, design controls and document settings render in Bokmål","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"editor sections, design controls and document settings render in Bokmål"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"internal navigation warns and can be cancelled before discarding a pending edit","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"internal navigation warns and can be cancelled before discarding a pending edit"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"custom entries can be added, edited, reordered and deleted with confirmation","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"custom entries can be added, edited, reordered and deleted with confirmation"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C01 C07] source-backed entry edits identify their scope and save only this CV","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-10 PRES-C01 C07] source-backed entry edits identify their scope and save only this CV"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C07 C10] resetting one entry field preserves omission, sibling override and order and supports undo","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-10 PRES-C07 C10] resetting one entry field preserves omission, sibling override and order and supports undo"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C07 C10 E08] omitted entries remain editable and retain their draft after a failed save","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-10 PRES-C07 C10 E08] omitted entries remain editable and retain their draft after a failed save"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C01 C07] section content reset inherits source without changing omission or presentation","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-10 PRES-C01 C07] section content reset inherits source without changing omission or presentation"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"profile-backed sections expand, reorder, hide and persist variant-only overrides","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"profile-backed sections expand, reorder, hide and persist variant-only overrides"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"focusing a preview retry control keeps its pointer target stationary","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"focusing a preview retry control keeps its pointer target stationary"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"preview failure is visible and retryable without leaving the editor","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"preview failure is visible and retryable without leaving the editor"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 E08] automatic fit attaches when the asynchronously loaded preview pane appears","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-11 PRES-C06 E08] automatic fit attaches when the asynchronously loaded preview pane appears"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 C12] page count is announced only after the renderer has settled","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-11 PRES-C06 C12] page count is announced only after the renderer has settled"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 E09] overlapping preview successes and failures cannot replace the newest document","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-11 PRES-C06 E09] overlapping preview successes and failures cannot replace the newest document"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 C10 E08] returning from preview focuses the existing editor without changing the pending draft","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716613833,"status":"pending","title":"[P5-11 PRES-C06 C10 E08] returning from preview focuses the existing editor without changing the pending draft"},{"ancestorTitles":[],"duration":1510,"failing":false,"failureDetails":[{"matcherResult":{"pass":true,"message":"expect(element).not.toBeInTheDocument()\n\nexpected document not to contain element, found
Review 1 proposed change(s)
instead"}}],"failureMessages":["Error: expect(element).not.toBeInTheDocument()\n\nexpected document not to contain element, found
Review 1 proposed change(s)
instead\n at Object.toBeInTheDocument (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\cv-builder-deep-link.test.tsx:1115:65)"],"fullName":"changing whole-document output language discards the previous-language review without applying it","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716613833,"status":"failed","title":"changing whole-document output language discards the previous-language review without applying it"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11 PRES-C07] whole-document AI Apply changes only an explicitly accepted CV override","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"[PRES-C11 PRES-C07] whole-document AI Apply changes only an explicitly accepted CV override"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11 PRES-C07] whole-document AI Reject changes only an explicitly accepted CV override","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"[PRES-C11 PRES-C07] whole-document AI Reject changes only an explicitly accepted CV override"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11] unsafe whole-document response (invalid JSON) cannot be applied","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"[PRES-C11] unsafe whole-document response (invalid JSON) cannot be applied"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11] unsafe whole-document response (missing original ID) cannot be applied","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"[PRES-C11] unsafe whole-document response (missing original ID) cannot be applied"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11] unsafe whole-document response (duplicate original ID) cannot be applied","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"[PRES-C11] unsafe whole-document response (duplicate original ID) cannot be applied"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound document generation saves the pending draft, reviews server Original, and accepted AI remains undoable","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"bound document generation saves the pending draft, reviews server Original, and accepted AI remains undoable"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a newer draft is flushed before stale proposal acceptance fails without rebasing or changing content","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"a newer draft is flushed before stale proposal acceptance fails without rebasing or changing content"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"late document proposals cannot return after tab unmount or a source undo","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"late document proposals cannot return after tab unmount or a source undo"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound section:skills assistant sends explicit scope and edited wording to server acceptance","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"bound section:skills assistant sends explicit scope and edited wording to server acceptance"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound custom:sample assistant sends explicit scope and edited wording to server acceptance","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"bound custom:sample assistant sends explicit scope and edited wording to server acceptance"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound entry:experience:job-1 assistant sends explicit scope and edited wording to server acceptance","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"bound entry:experience:job-1 assistant sends explicit scope and edited wording to server acceptance"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"user edits made during server acceptance are retained instead of overwritten by its late saved response","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793716615372,"status":"pending","title":"user edits made during server acceptance are retained instead of overwritten by its late saved response"}],"endTime":1793716615391,"message":" ● changing whole-document output language discards the previous-language review without applying it\n\n expect(element).not.toBeInTheDocument()\n\n expected document not to contain element, found
Review 1 proposed change(s)
instead\n\n 1113 | fireEvent.mouseDown(screen.getByLabelText('Output language'));\n 1114 | fireEvent.click(screen.getByRole('option', { name: 'Norsk bokmål' }));\n > 1115 | expect(screen.queryByText('Review 1 proposed change(s)')).not.toBeInTheDocument();\n | ^\n 1116 | expect(mockedApi.post.mock.calls.filter(([url]) => url === '/cv/variants/3/ai/apply')).toHaveLength(0);\n 1117 | expect(mockedApi.post.mock.calls.filter(([url]) => url === '/cv/ai/assist')).toHaveLength(1);\n 1118 | });\n\n at Object.toBeInTheDocument (src/cv-builder-deep-link.test.tsx:1115:65)\n","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\cv-builder-deep-link.test.tsx","startTime":1793716609057,"status":"failed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/evidence/ai-settings/frontend/a3-document-ai-language-tests.json b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-document-ai-language-tests.json new file mode 100644 index 00000000..6e1984eb --- /dev/null +++ b/docs/ui-modernisation/evidence/ai-settings/frontend/a3-document-ai-language-tests.json @@ -0,0 +1 @@ +{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":1,"numPassedTests":60,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":1,"numTotalTests":60,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793716629407,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":2914,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Strict Mode groups a typing burst into one undo step and preserves redo through autosave","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716635384,"status":"passed","title":"Strict Mode groups a typing burst into one undo step and preserves redo through autosave"},{"ancestorTitles":[],"duration":1814,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a pause between typing bursts leaves a separate undo step","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716638299,"status":"passed","title":"a pause between typing bursts leaves a separate undo step"},{"ancestorTitles":[],"duration":608,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"tablet width keeps both editing and preview available in the stacked document flow","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716640113,"status":"passed","title":"tablet width keeps both editing and preview available in the stacked document flow"},{"ancestorTitles":[],"duration":2012,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"document shortcuts undo and redo renaming, preserve native input undo and discard branched redo","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716640721,"status":"passed","title":"document shortcuts undo and redo renaming, preserve native input undo and discard branched redo"},{"ancestorTitles":[],"duration":1233,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a revision conflict disables document history without silently writing an undo","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716642734,"status":"passed","title":"a revision conflict disables document history without silently writing an undo"},{"ancestorTitles":[],"duration":1580,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"switching documents hides the previous draft while loading and starts fresh history","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716643967,"status":"passed","title":"switching documents hides the previous draft while loading and starts fresh history"},{"ancestorTitles":[],"duration":958,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"explicit blank editing excludes master content and includes a profile section only after an Add action","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716645547,"status":"passed","title":"explicit blank editing excludes master content and includes a profile section only after an Add action"},{"ancestorTitles":[],"duration":699,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a blank CV can deliberately add an additional Career Profile section","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716646505,"status":"passed","title":"a blank CV can deliberately add an additional Career Profile section"},{"ancestorTitles":[],"duration":2169,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a historical restore response from the previous document cannot change the newly opened CV","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716647204,"status":"passed","title":"a historical restore response from the previous document cannot change the newly opened CV"},{"ancestorTitles":[],"duration":575,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"content sections follow the editing-region heading without mutating CV settings","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716649373,"status":"passed","title":"content sections follow the editing-region heading without mutating CV settings"},{"ancestorTitles":[],"duration":445,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"settings history explains current Career Profile resolution without writing data","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716649948,"status":"passed","title":"settings history explains current Career Profile resolution without writing data"},{"ancestorTitles":[],"duration":1599,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"PDF export locks immediately, rejects a newer unsaved draft, and keeps that draft recoverable","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716650394,"status":"passed","title":"PDF export locks immediately, rejects a newer unsaved draft, and keeps that draft recoverable"},{"ancestorTitles":[],"duration":1425,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"edits during a held PDF response prevent an older document download","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716651993,"status":"passed","title":"edits during a held PDF response prevent an older document download"},{"ancestorTitles":[],"duration":927,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"moving a section to the first position announces its actual order and focuses its row","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716653418,"status":"passed","title":"moving a section to the first position announces its actual order and focuses its row"},{"ancestorTitles":[],"duration":5637,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"section navigation opens and focuses omitted/custom sections without changing their data","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793716654345,"status":"passed","title":"section navigation opens and focuses omitted/custom sections without changing their data"},{"ancestorTitles":[],"duration":1892,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keyboard move controls retain focus and persist the same section order shown by navigation","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716659982,"status":"passed","title":"keyboard move controls retain focus and persist the same section order shown by navigation"},{"ancestorTitles":[],"duration":1521,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"secondary duplicate action saves the current draft before creating the copy","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716661874,"status":"passed","title":"secondary duplicate action saves the current draft before creating the copy"},{"ancestorTitles":[],"duration":1084,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"pane navigation focuses the existing preview without changing the pending draft","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716663395,"status":"passed","title":"pane navigation focuses the existing preview without changing the pending draft"},{"ancestorTitles":[],"duration":534,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"deep link loads the exact variant named in the route","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716664479,"status":"passed","title":"deep link loads the exact variant named in the route"},{"ancestorTitles":[],"duration":30,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a variant that does not exist shows a safe error instead of an empty editor","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716665013,"status":"passed","title":"a variant that does not exist shows a safe error instead of an empty editor"},{"ancestorTitles":[],"duration":42,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"another user's variant is refused by the server and never rendered","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716665043,"status":"passed","title":"another user's variant is refused by the server and never rendered"},{"ancestorTitles":[],"duration":53,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a denied CV read has localized permission context without a write or retry","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716665086,"status":"passed","title":"a denied CV read has localized permission context without a write or retry"},{"ancestorTitles":[],"duration":350,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a temporary CV opening failure retries reads and restores focus to the editor without saving","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716665139,"status":"passed","title":"a temporary CV opening failure retries reads and restores focus to the editor without saving"},{"ancestorTitles":[],"duration":1161,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål history localizes known sources while preserving unknown metadata and versions","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793716665490,"status":"passed","title":"Bokmål history localizes known sources while preserving unknown metadata and versions"},{"ancestorTitles":[],"duration":1039,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"invalid names are explained and are not silently autosaved","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716666651,"status":"passed","title":"invalid names are explained and are not silently autosaved"},{"ancestorTitles":[],"duration":2083,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"failed autosave is visible and can be retried with the latest data","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793716667690,"status":"passed","title":"failed autosave is visible and can be retried with the latest data"},{"ancestorTitles":[],"duration":2381,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"session undo and redo restore content edits before autosave","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716669773,"status":"passed","title":"session undo and redo restore content edits before autosave"},{"ancestorTitles":[],"duration":2624,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"queued saves use acknowledged server versions without replacing newer local editing state","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716672154,"status":"passed","title":"queued saves use acknowledged server versions without replacing newer local editing state"},{"ancestorTitles":[],"duration":3800,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"revision conflict retains the draft and blocks later autosaves until explicit reload","invocations":1,"location":null,"numPassingAsserts":10,"retryReasons":[],"startAt":1793716674778,"status":"passed","title":"revision conflict retains the draft and blocks later autosaves until explicit reload"},{"ancestorTitles":[],"duration":2605,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"edits made while a confirmed reload is in flight remain recoverable","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716678578,"status":"passed","title":"edits made while a confirmed reload is in flight remain recoverable"},{"ancestorTitles":[],"duration":2666,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"restoring history uses the current version and never replaces edits made during the request","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716681183,"status":"passed","title":"restoring history uses the current version and never replaces edits made during the request"},{"ancestorTitles":[],"duration":1649,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Content is the primary studio panel and all advanced tabs retain their controls","invocations":1,"location":null,"numPassingAsserts":14,"retryReasons":[],"startAt":1793716683849,"status":"passed","title":"Content is the primary studio panel and all advanced tabs retain their controls"},{"ancestorTitles":[],"duration":2667,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"choosing a template restores its own structure instead of inheriting the previous template layout","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716685498,"status":"passed","title":"choosing a template restores its own structure instead of inheriting the previous template layout"},{"ancestorTitles":[],"duration":2009,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"editor sections, design controls and document settings render in Bokmål","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716688165,"status":"passed","title":"editor sections, design controls and document settings render in Bokmål"},{"ancestorTitles":[],"duration":1934,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"internal navigation warns and can be cancelled before discarding a pending edit","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716690174,"status":"passed","title":"internal navigation warns and can be cancelled before discarding a pending edit"},{"ancestorTitles":[],"duration":10565,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"custom entries can be added, edited, reordered and deleted with confirmation","invocations":1,"location":null,"numPassingAsserts":16,"retryReasons":[],"startAt":1793716692108,"status":"passed","title":"custom entries can be added, edited, reordered and deleted with confirmation"},{"ancestorTitles":[],"duration":3918,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C01 C07] source-backed entry edits identify their scope and save only this CV","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793716702674,"status":"passed","title":"[P5-10 PRES-C01 C07] source-backed entry edits identify their scope and save only this CV"},{"ancestorTitles":[],"duration":5776,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C07 C10] resetting one entry field preserves omission, sibling override and order and supports undo","invocations":1,"location":null,"numPassingAsserts":12,"retryReasons":[],"startAt":1793716706592,"status":"passed","title":"[P5-10 PRES-C07 C10] resetting one entry field preserves omission, sibling override and order and supports undo"},{"ancestorTitles":[],"duration":3299,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C07 C10 E08] omitted entries remain editable and retain their draft after a failed save","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716712368,"status":"passed","title":"[P5-10 PRES-C07 C10 E08] omitted entries remain editable and retain their draft after a failed save"},{"ancestorTitles":[],"duration":2636,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-10 PRES-C01 C07] section content reset inherits source without changing omission or presentation","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716715667,"status":"passed","title":"[P5-10 PRES-C01 C07] section content reset inherits source without changing omission or presentation"},{"ancestorTitles":[],"duration":6641,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"profile-backed sections expand, reorder, hide and persist variant-only overrides","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793716718303,"status":"passed","title":"profile-backed sections expand, reorder, hide and persist variant-only overrides"},{"ancestorTitles":[],"duration":2041,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"focusing a preview retry control keeps its pointer target stationary","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793716724944,"status":"passed","title":"focusing a preview retry control keeps its pointer target stationary"},{"ancestorTitles":[],"duration":1853,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"preview failure is visible and retryable without leaving the editor","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716726985,"status":"passed","title":"preview failure is visible and retryable without leaving the editor"},{"ancestorTitles":[],"duration":522,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 E08] automatic fit attaches when the asynchronously loaded preview pane appears","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793716728839,"status":"passed","title":"[P5-11 PRES-C06 E08] automatic fit attaches when the asynchronously loaded preview pane appears"},{"ancestorTitles":[],"duration":1029,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 C12] page count is announced only after the renderer has settled","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716729361,"status":"passed","title":"[P5-11 PRES-C06 C12] page count is announced only after the renderer has settled"},{"ancestorTitles":[],"duration":3269,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 E09] overlapping preview successes and failures cannot replace the newest document","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793716730390,"status":"passed","title":"[P5-11 PRES-C06 E09] overlapping preview successes and failures cannot replace the newest document"},{"ancestorTitles":[],"duration":1655,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P5-11 PRES-C06 C10 E08] returning from preview focuses the existing editor without changing the pending draft","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716733659,"status":"passed","title":"[P5-11 PRES-C06 C10 E08] returning from preview focuses the existing editor without changing the pending draft"},{"ancestorTitles":[],"duration":1415,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"changing whole-document output language discards the previous-language review without applying it","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716735315,"status":"passed","title":"changing whole-document output language discards the previous-language review without applying it"},{"ancestorTitles":[],"duration":2382,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11 PRES-C07] whole-document AI Apply changes only an explicitly accepted CV override","invocations":1,"location":null,"numPassingAsserts":12,"retryReasons":[],"startAt":1793716736731,"status":"passed","title":"[PRES-C11 PRES-C07] whole-document AI Apply changes only an explicitly accepted CV override"},{"ancestorTitles":[],"duration":1515,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11 PRES-C07] whole-document AI Reject changes only an explicitly accepted CV override","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793716739114,"status":"passed","title":"[PRES-C11 PRES-C07] whole-document AI Reject changes only an explicitly accepted CV override"},{"ancestorTitles":[],"duration":2378,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11] unsafe whole-document response (invalid JSON) cannot be applied","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716740629,"status":"passed","title":"[PRES-C11] unsafe whole-document response (invalid JSON) cannot be applied"},{"ancestorTitles":[],"duration":2065,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11] unsafe whole-document response (missing original ID) cannot be applied","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716743007,"status":"passed","title":"[PRES-C11] unsafe whole-document response (missing original ID) cannot be applied"},{"ancestorTitles":[],"duration":2232,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[PRES-C11] unsafe whole-document response (duplicate original ID) cannot be applied","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793716745072,"status":"passed","title":"[PRES-C11] unsafe whole-document response (duplicate original ID) cannot be applied"},{"ancestorTitles":[],"duration":7124,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound document generation saves the pending draft, reviews server Original, and accepted AI remains undoable","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793716747304,"status":"passed","title":"bound document generation saves the pending draft, reviews server Original, and accepted AI remains undoable"},{"ancestorTitles":[],"duration":3520,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a newer draft is flushed before stale proposal acceptance fails without rebasing or changing content","invocations":1,"location":null,"numPassingAsserts":13,"retryReasons":[],"startAt":1793716754428,"status":"passed","title":"a newer draft is flushed before stale proposal acceptance fails without rebasing or changing content"},{"ancestorTitles":[],"duration":4677,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"late document proposals cannot return after tab unmount or a source undo","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793716757949,"status":"passed","title":"late document proposals cannot return after tab unmount or a source undo"},{"ancestorTitles":[],"duration":4161,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound section:skills assistant sends explicit scope and edited wording to server acceptance","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716762626,"status":"passed","title":"bound section:skills assistant sends explicit scope and edited wording to server acceptance"},{"ancestorTitles":[],"duration":4882,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound custom:sample assistant sends explicit scope and edited wording to server acceptance","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716766787,"status":"passed","title":"bound custom:sample assistant sends explicit scope and edited wording to server acceptance"},{"ancestorTitles":[],"duration":4123,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"bound entry:experience:job-1 assistant sends explicit scope and edited wording to server acceptance","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793716771669,"status":"passed","title":"bound entry:experience:job-1 assistant sends explicit scope and edited wording to server acceptance"},{"ancestorTitles":[],"duration":3221,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"user edits made during server acceptance are retained instead of overwritten by its late saved response","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793716775792,"status":"passed","title":"user edits made during server acceptance are retained instead of overwritten by its late saved response"}],"endTime":1793716779016,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\cv-builder-deep-link.test.tsx","startTime":1793716630880,"status":"passed","summary":""}],"wasInterrupted":false} diff --git a/job-tracker-ui/e2e/phase7-settings-preferences.spec.ts b/job-tracker-ui/e2e/phase7-settings-preferences.spec.ts index a2e8d78e..c721e6c7 100644 --- a/job-tracker-ui/e2e/phase7-settings-preferences.spec.ts +++ b/job-tracker-ui/e2e/phase7-settings-preferences.spec.ts @@ -64,7 +64,7 @@ async function choose(page: Page, label: string, language: Language = 'en') { else { await keyboard(tab); await expect(tab).toHaveAttribute('aria-selected', 'true'); } } function notificationGroup(page: Page, language: Language = 'en') { return page.getByRole('main').getByRole('group', { name: copy('settingsNotificationsTitle', language), exact: true }); } -function notificationCheckbox(page: Page, language: Language = 'en') { return page.getByRole('main').getByRole('checkbox', { name: copy('settingsNotificationsFollowUpReminders', language), exact: true }); } +function notificationCheckbox(page: Page, language: Language = 'en') { return page.getByRole('main').getByRole('switch', { name: copy('settingsNotificationsFollowUpReminders', language), exact: true }); } async function toggle(control: Locator) { await expect(control).toBeEnabled(); await control.focus(); await control.press('Space'); } async function persistedNotifications(session: Session, api: APIRequestContext) { return json<{ emailFollowUpRemindersEnabled: boolean }>(await call(session.requests, api, 'GET', '/notification-settings')); } function response(page: Page, method: string, path: string) { return page.waitForResponse(value => value.request().method() === method && new URL(value.url()).pathname === `/api${path}`); } diff --git a/job-tracker-ui/e2e/settings-page-layout.spec.ts b/job-tracker-ui/e2e/settings-page-layout.spec.ts index 51e54d64..abfbb9f2 100644 --- a/job-tracker-ui/e2e/settings-page-layout.spec.ts +++ b/job-tracker-ui/e2e/settings-page-layout.spec.ts @@ -135,7 +135,7 @@ for (const mode of ["light", "dark"] as const) for (const language of ["en", "nb await expect(notifications.getByRole("progressbar", { name: t.loading, exact: true })).toBeVisible(); await capture(page, info, `notifications-loading-${suffix}`); release(); - const pref = main.getByRole("checkbox", { name: t.settingsNotificationsFollowUpReminders, exact: true }); + const pref = main.getByRole("switch", { name: t.settingsNotificationsFollowUpReminders, exact: true }); await expect(pref).toBeChecked(); await page.unroute(`${apiUrl}/notification-settings`); await pref.uncheck(); diff --git a/job-tracker-ui/scripts/verify-a3-ai-settings.mjs b/job-tracker-ui/scripts/verify-a3-ai-settings.mjs new file mode 100644 index 00000000..9942f93d --- /dev/null +++ b/job-tracker-ui/scripts/verify-a3-ai-settings.mjs @@ -0,0 +1,103 @@ +// Exported React UI with synthetic API responses; no backend, model or provider access. +import { chromium, expect } from '@playwright/test'; +import AxeBuilder from '@axe-core/playwright'; +import ts from 'typescript'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import path from 'node:path'; +const compiled = ts.transpileModule(fs.readFileSync(new URL('../src/i18n/translations.ts', import.meta.url), 'utf8'), { compilerOptions: { module: ts.ModuleKind.ESNext } }).outputText; +const { translations } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`); +const out = path.resolve(import.meta.dirname, '../../docs/ui-modernisation/evidence/ai-settings/browser'); +fs.mkdirSync(out, { recursive: true }); +const report = { screens: [], journeys: [], errors: [], unexpectedWrites: [], writes: [], proposals: [], unavailableReads: [], blockedExternal: [] }; +const browser = await chromium.launch(); +try { + const configurations = process.env.A3_PILOT ? [[320, 'en', 'light']] : [320, 390, 768, 1440].flatMap(width => ['en', 'nb'].flatMap(language => ['light', 'dark'].map(mode => [width, language, mode]))); + for (const [width, language, mode] of configurations) { + console.log(`Checking ${width}/${language}/${mode}`); + const t = key => { assert.ok(translations[language][key], key); return translations[language][key]; }; + const context = await browser.newContext({ viewport: { width, height: 1000 }, reducedMotion: 'reduce' }); + const page = await context.newPage(); page.on('pageerror', error => report.errors.push(error.message)); + await page.addInitScript(({ language, mode }) => { localStorage.setItem('uiLanguage', language); localStorage.setItem('jobtracker.themeMode', mode); }, { language, mode }); + let notifications = { emailFollowUpRemindersEnabled: true }; + let privacy = { enabled: true, externalProcessingAllowed: false, externalProcessingAvailable: false, effectiveExternalProcessing: false, provider: 'local' }; + let variant = { id: 3, name: 'Teacher CV', version: 4, settings: { language: 'en', themeId: 'modern', showPhoto: false, showPageNumbers: false, showIcons: true, sections: [], overrides: {}, customSections: [] }, isPublic: false, publicSlug: 'synthetic', jobApplicationId: null, updatedAtUtc: '2026-11-03T10:00:00Z' }; + let proposal; + const writes = [], proposals = []; + await page.route('**/*', route => { + const req = route.request(), url = new URL(req.url()), p = url.pathname; + if (!['localhost', '127.0.0.1'].includes(url.hostname)) { report.blockedExternal.push(url.origin); return route.abort(); } + if (!p.startsWith('/api/')) return route.continue(); + const answer = data => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(data) }); + const note = action => { writes.push(action); report.writes.push({ width, language, mode, action }); }; + if (req.method() === 'PUT' && p === '/api/notification-settings') { assert.deepEqual(req.postDataJSON(), { emailFollowUpRemindersEnabled: false }); notifications = req.postDataJSON(); note('notificationPreference'); return answer(notifications); } + if (req.method() === 'PUT' && p === '/api/ai/settings') { const body = req.postDataJSON(); assert.equal(body.externalProcessingAllowed, false); privacy = { ...privacy, ...body }; note('aiPreference'); return answer(privacy); } + if (req.method() === 'PUT' && p === '/api/cv/variants/3') { + const body = req.postDataJSON(); assert.equal(body.expectedVersion, variant.version); assert.equal(body.settings.headline, 'Manual teacher headline'); + variant = { ...variant, settings: body.settings, name: body.name, version: variant.version + 1 }; note('manualCvSave'); return answer(variant); + } + if (req.method() === 'POST' && p === '/api/cv/preview') return answer({ themeId: 'modern', html: 'Controlled preview

Alex Sample

Recorded teacher profile

' }); + if (req.method() === 'POST' && p === '/api/cv/ai/assist') { + const body = req.postDataJSON(); assert.equal(privacy.enabled, true); assert.equal(body.expectedVersion, variant.version); assert.equal(body.action, 'document-translate'); assert.equal(body.variantId, 3); assert.equal(Object.hasOwn(body, 'text'), false); + assert.equal(body.language, proposals.length ? 'nb-NO' : 'en'); + proposal = { version: variant.version, language: body.language, token: `synthetic-${proposals.length}` }; + proposals.push(body.language); report.proposals.push({ width, language, mode, outputLanguage: body.language }); + return answer({ original: JSON.stringify([{ id: 'headline', items: [variant.settings.headline] }]), result: JSON.stringify([{ id: 'headline', items: ['Reviewed teacher headline'] }]), proposalToken: proposal.token }); + } + if (req.method() === 'POST' && p === '/api/cv/variants/3/ai/apply') { + assert.deepEqual(req.postDataJSON(), { proposalToken: proposal.token }); assert.equal(proposal.version, variant.version); + variant = { ...variant, version: variant.version + 1, settings: { ...variant.settings, headline: 'Reviewed teacher headline', language: proposal.language } }; note('explicitAiApply'); return answer(variant); + } + if (req.method() !== 'GET') { report.unexpectedWrites.push(p); return route.abort(); } + const fixtures = { + '/api/auth/config': { requireAuth: true }, '/api/auth/me': { id: 'a3-ai-owner', sessionContext: 'a3-ai-session', provider: 'local', firstName: 'Alex', displayName: 'Alex Sample', roles: [], plan: 'pro', entitlements: { ai: privacy.enabled, proThemes: true }, uiLanguage: language === 'nb' ? 'nb-NO' : 'en' }, + '/api/jobapplications/reminders': [], '/api/notifications/unread-count': { count: 0 }, '/api/notification-settings': notifications, '/api/ai/settings': privacy, + '/api/ai/usage': { currentMonth: { calls: 2, estimatedTokens: 200 }, plan: 'pro', monthlyCallLimit: 100, monthlyTokenLimit: 10000, storageUsedBytes: 0, storageLimitBytes: 250000000 }, + '/api/billing/status': { enabled: false, canCheckout: false, canManage: false }, + '/api/rules': { id: 1, appliedFollowUpDays: 14, appliedGhostDays: 30, offerFollowUpDays: 7, offerGhostDays: 14, feedbackFollowUpDays: 7, feedbackGhostDays: 14 }, + '/api/cv/variants/3': variant, '/api/cv/variants/3/versions': [], '/api/cv/outline': { fullName: 'Alex Sample', headline: 'Recorded teacher headline', sections: [] }, + '/api/cv/themes': [{ id: 'modern', name: 'Modern', category: 'Professional', description: 'Synthetic template', layout: 'header-band', accent: '#3157d5', photoShape: 'none', supportsIcons: false, atsFriendly: true, requiresPro: false, available: true, swatches: ['#3157d5'] }], + }; + if (Object.hasOwn(fixtures, p)) return answer(fixtures[p]); + report.unavailableReads.push(p); return route.fulfill({ status: 404, contentType: 'application/json', body: '{}' }); + }); + const scan = async state => { + assert.equal(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth + 1), false, `overflow:${state}`); + const result = await new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa']).analyze(); + report.screens.push({ width, language, mode, state, violations: result.violations }); assert.deepEqual(result.violations, [], `${state} accessibility`); + await page.evaluate(() => window.scrollTo({ top: 0, behavior: 'instant' })); + await expect.poll(() => page.evaluate(() => window.scrollY)).toBe(0); + await page.screenshot({ path: path.join(out, `${state}-${language}-${mode}-${width}.png`), fullPage: width >= 768 }); + }; + const settingsSection = async key => { + if (width >= 600) await page.getByRole('tab', { name: t(key), exact: true }).click(); + else { await page.getByRole('combobox', { name: t('settingsNavigation'), exact: true }).click(); await page.getByRole('option', { name: t(key), exact: true }).click(); } + }; + await page.goto('http://localhost:4338/settings'); + await settingsSection('settingsTabAutomation'); + const reminder = page.getByRole('switch', { name: t('settingsNotificationsFollowUpReminders'), exact: true }); await reminder.uncheck(); assert.equal(writes.length, 0); + await page.getByRole('button', { name: t('settingsNotificationsSave'), exact: true }).click(); await expect.poll(() => notifications.emailFollowUpRemindersEnabled).toBe(false); await scan('automation'); + await page.getByRole('button', { name: t('settingsAutomationAi'), exact: true }).press('Enter'); await expect(page.locator('#settings-ai-controls')).toBeFocused(); + await page.getByRole('switch', { name: t('settingsAiEnabled'), exact: true }).uncheck(); await page.getByRole('button', { name: t('settingsAiSave'), exact: true }).click(); await expect.poll(() => privacy.enabled).toBe(false); await scan('ai-disabled'); + await page.goto('http://localhost:4338/career/builder/3'); + await page.getByRole('tab', { name: t('cvEditorAiTools'), exact: true }).click(); + await expect(page.getByText(t('aiUnavailableTitle'), { exact: true })).toBeVisible(); await expect(page.getByRole('button', { name: t('cvDocumentAiReview'), exact: true }).first()).toBeDisabled(); + await page.getByRole('tab', { name: t('cvEditorContent'), exact: true }).click(); + await page.getByRole('textbox', { name: t('cvEditorHeadlineOverride'), exact: true }).fill('Manual teacher headline'); await expect.poll(() => variant.version, { timeout: 15000 }).toBe(5); assert.equal(proposals.length, 0); await scan('manual-fallback'); + await page.goto('http://localhost:4338/settings'); await page.getByRole('switch', { name: t('settingsAiEnabled'), exact: true }).check(); await page.getByRole('button', { name: t('settingsAiSave'), exact: true }).click(); await expect.poll(() => privacy.enabled).toBe(true); + await page.goto('http://localhost:4338/career/builder/3'); await page.getByRole('tab', { name: t('cvEditorAiTools'), exact: true }).click(); + await page.getByRole('button', { name: t('cvDocumentAiReview'), exact: true }).first().click(); await expect(page.getByRole('button', { name: t('cvAiApply'), exact: true })).toBeVisible(); assert.equal(writes.length, 4); await scan('ai-review'); + await page.getByRole('combobox', { name: new RegExp(`^${t('cvAiLanguage')}`) }).click(); await page.getByRole('option', { name: t('languageNorwegianBokmal'), exact: true }).click(); + await expect(page.getByRole('button', { name: t('cvAiApply'), exact: true })).toHaveCount(0); assert.equal(proposals.length, 1); assert.equal(variant.settings.headline, 'Manual teacher headline'); await scan('language-discard'); + await page.getByRole('button', { name: t('cvDocumentAiReview'), exact: true }).first().click(); await page.getByRole('button', { name: t('cvAiApply'), exact: true }).click(); await expect.poll(() => variant.version).toBe(6); + await page.getByRole('tab', { name: t('cvEditorContent'), exact: true }).click(); await expect(page.getByRole('textbox', { name: t('cvEditorHeadlineOverride'), exact: true })).toHaveValue('Reviewed teacher headline'); await scan('explicit-apply'); + assert.deepEqual(writes, ['notificationPreference', 'aiPreference', 'manualCvSave', 'aiPreference', 'explicitAiApply']); assert.deepEqual(proposals, ['en', 'nb-NO']); + report.journeys.push({ width, language, mode, manualFallback: 'PASS', languageDiscardWithoutApply: 'PASS', explicitTokenApply: 'PASS', aiSettingsKeyboardFocus: 'PASS' }); await context.close(); + } + assert.equal(report.screens.length, configurations.length * 6); assert.equal(report.journeys.length, configurations.length); assert.equal(report.writes.length, configurations.length * 5); assert.equal(report.proposals.length, configurations.length * 2); + assert.deepEqual(report.errors, []); assert.deepEqual(report.unexpectedWrites, []); assert.ok(report.blockedExternal.every(origin => origin === 'https://fonts.googleapis.com')); + console.log(`PASS:${report.journeys.length} controlled journeys,${report.screens.length} axe scans/captures.`); +} finally { + fs.writeFileSync(path.join(out, process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['All API, AI and preview results are synthetic fixtures. No model activation, semantic translation quality, backend end-to-end or physical PDF qualification.', 'No native device, screen reader, provider, integrated security, deployment or release acceptance.'] }, null, 2)); + await browser.close(); +} diff --git a/job-tracker-ui/src/components/ProFeatureNotice.tsx b/job-tracker-ui/src/components/ProFeatureNotice.tsx index 845cd385..c1674d33 100644 --- a/job-tracker-ui/src/components/ProFeatureNotice.tsx +++ b/job-tracker-ui/src/components/ProFeatureNotice.tsx @@ -2,6 +2,7 @@ import React, { useState } from "react"; import CloseIcon from "@mui/icons-material/Close"; import { Alert, Button, IconButton, Stack, Typography } from "@mui/material"; import { useOptionalI18n } from "../i18n/I18nProvider"; +import { useAccountPlan } from "../accountPlan"; type Props = { featureKey: string; @@ -15,6 +16,9 @@ function storageKey(featureKey: string) { export default function ProFeatureNotice({ featureKey, title, children }: Props) { const i18n = useOptionalI18n(); + const { plan, canUseAi } = useAccountPlan(); + const aiUnavailable = plan === "pro" && !canUseAi; + const displayTitle = aiUnavailable ? i18n?.t("aiUnavailableTitle") ?? "AI assistance is unavailable" : title; const [dismissed, setDismissed] = useState(() => { if (typeof window === "undefined") return false; try { @@ -40,15 +44,15 @@ export default function ProFeatureNotice({ featureKey, title, children }: Props) severity="info" action={( - - + + )} > - {title}{" "} - {children} + {displayTitle}{" "} + {aiUnavailable ? i18n?.t("aiUnavailableBody") ?? "You can continue editing manually. Review your AI settings and usage before trying again." : children} ); } diff --git a/job-tracker-ui/src/components/SettingsView.tsx b/job-tracker-ui/src/components/SettingsView.tsx index 46eaa363..c5b9cc37 100644 --- a/job-tracker-ui/src/components/SettingsView.tsx +++ b/job-tracker-ui/src/components/SettingsView.tsx @@ -10,6 +10,7 @@ import { InputLabel, MenuItem, Select, + Switch, Tab, Tabs, Typography, @@ -81,6 +82,7 @@ export default function SettingsView({ const rulesSession = useRef({ mounted: true, loading: false, saving: false }); const notificationSession = useRef({ mounted: true, loading: false, saving: false, generation: 0 }); const notificationBody = useRef(null); + const aiControls = useRef(null); const notificationRetryFocus = useRef(null); const currentTranslation = useRef(t); const rulesDirty = Boolean(rulesDraft && savedRules && RULE_FIELDS.some(field => rulesDraft[field] !== String(savedRules[field]))); @@ -223,6 +225,36 @@ export default function SettingsView({ }; const notificationReadStatus = (notificationError?.cause as { response?: { status?: number } } | undefined)?.response?.status; + const notificationCard = ( + + + {!notificationPrefs ? : + {notificationError?.action ? {getApiErrorMessage(notificationError.cause, t("settingsNotificationsSaveFailed"))} : null} + {notificationsDirty ? {t("assetsUnsavedChanges")}. {t("settingsNotificationsDraftScope")} : null} + setNotificationPrefs({ emailFollowUpRemindersEnabled: e.target.checked })} />} + label={t("settingsNotificationsFollowUpReminders")} + /> + {t("settingsNotificationsEmailBody")} + + + + + } + + + {t("settingsNotificationsDelivery")} + + + + + + ); + return ( @@ -234,6 +266,7 @@ export default function SettingsView({ onChange={(event) => selectSection(Number(event.target.value))} > {t("settingsTabGeneral")} + {t("settingsTabAutomation")} {t("settingsTabFollowUps")} {t("settingsTabNotifications")} {t("settingsTabBackup")} @@ -241,10 +274,11 @@ export default function SettingsView({ selectSection(v)} variant="scrollable" scrollButtons="auto" sx={{ display: { xs: "none", sm: "flex" }, mb: 1 }}> - - - - + + + + + {rulesDirty ? {t("assetsUnsavedChanges")}. {t("rulesDraftScope")} : null} @@ -331,7 +365,7 @@ export default function SettingsView({ - + - - - {!notificationPrefs ? : - {notificationError?.action ? {getApiErrorMessage(notificationError.cause, t("settingsNotificationsSaveFailed"))} : null} - {notificationsDirty ? {t("assetsUnsavedChanges")}. {t("settingsNotificationsDraftScope")} : null} - setNotificationPrefs({ emailFollowUpRemindersEnabled: e.target.checked })} />} - label={t("settingsNotificationsFollowUpReminders")} - /> - {t("settingsNotificationsEmailBody")} + {notificationCard} + + + + + + {t("settingsAutomationEmailSchedule")} - - + + + - } - - - {t("settingsNotificationsDelivery")} - - - - - + {t("settingsAutomationRulesScope")} + + {notificationCard} + diff --git a/job-tracker-ui/src/cv-builder-deep-link.test.tsx b/job-tracker-ui/src/cv-builder-deep-link.test.tsx index 56c5dfb4..7927f2b2 100644 --- a/job-tracker-ui/src/cv-builder-deep-link.test.tsx +++ b/job-tracker-ui/src/cv-builder-deep-link.test.tsx @@ -1107,6 +1107,16 @@ async function reviewDocumentSuggestion(result: string) { expect(request).not.toHaveProperty('targetId'); } +test('changing whole-document output language discards the previous-language review without applying it', async () => { + await reviewDocumentSuggestion(JSON.stringify([{ id: 'headline', items: ['Reviewed headline'] }])); + expect(await screen.findByText('Review 1 proposed change(s)')).toBeInTheDocument(); + fireEvent.mouseDown(screen.getByLabelText('Output language')); + fireEvent.click(screen.getByRole('option', { name: 'Norsk bokmål' })); + expect(screen.queryByText('Review 1 proposed change(s)')).not.toBeInTheDocument(); + expect(mockedApi.post.mock.calls.filter(([url]) => url === '/cv/variants/3/ai/apply')).toHaveLength(0); + expect(mockedApi.post.mock.calls.filter(([url]) => url === '/cv/ai/assist')).toHaveLength(1); +}); + test.each(['Apply', 'Reject'])('[PRES-C11 PRES-C07] whole-document AI %s changes only an explicitly accepted CV override', async action => { await reviewDocumentSuggestion(JSON.stringify([{ id: 'headline', items: ['Reviewed headline'] }])); expect(await screen.findByText('Review 1 proposed change(s)')).toBeInTheDocument(); diff --git a/job-tracker-ui/src/i18n/translations.ts b/job-tracker-ui/src/i18n/translations.ts index 7af4c539..98a5b383 100644 --- a/job-tracker-ui/src/i18n/translations.ts +++ b/job-tracker-ui/src/i18n/translations.ts @@ -2,6 +2,15 @@ export type UiLanguage = "en" | "nb"; export const translations = { en: { + aiUnavailableTitle: "AI assistance is unavailable", + aiUnavailableSettings: "Review AI settings", + aiUnavailableBody: "You can continue editing manually. Review your AI settings and usage before trying again.", + settingsTabAutomation: "Automation", + settingsAutomationBody: "Control email follow-up reminders here. Use the linked settings for AI assistance, waiting periods and individual saved-search alerts.", + settingsAutomationEmailSchedule: "When reminder delivery is available, due or upcoming applications are checked about every six hours. Emails go only to your confirmed account address, at most once per application per day.", + settingsAutomationAi: "AI privacy and usage", + settingsAutomationSearches: "Saved-search alerts", + settingsAutomationRulesScope: "Day thresholds influence reminders and optional automatic Ghosted status updates. They do not disable status processing. Saved-search alerts are controlled individually in Discover; AI privacy and usage remain in General.", documentsFilters: "Document filters", documentsJumpResults: "Jump to documents", documentsReturnFilters: "Return to document filters", @@ -3197,6 +3206,15 @@ export const translations = { coverAiReject: "Reject", }, nb: { + aiUnavailableTitle: "KI-hjelp er utilgjengelig", + aiUnavailableSettings: "Se KI-innstillinger", + aiUnavailableBody: "Du kan fortsette å redigere manuelt. Se gjennom KI-innstillingene og forbruket ditt før du prøver igjen.", + settingsTabAutomation: "Automatisering", + settingsAutomationBody: "Styr e-postpåminnelser om oppfølging her. Bruk de tilknyttede innstillingene for AI-hjelp, ventetider og varsler for hvert lagret søk.", + settingsAutomationEmailSchedule: "Når påminnelseslevering er tilgjengelig, kontrolleres forfalte eller kommende søknader omtrent hver sjette time. E-post sendes bare til den bekreftede kontoadressen din, høyst én gang per søknad per dag.", + settingsAutomationAi: "AI-personvern og forbruk", + settingsAutomationSearches: "Varsler for lagrede søk", + settingsAutomationRulesScope: "Daggrenser påvirker påminnelser og valgfrie automatiske statusoppdateringer til Ghostet. De deaktiverer ikke statusbehandlingen. Varsler for lagrede søk styres enkeltvis i Finn jobber; AI-personvern og forbruk ligger under Generelt.", documentsFilters: "Dokumentfiltre", documentsJumpResults: "Gå til dokumenter", documentsReturnFilters: "Tilbake til dokumentfiltre", diff --git a/job-tracker-ui/src/pro-feature-notice.test.tsx b/job-tracker-ui/src/pro-feature-notice.test.tsx index b1885aa6..71821ca4 100644 --- a/job-tracker-ui/src/pro-feature-notice.test.tsx +++ b/job-tracker-ui/src/pro-feature-notice.test.tsx @@ -3,9 +3,31 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import ProFeatureNotice from "./components/ProFeatureNotice"; +import { AccountPlanProvider } from "./accountPlan"; +import { I18nProvider } from "./i18n/I18nProvider"; beforeEach(() => window.sessionStorage.clear()); +test.each([ + ["en", "AI assistance is unavailable", "Review AI settings"], + ["nb", "KI-hjelp er utilgjengelig", "Se KI-innstillinger"], +])("keeps paid users on the manual path without an upgrade prompt (%s)", (language, title, action) => { + window.localStorage.setItem("uiLanguage", language); + render( + + + Upgrade body + + , + ); + expect(screen.getByText(title)).toBeInTheDocument(); + expect(screen.getByRole("link", { name: action })).toHaveAttribute("href", "/settings"); + expect(screen.queryByText("Upgrade body")).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole("button", { name: new RegExp(title) })); + expect(screen.queryByText(title)).not.toBeInTheDocument(); + window.localStorage.removeItem("uiLanguage"); +}); + test("shows a respectful upgrade action and remembers dismissal for the session", () => { const { unmount } = render( diff --git a/job-tracker-ui/src/settings-view.test.tsx b/job-tracker-ui/src/settings-view.test.tsx index 9f5581b5..b54e8faf 100644 --- a/job-tracker-ui/src/settings-view.test.tsx +++ b/job-tracker-ui/src/settings-view.test.tsx @@ -319,12 +319,31 @@ test('[PRES-S03] Rules draft updates do not refetch an unrelated notification pr }); function preferenceCopy(key: TranslationKey) { return translations[document.documentElement.lang === 'nb-NO' ? 'nb' : 'en'][key]; } +test.each(['en', 'nb'] as const)('%s Automation reuses the saved notification preference and explicit save', async language => { + localStorage.setItem('uiLanguage', language); renderView(); + fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabAutomation') })); + const panel = within(screen.getByRole('tabpanel', { name: preferenceCopy('settingsTabAutomation') })); + const toggle = await panel.findByRole('switch', { name: preferenceCopy('settingsNotificationsFollowUpReminders') }); + expect(toggle).toBeChecked(); fireEvent.click(toggle); expect(mockedApi.put).not.toHaveBeenCalled(); + fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabNotifications') })); + expect(await notificationPanel().findByRole('switch', { name: preferenceCopy('settingsNotificationsFollowUpReminders') })).not.toBeChecked(); + fireEvent.click(notificationPanel().getByRole('button', { name: preferenceCopy('settingsNotificationsSave') })); + await waitFor(() => expect(mockedApi.put).toHaveBeenCalledWith('/notification-settings', { emailFollowUpRemindersEnabled: false })); +}); + +test('Automation AI entry moves focus into existing settings without an AI request', async () => { + renderView(); fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabAutomation') })); + fireEvent.click(await screen.findByRole('button', { name: preferenceCopy('settingsAutomationAi') })); + await waitFor(() => expect(document.getElementById('settings-ai-controls')).toHaveFocus()); + expect(mockedApi.post).not.toHaveBeenCalled(); +}); + function notificationPanel() { return within(screen.getByRole('tabpanel', { name: preferenceCopy('settingsTabNotifications') })); } function notificationReads() { return mockedApi.get.mock.calls.filter(([url]) => url === '/notification-settings'); } function notificationWrites() { return mockedApi.put.mock.calls.filter(([url]) => url === '/notification-settings'); } async function openNotifications() { fireEvent.click(screen.getByRole('tab', { name: preferenceCopy('settingsTabNotifications') })); - return notificationPanel().findByRole('checkbox', { name: preferenceCopy('settingsNotificationsFollowUpReminders') }); + return notificationPanel().findByRole('switch', { name: preferenceCopy('settingsNotificationsFollowUpReminders') }); } async function preferenceLanguage(language: 'en' | 'nb') { await act(async () => { window.dispatchEvent(new StorageEvent('storage', { key: 'uiLanguage', newValue: language })); }); @@ -345,7 +364,7 @@ test('[P7-09 preferences] initial notification failure offers a single GET Retry act(() => { retry.focus(); fireEvent.click(retry); fireEvent.click(retry); }); expect(notificationReads()).toHaveLength(2); expect(mockedApi.put).not.toHaveBeenCalled(); await act(async () => pending.resolve({ data: { emailFollowUpRemindersEnabled: false } })); - expect(await notificationPanel().findByRole('checkbox', { name: translations.en.settingsNotificationsFollowUpReminders })).not.toBeChecked(); + expect(await notificationPanel().findByRole('switch', { name: translations.en.settingsNotificationsFollowUpReminders })).not.toBeChecked(); expect(notificationPanel().queryByRole('button', { name: 'Retry' })).not.toBeInTheDocument(); expect(notificationPanel().getByRole('group', { name: translations.en.settingsNotificationsTitle })).toHaveFocus(); expect(notificationReads()).toHaveLength(2); expect(mockedApi.put).not.toHaveBeenCalled(); @@ -359,7 +378,7 @@ test('[P7-09 preferences] notification drafts survive internal sections and loca const retained = await openNotifications(); expect(retained).not.toBeChecked(); expect(notificationReads()).toHaveLength(reads); expect(notificationPanel().getByRole('status')).toHaveTextContent(translations.nb.settingsNotificationsDraftScope); - await preferenceLanguage('en'); expect(notificationPanel().getByRole('checkbox', { name: translations.en.settingsNotificationsFollowUpReminders })).not.toBeChecked(); + await preferenceLanguage('en'); expect(notificationPanel().getByRole('switch', { name: translations.en.settingsNotificationsFollowUpReminders })).not.toBeChecked(); expect(notificationReads()).toHaveLength(reads); expect(mockedApi.put).not.toHaveBeenCalled(); }); @@ -375,7 +394,7 @@ test('[P7-09 preferences] one held notification save acknowledges its snapshot a expect(await openNotifications()).toBeChecked(); expect(notificationPanel().getByRole('status')).toHaveTextContent(translations.en.assetsUnsavedChanges); fireEvent.click(notificationPanel().getByRole('button', { name: translations.en.assetsDiscardChanges })); - expect(notificationPanel().getByRole('checkbox', { name: translations.en.settingsNotificationsFollowUpReminders })).not.toBeChecked(); + expect(notificationPanel().getByRole('switch', { name: translations.en.settingsNotificationsFollowUpReminders })).not.toBeChecked(); expect(notificationPanel().queryByText(translations.en.settingsNotificationsDraftScope)).not.toBeInTheDocument(); expect(notificationReads()).toHaveLength(1); expect(notificationWrites()).toHaveLength(1); }); @@ -387,7 +406,7 @@ test('[P7-09 preferences] failed notification save keeps its current-locale draf expect(await notificationPanel().findByRole('alert')).toHaveTextContent(translations.en.settingsNotificationsSaveFailed); const reads = notificationReads().length; await preferenceLanguage('nb'); expect(notificationPanel().getByRole('alert')).toHaveTextContent(translations.nb.settingsNotificationsSaveFailed); - expect(notificationPanel().getByRole('checkbox', { name: translations.nb.settingsNotificationsFollowUpReminders })).not.toBeChecked(); + expect(notificationPanel().getByRole('switch', { name: translations.nb.settingsNotificationsFollowUpReminders })).not.toBeChecked(); expect(notificationPanel().queryByRole('button', { name: translations.nb.retry })).not.toBeInTheDocument(); fireEvent.click(notificationPanel().getByRole('button', { name: translations.nb.settingsNotificationsSave })); await waitFor(() => expect(notificationPanel().queryByRole('alert')).not.toBeInTheDocument()); @@ -403,7 +422,7 @@ test('[P7-09 preferences] discarding a notification draft leaves the independent renderView(); fireEvent.change(await openRules(), { target: { value: '5' } }); fireEvent.click(await openNotifications()); fireEvent.click(notificationPanel().getByRole('button', { name: translations.en.assetsDiscardChanges })); - expect(notificationPanel().getByRole('checkbox', { name: translations.en.settingsNotificationsFollowUpReminders })).toBeChecked(); + expect(notificationPanel().getByRole('switch', { name: translations.en.settingsNotificationsFollowUpReminders })).toBeChecked(); expect(notificationPanel().queryByText(translations.en.settingsNotificationsDraftScope)).not.toBeInTheDocument(); fireEvent.click(screen.getByRole('tab', { name: 'Follow-ups' })); expect(screen.getByLabelText('Applied: follow-up days')).toHaveValue(5); diff --git a/job-tracker-ui/src/views/CvBuilderEditor.tsx b/job-tracker-ui/src/views/CvBuilderEditor.tsx index 05f702e8..9a09f43b 100644 --- a/job-tracker-ui/src/views/CvBuilderEditor.tsx +++ b/job-tracker-ui/src/views/CvBuilderEditor.tsx @@ -892,7 +892,7 @@ function DocumentAiTab({ settings, outline, onGenerate, onAccept }: CvAiCallback setProposal(null); setBusy(null); return () => { requestId.current += 1; }; - }, [sourceKey, settings.language, canUseAi]); + }, [sourceKey, settings.language, targetLanguage, canUseAi]); const discard = () => { requestId.current += 1;