docs: update OpenAPI contract, README branding, and PROJECT_STATE for the correction milestone
- contracts/openapi.yaml: title is now "Fleet Ops API"; documents the new status-recommendation preview endpoint and the apply endpoint's request body (recommendation_token) and full error-code set; notes the search endpoint's code+params response shape. - README.md: title and intro now say Fleet Ops, with an explicit note on the Fleet Ops (visible)/MobilityOps (technical identifier) naming split; refreshed stale test counts (151 backend, 108 Playwright). - PROJECT_STATE.md: full progress record for the in-progress correction milestone, including what's done, what bugs were found and fixed, and what's explicitly not yet done (i18n test-strengthening 11D/E/F, clean-checkout drill, Unraid deployment, merge to master). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1e407754e6
commit
a7ac5ed9d0
@@ -872,3 +872,78 @@ scenarios, demo manifest, About page). Gap audit: `docs/demo-release/current-dem
|
||||
test results, clean-checkout result, deployment evidence for both the feature branch
|
||||
and master, responsive/accessibility results, known limitations, rollback procedure)
|
||||
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
|
||||
|
||||
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
|
||||
inventory, vehicle-status decision table). Not yet merged to master.
|
||||
|
||||
- **Status-recommendation flow redesigned** per the brief: the old single opaque
|
||||
"calculate and apply recommended status" action is replaced by a single shared, pure
|
||||
evaluator (`backend/app/services/vehicle_status.py::evaluate_vehicle_status`) used
|
||||
identically by the scanner, a new non-mutating preview endpoint
|
||||
(`POST .../status-recommendation`), and a transactional apply endpoint
|
||||
(`POST .../apply-recommended-status`) that locks the row, recomputes facts, rejects a
|
||||
stale `recommendation_token` (optimistic concurrency), refuses unsafe/manual-review
|
||||
recommendations, and re-validates post-write before resolving the issue. Frontend
|
||||
`DataQualityIssueDetail.tsx` shows "Review recommendation" → a decision panel
|
||||
(current/recommended status, why, evidence, consequences, localized in all 3
|
||||
languages) → an exact "Change status to <status>" confirm action → result, with a
|
||||
distinct "Manual review required" state offering no generic apply button.
|
||||
- Fixed the real unsafe shortcut this evaluator exists to eliminate: "maintenance +
|
||||
active booking" no longer auto-recommends "rented" (current status is itself now a
|
||||
blocking fact), and "maintenance with nothing else wrong" no longer auto-clears to
|
||||
"available" (no fact proves maintenance is actually finished — that release stays a
|
||||
manual decision).
|
||||
- **MO-016 order independence**: order independence does not mean "same final status
|
||||
regardless of order" — resolving the booking overlap first genuinely removes the
|
||||
conflict, correctly leaving nothing to apply. What must (and does) hold either way:
|
||||
the recommendation always reflects real current facts, and nothing unsafe is ever
|
||||
applied (never "rented"). Verified by both a backend test
|
||||
(`test_mo_016_status_conflict_recommendation_is_order_independent`, explicitly scoped
|
||||
to MO-016/DQ-DEMO-STATUS after finding the original version wasn't) and a browser-level
|
||||
Playwright test in both orders.
|
||||
- **"Fleet Ops" is a non-localizable brand constant** (`frontend/src/product.ts`,
|
||||
backend `PRODUCT_NAME`), wired via `{{productName}}` interpolation everywhere the
|
||||
brand appeared in locale prose; a permanent test fails the build if any locale file
|
||||
ever defines the brand name or an `appName` key again.
|
||||
- **Dynamic backend prose converted to message codes + params**: return status reasons,
|
||||
audit field/actor-type labels, automation `last_error` (new `last_error_code` column,
|
||||
migration `799d8800e241`), and search results (sections/vehicles/bookings/issues) all
|
||||
now carry stable codes the frontend localizes; raw technical text is demoted to a
|
||||
"Technical details" disclosure everywhere.
|
||||
- **Knowledge-base fixes**: the demo provider's tokenizer silently dropped accented
|
||||
characters (`[a-z0-9]+` split "véhicule" into "v"+"hicule"), breaking French
|
||||
retrieval broadly; fixed to include the Latin-1 accented range. Also reweighted
|
||||
section scoring so a body match (real substance) outranks a heading/title match (a
|
||||
shallow structural hint) — the old weighting misranked the damage procedure behind
|
||||
an unrelated document for the brief's exact validation question in all 3 languages.
|
||||
Removed leftover "MobilityOps"/"PoC" mentions from 9 procedure documents (knowledge
|
||||
prose is visible content, missed by the earlier rebrand).
|
||||
- New `frontend/e2e/fleet-ops-correction.spec.ts` (14 tests) covers branding in 3
|
||||
languages, language persistence, the full status-recommendation flow (non-mutating
|
||||
preview, exact confirm text, manual review, stale-token rejection), MO-016 order
|
||||
independence, trilingual knowledge grounding, and localized audit/automation. Writing
|
||||
it surfaced and fixed two real bugs: the frontend conflated "no conflict" with
|
||||
"manual review required" (both carry `safe_to_apply: false`), and the original
|
||||
MO-016 backend test never actually targeted MO-016's own issue.
|
||||
- Added a keyboard/reduced-motion/no-color-only-status accessibility test for the new
|
||||
status-decision panel; added `aria-live="polite"` to the panel so the applied
|
||||
confirmation is announced.
|
||||
- `contracts/openapi.yaml` and `README.md` updated: title is "Fleet Ops", the new
|
||||
status-recommendation endpoint documented, apply-recommended-status's request body
|
||||
and error codes documented, search endpoint's code+params shape documented, README
|
||||
states the Fleet Ops/MobilityOps naming split explicitly and refreshes stale test
|
||||
counts (151 backend, 108 Playwright).
|
||||
- Gates green so far: 151 backend tests, Ruff, mypy, Alembic upgrade/downgrade
|
||||
verified, frontend `tsc`/build, full 108-test Playwright suite (rebuilt `api`+`web`
|
||||
containers each time before testing).
|
||||
- **Not yet done**: sections 11D/E/F of the i18n test-strengthening brief (hardcoded-
|
||||
JSX lint check, broader dynamic-content localization tests, a 3-language route
|
||||
matrix), the clean-checkout drill, Unraid deployment + live 3-language validation,
|
||||
and the final merge to master with `artifacts/fleet-ops-correction/final-summary.md`
|
||||
evidence. Do not claim PASS on this correction until all of those are done.
|
||||
- Commits so far on this branch: `6deb955` (status flow + brand constant + message
|
||||
codes), `e6539d1` (knowledge fixes), `ac4b163` (Playwright spec updates for the new
|
||||
flow), `1fdd2b3` (new E2E coverage + 2 bug fixes), `1e40775` (accessibility test).
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
# MobilityOps
|
||||
# Fleet Ops
|
||||
|
||||
**Connected operations for vehicle rental and service teams.**
|
||||
|
||||
MobilityOps is a working proof of concept for a fictitious mobility company. It combines vehicle and booking operations, a controlled vehicle-return workflow, data-quality review, RAGcore-backed internal knowledge, n8n orchestration and read-only tools published through ITWorx MCP Hub.
|
||||
Fleet Ops is a working proof of concept for a fictitious mobility company. It combines vehicle and booking operations, a controlled vehicle-return workflow, data-quality review, RAGcore-backed internal knowledge, n8n orchestration and read-only tools published through ITWorx MCP Hub.
|
||||
|
||||
**Naming:** "Fleet Ops" is the product's visible name everywhere in the UI, the demo
|
||||
knowledge base, and this documentation. "MobilityOps" remains the technical
|
||||
identifier only — the repository name, local directory, package/module names, Docker
|
||||
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
|
||||
architecture, the vehicle-status decision table, and the correction evidence.
|
||||
|
||||
The web application uses the premium responsive **Control Rail** interface: a compact
|
||||
operations-first workspace with persisted readiness metrics, evidence-led exceptions,
|
||||
@@ -114,9 +121,9 @@ All defaults are configurable via `.env` (see `.env.example`).
|
||||
## Quality gates
|
||||
|
||||
```bash
|
||||
make test # backend: pytest (127 tests)
|
||||
make test # backend: pytest (151 tests)
|
||||
make lint # backend: ruff + mypy (strict, zero errors)
|
||||
make e2e # frontend: Playwright end-to-end (56 tests, live stack required)
|
||||
make e2e # frontend: Playwright end-to-end (108 tests, live stack required)
|
||||
```
|
||||
|
||||
Frontend build/typecheck: `cd frontend && npm run build` (`tsc -b && vite build`).
|
||||
|
||||
+50
-6
@@ -1,8 +1,11 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: MobilityOps API
|
||||
title: Fleet Ops API
|
||||
version: 0.1.0
|
||||
description: Contract baseline for the MobilityOps proof of concept.
|
||||
description: >-
|
||||
Contract baseline for the Fleet Ops demo. "Fleet Ops" is the visible product name;
|
||||
"mobilityops" remains the technical identifier for the repository, deployment
|
||||
directory, database, and internal service/health identifiers only.
|
||||
servers:
|
||||
- url: http://localhost:8128
|
||||
paths:
|
||||
@@ -181,26 +184,67 @@ paths:
|
||||
description: Wrong rule type, issue not open, or overlap still present
|
||||
'422':
|
||||
description: booking_ref not one of the overlapping bookings
|
||||
/api/v1/data-quality/issues/{public_ref}/status-recommendation:
|
||||
post:
|
||||
operationId: previewVehicleStatusRecommendation
|
||||
description: >-
|
||||
vehicle_status_conflict only. Non-mutating: computes the recommendation from
|
||||
the same shared evaluator the scanner and apply endpoint use
|
||||
(app.services.vehicle_status.evaluate_vehicle_status), without resolving the
|
||||
issue, writing an audit event, or queuing automation. Safe to call repeatedly
|
||||
-- see docs/fleet-ops-correction/vehicle-status-decision-table.md.
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/PublicRef'
|
||||
responses:
|
||||
'200':
|
||||
description: >-
|
||||
Current/recommended status, recommendation code, safe_to_apply,
|
||||
manual_review_required, the underlying facts, and a recommendation_token
|
||||
the apply endpoint revalidates against.
|
||||
'409':
|
||||
description: Wrong rule type, issue not open, or vehicle not found
|
||||
/api/v1/data-quality/issues/{public_ref}/apply-recommended-status:
|
||||
post:
|
||||
operationId: applyRecommendedVehicleStatus
|
||||
description: >-
|
||||
vehicle_status_conflict only. Applies the one authoritative recommendation
|
||||
function's output and re-validates before resolving.
|
||||
function's output within one transaction: locks the issue and vehicle,
|
||||
recomputes the recommendation from fresh facts, rejects the request if the
|
||||
supplied recommendation_token no longer matches (RECOMMENDATION_STALE), refuses
|
||||
an unsafe/manual-review recommendation (MANUAL_REVIEW_REQUIRED) or a
|
||||
recommendation with nothing to apply (NO_CONFLICT_DETECTED), then re-validates
|
||||
the same evaluator post-write before resolving the issue.
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/PublicRef'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [recommendation_token]
|
||||
properties:
|
||||
recommendation_token:
|
||||
type: string
|
||||
description: The token from the most recent status-recommendation preview call.
|
||||
responses:
|
||||
'200':
|
||||
description: Applied status, reason and the resolved issue
|
||||
description: Applied status, reason code and the resolved issue
|
||||
'409':
|
||||
description: Wrong rule type, issue not open, or no conflict detected
|
||||
description: >-
|
||||
Wrong rule type, issue not open, vehicle not found, stale recommendation
|
||||
token, manual review required, no conflict detected, or the applied status
|
||||
did not resolve the conflict on re-validation
|
||||
/api/v1/search:
|
||||
get:
|
||||
operationId: search
|
||||
description: >-
|
||||
Bounded typed results (vehicle, booking, data_quality_issue, section).
|
||||
Data-quality and manager-only sections are filtered server-side by role.
|
||||
Customers are never returned -- no customer detail route exists.
|
||||
Customers are never returned -- no customer detail route exists. Every result's
|
||||
`label` is a stable public_ref/section id (never translatable prose); `detail_code`
|
||||
(+ optional `detail_params` for data values like make/model/location) is what the
|
||||
frontend localizes -- the backend never emits English/Dutch/French sentences here.
|
||||
parameters:
|
||||
- in: query
|
||||
name: q
|
||||
|
||||
Reference in New Issue
Block a user