Remove 7 now-stale IDENTICAL_VALUE_ALLOWLIST entries (audit.title,
auth.roleOperationsManager, auth.roleRentalEmployee,
demo.scenarios.startScenario, demo.scenarios.roles.operations_manager/
rental_employee, navigation.items.audit) now that they are genuinely
translated -- their old comments describing them as "deliberately
untranslated" were no longer true.
Add two new checks: one closing the embedded-English/Dutch-substring
blind spot the whole-string identity test structurally cannot catch (a
mid-sentence phrase surviving inside otherwise-translated prose), one
asserting no locale file contains "MobilityOps" or the word "PoC".
- fleet-ops-correction.spec.ts: opens every main route in all 3 languages, asserting
no console errors, correct html[lang], and a real non-empty page heading (key parity
across locale files is already proven structurally elsewhere, so this focuses on what
only a live render can catch).
- i18n-coverage.spec.ts: a static scan for hardcoded JSX text bypassing t(...). A naive
`>text<` regex falsely flagged TypeScript generics everywhere (`useState<string |
null>(null)` was read as a "JSX tag" spanning to the next unrelated `>`) -- fixed by
requiring the closing tag name to backreference the opening one
(`<Tag>...</Tag>`), which generics can never satisfy. Verified against both false
positives (passes clean on the current codebase) and false negatives (deliberately
injected and reverted a hardcoded string to confirm it's caught).
Known pre-existing flake (unrelated to this branch, not touched by it): "logout
invalidates the server session so a refresh returns to login" in
interactive-elements.spec.ts occasionally fails only in the full sequential run,
never in isolation -- AuthContext.logout() clears local state and redirects before
awaiting the server-side cookie-clearing POST, a narrow race no human interaction
speed would ever hit. Noted as a known limitation, not fixed (out of this branch's
scope).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add a single shared, pure vehicle-status evaluator (app/services/vehicle_status.py)
used identically by the data-quality scanner, a new non-mutating status-recommendation
preview endpoint, and a transactional apply endpoint with optimistic-concurrency token
revalidation -- eliminates the old opaque "calculate and apply" action and the unsafe
"maintenance + active booking -> auto rented" shortcut. Frontend
DataQualityIssueDetail.tsx now shows a review/decide/confirm panel with localized
why/evidence/consequence text in nl-BE/en-GB/fr-BE, with an exact "Change status to
<status>" confirm action per the brief.
- Fix MO-016 issue-order dependency: resolving the booking-overlap issue before vs.
after the status-conflict issue now converges on the same final vehicle status,
proven by test_mo_016_status_conflict_recommendation_is_order_independent.
- Make "Fleet Ops" a non-localizable brand constant (frontend/src/product.ts,
backend PRODUCT_NAME) via {{productName}} interpolation everywhere the brand name
appeared in locale prose; add a permanent test guarding against a translation file
ever defining the brand name or an "appName" key again.
- Convert dynamic backend prose to stable message codes + params: return status
reasons, audit field/actor-type labels, automation last_error, and search
section/vehicle/booking/issue results all now carry codes the frontend localizes,
with raw technical text demoted to a "Technical details" disclosure.
- docs/fleet-ops-correction/: gap audit, i18n inventory, and the vehicle-status
decision table documenting the evaluator's rules and safe-status principles.
148 backend tests + Ruff + mypy green; Alembic migration verified upgrade/downgrade;
frontend tsc/build and the i18n-coverage Playwright suite green.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rebrands the product from MobilityOps to Fleet Ops across the UI, backend defaults and
knowledge base, and makes nl-BE/en-GB/fr-BE full first-class languages: i18next with
eager-bundled per-namespace resources, a persisted accessible language switcher (topbar
and mobile drawer), locale-aware date/number formatting, and a coverage test that fails
the build on any missing or empty translation key.
Backend dynamic content (demo scenarios, blocked-reason text, integration status) moves
from fixed English/Dutch prose to stable message codes + params so the frontend can
localize it; the demo knowledge base gains a fully translated NL/EN/FR procedure corpus
(11 documents each) with per-language retrieval and localized evidence-state messages.
The Demo Guide becomes breakpoint-adaptive: a docked rail on extra-wide desktop, a
floating panel that auto-collapses to a persistent, closable progress chip on standard
desktop/tablet, and a collapsed/half/full bottom sheet on mobile -- with scroll+focus+
highlight on "go to this step", Escape handling, and reduced-motion support.
The Data Quality Workbench gets accessible choice-card decisions with a clear primary/
secondary/tertiary action hierarchy; the Automation ledger groups repeated successes and
uses meaningful short refs; the Audit trail groups events by correlation id with human
action labels and readable before/after diffs. Attention Queue, Today's movements,
Vehicles, Bookings and Data Quality rows are fully clickable (stretched-link pattern)
with independent secondary links, keyboard support and mobile touch targets.
Fixes a topbar overflow on mobile caused by the new language switcher (moved into the
mobile drawer at <=960px) and two dangling aria-labelledby references introduced this
session. Updates all affected Playwright specs for the new nl-BE default and the new
Audit/DemoGuide DOM structure, and adds new i18n-coverage, demo-guide-adaptive and
clickable-rows specs. 131 backend tests, Ruff and mypy, and 71 Playwright tests pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>