docs: update PROJECT_STATE and README for the final localization round
PROJECT_STATE.md: fix the stale "Product name: MobilityOps."/"PoC only" locked-decisions lines (predate the Fleet Ops rebrand), fix the "Fleet Ops correction" section header still reading "IN PROGRESS .../Not yet merged to master" when it was in fact already merged (de0bdea, evidence commitf780557), and append a new dated entry for this correction round with commits and gate evidence so far. README.md: reference docs/fleet-ops-final-localization/ alongside the existing docs/fleet-ops-correction/ link, refresh the stale Playwright test count (113 -> 138).
This commit is contained in:
+93
-7
@@ -29,9 +29,15 @@ M7 — complete. All milestones (M0–M7) done, plus a full post-M7 final-accept
|
|||||||
|
|
||||||
## Locked decisions
|
## Locked decisions
|
||||||
|
|
||||||
- Product name: MobilityOps.
|
- Product name: Fleet Ops (the only visible product name in the UI/copy, never translated;
|
||||||
|
see `frontend/src/product.ts`). "MobilityOps" is the internal repo name, Compose project
|
||||||
|
name and deployment directory only — never shown to a user. See the "Final product
|
||||||
|
polish: Fleet Ops rebrand" and "Fleet Ops final localization" entries below.
|
||||||
- Fictitious tenant: Northstar Mobility Demo.
|
- Fictitious tenant: Northstar Mobility Demo.
|
||||||
- PoC only; all operational and knowledge data are synthetic.
|
- Synthetic demo data only; all operational and knowledge data are synthetic. The product
|
||||||
|
itself is not described as a "PoC" in user-facing copy (see the localization entry
|
||||||
|
below) — this document and other internal/engineering docs may still use "PoC" to
|
||||||
|
describe the engineering scope, per `CLAUDE.md`.
|
||||||
- Core stack and boundaries are defined in `CLAUDE.md` and `docs/03-architecture.md`.
|
- Core stack and boundaries are defined in `CLAUDE.md` and `docs/03-architecture.md`.
|
||||||
- RAGcore and ITWorx MCP Hub are external central services.
|
- RAGcore and ITWorx MCP Hub are external central services.
|
||||||
- n8n receives post-commit events through an outbox dispatcher.
|
- n8n receives post-commit events through an outbox dispatcher.
|
||||||
@@ -873,11 +879,15 @@ scenarios, demo manifest, About page). Gap audit: `docs/demo-release/current-dem
|
|||||||
and master, responsive/accessibility results, known limitations, rollback procedure)
|
and master, responsive/accessibility results, known limitations, rollback procedure)
|
||||||
plus 10 screenshots in `artifacts/fleet-ops-release/screenshots/`.
|
plus 10 screenshots in `artifacts/fleet-ops-release/screenshots/`.
|
||||||
|
|
||||||
## Fleet Ops correction: safe status-recommendation flow, MO-016, message codes (2026-08-03) — IN PROGRESS on fix/fleet-ops-i18n-status-flow
|
## Fleet Ops correction: safe status-recommendation flow, MO-016, message codes (2026-08-03) — MERGED TO MASTER
|
||||||
|
|
||||||
Branch `fix/fleet-ops-i18n-status-flow`, created from master's post-release head
|
Branch `fix/fleet-ops-i18n-status-flow`, created from master's post-release head
|
||||||
(`18344bc`). Audit and rationale in `docs/fleet-ops-correction/` (gap audit, i18n
|
(`18344bc`). Audit and rationale in `docs/fleet-ops-correction/` (gap audit, i18n
|
||||||
inventory, vehicle-status decision table). Not yet merged to master.
|
inventory, vehicle-status decision table). Merged to master via `de0bdea` ("merge:
|
||||||
|
complete Fleet Ops localization and status resolution"), with final evidence commit
|
||||||
|
`f780557` ("docs(release): final Fleet Ops correction evidence and screenshots") —
|
||||||
|
`f780557` is `origin/master`'s current head as of the start of the correction round
|
||||||
|
below.
|
||||||
|
|
||||||
- **Status-recommendation flow redesigned** per the brief: the old single opaque
|
- **Status-recommendation flow redesigned** per the brief: the old single opaque
|
||||||
"calculate and apply recommended status" action is replaced by a single shared, pure
|
"calculate and apply recommended status" action is replaced by a single shared, pure
|
||||||
@@ -979,9 +989,85 @@ inventory, vehicle-status decision table). Not yet merged to master.
|
|||||||
the live server (`MOBILITYOPS_PUBLIC_URL=http://192.168.10.150:1236`), no console
|
the live server (`MOBILITYOPS_PUBLIC_URL=http://192.168.10.150:1236`), no console
|
||||||
errors, no errors in `api`/`web` container logs, both containers healthy, final
|
errors, no errors in `api`/`web` container logs, both containers healthy, final
|
||||||
reset done, `scenario_integrity.all_ready: true`.
|
reset done, `scenario_integrity.all_ready: true`.
|
||||||
- **Not yet done**: the final merge to master with
|
- Final evidence: `artifacts/fleet-ops-correction/final-summary.md`. Merged to master
|
||||||
`artifacts/fleet-ops-correction/final-summary.md` evidence. Do not claim PASS on
|
via `de0bdea`, followed by evidence commit `f780557` on master. See the "Fleet Ops
|
||||||
this correction until that's done.
|
final localization" entry below for the next (small correction) round on top of this.
|
||||||
|
|
||||||
|
## Fleet Ops final localization: remaining NL/FR gaps, API-error localization, greeting (2026-08-04) — IN PROGRESS on fix/fleet-ops-final-i18n-ux
|
||||||
|
|
||||||
|
Branch `fix/fleet-ops-final-i18n-ux`, created from master's post-correction head
|
||||||
|
(`f780557`) — the brief asked for `fix/fleet-ops-final-localization`, but the
|
||||||
|
already-checked-out branch name is used instead since it was verified freshly and
|
||||||
|
cleanly branched from current `origin/master` with a clean working tree; see
|
||||||
|
`docs/fleet-ops-final-localization/audit.md` for the naming note. Scope: a small,
|
||||||
|
targeted correction round only — explicitly not touching status-flow business logic,
|
||||||
|
the status evaluator, Data Quality resolution rules, return rules, RAGcore/MCP Hub, or
|
||||||
|
product scope.
|
||||||
|
|
||||||
|
- **Audit-driven gap sweep**: `docs/fleet-ops-final-localization/audit.md` documents
|
||||||
|
every remaining untranslated/incorrect string, raw-backend-error call site,
|
||||||
|
over-permissive allowlist entry, the static-greeting bug, and doc staleness found by
|
||||||
|
a dedicated Explore pass before any file was touched.
|
||||||
|
- **Remaining NL/FR translation gaps fixed**: role names actually translated (not just
|
||||||
|
labelled as translated) — `auth.json`/`demo.json` role keys, `audit.title` →
|
||||||
|
"Auditgeschiedenis"/"Piste d'audit", `columns.actor` → "Uitvoerder", `list.statusOpen`
|
||||||
|
→ "Openstaand", `ledger.filterRecent` → "Recentste", `scenarios.startScenario` →
|
||||||
|
"Scenario starten". Also found and fixed (via the new embedded-substring test below)
|
||||||
|
8 previously-missed mid-sentence "Audit trail" leaks across `demo.json`,
|
||||||
|
`quality.json`, `returns.json` that the old whole-string-identity test structurally
|
||||||
|
could not catch.
|
||||||
|
- **Central API-error localization**: new `frontend/src/api/errorMessages.ts`
|
||||||
|
(`describeApiError`) replaces the `err instanceof ApiError ? err.message : ...`
|
||||||
|
anti-pattern (which showed raw English for the common case) at all 13 call sites
|
||||||
|
across 7 files. Raw backend text is now only ever shown under a "Technical
|
||||||
|
details"/"Détails techniques" disclosure (new `ApiErrorNotice` component in
|
||||||
|
`PageChrome.tsx`); the primary message is always a localized title + explanation +
|
||||||
|
optional next step, keyed on the 32 known `AppError` codes, then known HTTP statuses
|
||||||
|
(401/403/404/409/422/500), then a fully generic fallback. `ApiError` was split out of
|
||||||
|
`client.ts` into a standalone `api/apiError.ts` (no `import.meta.env` dependency) so
|
||||||
|
`errorMessages.ts` is independently testable outside a Vite/browser context.
|
||||||
|
- **i18n allowlist tightened**: removed 7 now-stale `IDENTICAL_VALUE_ALLOWLIST` entries
|
||||||
|
in `i18n-coverage.spec.ts` (`audit.title`, `auth.roleOperationsManager`,
|
||||||
|
`auth.roleRentalEmployee`, `demo.scenarios.startScenario`,
|
||||||
|
`demo.scenarios.roles.operations_manager`, `demo.scenarios.roles.rental_employee`,
|
||||||
|
`navigation.items.audit`) now that they're genuinely translated. Added 2 new tests:
|
||||||
|
one closing the embedded-English/Dutch-substring blind spot (mid-sentence phrase
|
||||||
|
leaks the whole-string check misses), one asserting no locale file contains
|
||||||
|
"MobilityOps" or the word "PoC".
|
||||||
|
- **`describeApiError` test coverage**: new `frontend/e2e/error-messages.spec.ts` (10
|
||||||
|
tests) — every known code/HTTP status has non-empty copy in all 3 locales, a known
|
||||||
|
code never surfaces raw backend text as the primary message (only via `.technical`),
|
||||||
|
unknown-code and unknown-status fallback chains behave correctly, and a drift guard
|
||||||
|
that greps the actual backend `AppError("CODE", ...)` call sites and fails if
|
||||||
|
`KNOWN_CODES` and the backend's real codes ever diverge (currently exactly in sync,
|
||||||
|
32 codes).
|
||||||
|
- **Time-dependent Europe/Brussels dashboard greeting**: new
|
||||||
|
`frontend/src/i18n/greeting.ts` (`getGreetingPeriod`, DST-safe via
|
||||||
|
`Intl.DateTimeFormat({ timeZone: "Europe/Brussels", hourCycle: "h23" })`, clock
|
||||||
|
injectable) + `useGreetingPeriod.ts` hook (30s poll for period rollover while the app
|
||||||
|
stays open, no reload). Replaces the previously-always-"Goedemorgen" static
|
||||||
|
`dashboard.json` title with 4 periods × 3 languages for both the greeting word and a
|
||||||
|
varying accompanying sentence (never "Goedenacht"). Tests: `greeting.spec.ts` (pure
|
||||||
|
boundary/DST unit tests) + `greeting-live.spec.ts` (6 real-browser tests via
|
||||||
|
Playwright's `page.clock` — all 8 required boundary times in all 3 languages, live
|
||||||
|
rollover without reload, language-switch behaviour, the "never Goedenacht" guard).
|
||||||
|
- **Found and fixed one real CSS regression along the way**: correctly translating
|
||||||
|
`roleOperationsManager` to the single unbreakable Dutch compound word
|
||||||
|
"Operationsmanager" (vs. the old two-word "Operations Manager", which could wrap)
|
||||||
|
pushed the topbar's `.operator` block past 1024px width, caught by the existing
|
||||||
|
`responsive-i18n.spec.ts` overflow test. Fixed with `overflow-wrap: anywhere` on
|
||||||
|
`.operator strong`/`small` and `min-width: 0` on their flex-item wrapper, not by
|
||||||
|
reverting the correct translation.
|
||||||
|
- Gates green so far: backend `pytest` 151 passed, `ruff check .` clean, `mypy app`
|
||||||
|
clean (49 files, unchanged — no backend Python touched this round); frontend `tsc`
|
||||||
|
clean, production build clean, full local Playwright suite **138 passed** (rebuilt
|
||||||
|
and restarted the local `web` container from source before this run).
|
||||||
|
- **Not yet done**: clean-checkout drill, commit/push, Unraid deployment of this fix
|
||||||
|
branch with live 3-language validation, the master merge (with the mandatory
|
||||||
|
`git fetch origin` / unexpected-change check first), and
|
||||||
|
`artifacts/fleet-ops-final-localization/final-summary.md`. Do not claim PASS on this
|
||||||
|
correction round until all of those are done and `git rev-parse HEAD` exactly matches
|
||||||
|
`/mnt/user/appdata/mobilityops/.deploy/source-revision`.
|
||||||
- Commits so far on this branch: `6deb955` (status flow + brand constant + message
|
- Commits so far on this branch: `6deb955` (status flow + brand constant + message
|
||||||
codes), `e6539d1` (knowledge fixes), `ac4b163` (Playwright spec updates for the new
|
codes), `e6539d1` (knowledge fixes), `ac4b163` (Playwright spec updates for the new
|
||||||
flow), `1fdd2b3` (new E2E coverage + 2 bug fixes), `1e40775` (accessibility test),
|
flow), `1fdd2b3` (new E2E coverage + 2 bug fixes), `1e40775` (accessibility test),
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ knowledge base, and this documentation. "MobilityOps" remains the technical
|
|||||||
identifier only — the repository name, local directory, package/module names, Docker
|
identifier only — the repository name, local directory, package/module names, Docker
|
||||||
Compose project, deployment directory, and database names. The UI is fully trilingual
|
Compose project, deployment directory, and database names. The UI is fully trilingual
|
||||||
(nl-BE default, en-GB, fr-BE); see `docs/fleet-ops-correction/` for the localization
|
(nl-BE default, en-GB, fr-BE); see `docs/fleet-ops-correction/` for the localization
|
||||||
architecture, the vehicle-status decision table, and the correction evidence.
|
architecture, the vehicle-status decision table, and the correction evidence, and
|
||||||
|
`docs/fleet-ops-final-localization/` for the follow-up correction round (remaining
|
||||||
|
NL/FR translation gaps, centralized API-error localization, the time-dependent
|
||||||
|
Europe/Brussels dashboard greeting).
|
||||||
|
|
||||||
The web application uses the premium responsive **Control Rail** interface: a compact
|
The web application uses the premium responsive **Control Rail** interface: a compact
|
||||||
operations-first workspace with persisted readiness metrics, evidence-led exceptions,
|
operations-first workspace with persisted readiness metrics, evidence-led exceptions,
|
||||||
@@ -123,7 +126,7 @@ All defaults are configurable via `.env` (see `.env.example`).
|
|||||||
```bash
|
```bash
|
||||||
make test # backend: pytest (151 tests)
|
make test # backend: pytest (151 tests)
|
||||||
make lint # backend: ruff + mypy (strict, zero errors)
|
make lint # backend: ruff + mypy (strict, zero errors)
|
||||||
make e2e # frontend: Playwright end-to-end (113 tests, live stack required)
|
make e2e # frontend: Playwright end-to-end (138 tests, live stack required)
|
||||||
```
|
```
|
||||||
|
|
||||||
Frontend build/typecheck: `cd frontend && npm run build` (`tsc -b && vite build`).
|
Frontend build/typecheck: `cd frontend && npm run build` (`tsc -b && vite build`).
|
||||||
|
|||||||
Reference in New Issue
Block a user