diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 08ed384..d13f15a 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -2672,3 +2672,28 @@ evidence yet." - Exact next action: commit and push M29, create and verify a live database backup, deploy the committed archive to Unraid, then run live health, migration, browser and acceptance checks before recording the final production evidence. + +## M30 — recruiter polish production acceptance (2026-08-10) + +- Pushed M29 to Gitea `master` as `29325b6`, created and verified pre-deployment backup + `mobilityops-20260810T161659Z.dump`, and deployed that exact source archive while + preserving `.env`, volumes and the existing central n8n. Deployment revision is + `29325b6c2775806080dc40e1988634d6ceb300a0`; Alembic is `b913a72e8c14 (head)`. +- API, web, PostgreSQL, scheduled backup, Prometheus and Grafana are healthy/current. + Live readiness is `ready`; post-deployment logs contain no traceback or critical error. +- The initial production browser run exposed two stale assertions that expected raw + RAGcore filenames. Fleet Ops now intentionally presents localized source titles. The + tests were tightened around localized titles plus language-specific evidence; the + focused live matrix passed 4/4 and the complete live suite then passed **150/150 in + 4.2 minutes**. +- Final live visual audit covered login, Highlights and Engineering. Desktop overflow is + zero and the 360/390 px layouts are automated. The integration story is evidence-based: + n8n operational (4/4 workflows, 19 successful, zero pending/unexpected failures), + RAGcore operational (11 managed sources, provider index count honestly unknown), and + MCP labelled not connected because the final reset clears recent tool-call evidence. +- Final reset restored **2 users / 180 customers / 50 vehicles / 254 bookings / 75 + inspections / 40 maintenance records / 33 quality issues / 20 workflow runs** with + all five scenarios ready. Live evidence screenshots and the canonical acceptance + summary were refreshed in `artifacts/evidence/`. +- Exact next action: commit/push this evidence-only hand-off update and refresh the + server's source archive/revision marker; no runtime rebuild or database change is needed. diff --git a/artifacts/evidence/final-summary.md b/artifacts/evidence/final-summary.md index 17969c8..e829531 100644 --- a/artifacts/evidence/final-summary.md +++ b/artifacts/evidence/final-summary.md @@ -1,83 +1,73 @@ -# MobilityOps — final acceptance evidence +# Fleet Ops — final acceptance evidence ## Accepted implementation -- Implementation under test: `5dda574` (`master`). The final evidence commit contains - documentation only and does not change the accepted runtime. -- Live URL: `http://192.168.10.150:1236`. -- Deployment: Unraid, `/mnt/user/appdata/mobilityops`, Compose project `mobilityops`. -- Data: deterministic, explicitly labelled synthetic demo data. -- Database migration: `f43d829ab610 (head)`. +- Runtime commit: `29325b6c2775806080dc40e1988634d6ceb300a0` (`master`). +- Live demo: `http://192.168.10.150:1236` — public passwordless synthetic demo. +- Deployment: Unraid `/mnt/user/appdata/mobilityops`, Compose project `mobilityops`. +- Database migration: `b913a72e8c14 (head)`. +- Product name: Fleet Ops; MobilityOps remains the technical repository/deployment ID. -## Clean acceptance results — 2026-08-10 +## Clean acceptance — 2026-08-10 ```text -Backend, isolated PostgreSQL: 225 passed, 1 dependency deprecation warning (96.71 s) -Playwright, live production: 145 passed (4.4 min) +Backend, isolated PostgreSQL: 239 passed, zero warnings +Playwright, fresh local build: 150 passed (5.2 min) +Playwright, live production: 150 passed (4.2 min) Ruff: clean -Mypy: clean -Frontend TypeScript/Vite: production build passed -npm audit (prod and full): 0 vulnerabilities -Alembic: f43d829ab610 (head) +Mypy: clean across 58 source files +Frontend lint/build: passed +npm audit, full and prod: 0 vulnerabilities +Alembic: b913a72e8c14 (head) ``` -Backend tests ran through `compose.yaml` plus `compose.test.yaml` in the disposable -`mobilityops-test` project. Its database, network and volume were removed afterward; no -test process ran inside the live API container. +The browser suite covers both roles, protected routes, booking/return/maintenance/user/privacy workflows, five data-quality resolution types, correlated audit, retryable orchestration, grounded knowledge in three languages, the complete guided demo, the recruiter highlights, keyboard behaviour and responsive layouts from 360 to 1440 px. -The single serial Playwright run covers 145 browser scenarios: both roles, protected -routes, booking lifecycle and return, maintenance/release, user administration, -data-quality scanning/assignment/resolution, audit, retryable automation, Knowledge Hub, -the complete guided demo, keyboard accessibility and responsive layouts from 360 to -1440 px. +The first production run correctly exposed two stale test assumptions: the redesigned Knowledge Hub shows localized source titles rather than raw file names. The evidence contract was changed to require the localized title and the language-specific source fragment. That focused matrix passed 4/4, followed by the complete 150/150 green production run. -## Live operational evidence +## Production hand-off state -After acceptance, demo reset restored an internally checked hand-off state: +The final reset completed at `2026-08-10T16:31:27Z` and restored: ```text users 2 · customers 180 · vehicles 50 · bookings 254 · inspections 75 maintenance 40 · data-quality issues 33 · workflow runs 20 -scenario_integrity.all_ready = true +scenario_integrity.all_ready = true (5/5 scenarios) ``` -Readiness returned `ready` with PostgreSQL `up`; API, database and web containers were -healthy. A verified custom-format database backup was written to: +API readiness is `ready`, PostgreSQL is `up`, and API, web, database, scheduled backup, Prometheus and Grafana are running healthy/current. No traceback or critical error appears in post-deployment API/backup logs. -`/mnt/user/appdata/mobilityops/backups/postgres/mobilityops-20260810T111913Z.dump` +A pre-deployment custom-format backup was created and independently verified by SHA-256 plus `pg_restore --list`: -## External integrations +`/mnt/user/appdata/mobilityops/backups/postgres/mobilityops-20260810T161659Z.dump` -- **n8n:** MobilityOps uses the existing central server instance, not a second n8n. - Dispatch is enabled and operational with 19 successful persisted runs, zero pending, - zero unexpected failures and healthy heartbeat evidence for the vehicle-return and - scheduled-quality workflows. One failed item is an explicitly labelled synthetic - retry scenario and is excluded from incident counts. -- **RAGcore:** live health returned available/ready for tenant - `northstar-mobility-demo`, workspace `mobilityops`, collection - `internal-procedures`. A live question returned a grounded answer in 5.1 seconds with - three unique, collapsible procedure citations. The UI never substitutes a fabricated - answer when evidence is insufficient or the provider is unavailable. -- **ITWorx MCP Hub:** registration is enabled, the Hub is reachable and MobilityOps - reports an audited real `fleet_ops_get_operations_summary` tool call. Tool endpoints - are read-only, tenant-bound, client-identity validated, service-authenticated and emit - correlation IDs. +## External integration evidence -## Visual acceptance +- **Existing central n8n:** configured, dispatch enabled and operational. All four expected workflows have recent healthy heartbeats. The reset state contains 19 successful runs, zero pending, zero unexpected failures and one explicitly synthetic failed-retry scenario. +- **RAGcore:** reachable and ready for tenant `northstar-mobility-demo`, workspace `mobilityops`, collection `internal-procedures`. Fleet Ops manages 11 authoritative Dutch sources; the latest n8n report records 33 synchronized language documents and zero failures. RAGcore exposes no reliable index-size endpoint, so `document_count` deliberately remains `null`. +- **ITWorx MCP Hub:** registration is enabled and the Hub is reachable. A reset intentionally clears demo audit history, so the final state has no recent tool-call evidence and the UI labels MCP **not connected** rather than inferring success from configuration. Four tenant-bound service-authenticated endpoints remain contract-tested and read-only. -The production UI was interactively inspected after the automated run. Desktop -dashboard, mobile data-quality workbench, Integration Management and Knowledge Hub had -no overlap or horizontal page overflow. Filters, SLA/assignment controls, integration -states, citations, feedback controls, keyboard landmarks and mobile navigation remained -visible and operable. Route-level lazy loading keeps the initial JavaScript chunk near -212 kB instead of the former 572 kB monolith. +## Recruiter and visual acceptance -## Deliberate scope boundary +The public entry now offers a direct **90-second Highlights** route. It links three product actions to their engineering proof, while the **Engineering** workspace explains domain ownership, commit-before-orchestration, citation-bound AI, security and explicit scope. -This is the completed locked MobilityOps PoC, not an unrestricted ERP. It intentionally -does not add accounting, payments, public reservations, CRM, inventory, HR, a second RAG -stack, a separate MCP server or autonomous write tools. Production deployment for real -personal data would still require an organisation identity provider, secrets rotation, -central observability/alerting, retention policy and an operated disaster-recovery -schedule. Those are deployment-governance concerns, not dead or simulated product -functions in the accepted scope. +Interactive live inspection confirmed: + +- no horizontal overflow on Highlights or Engineering at desktop; automated coverage confirms 360/390 px mobile layouts; +- clear hierarchy, consistent primary actions and readable proof cards; +- truthful live n8n/RAGcore/MCP labels after reset; +- no dead links, placeholder numbers or unexplained raw data-quality references; +- complete synthetic-data disclosure on login and in the persistent shell. + +Current evidence images are in `artifacts/evidence/screenshots/`: + +- `1-login.png` +- `2-highlights.png` +- `3-engineering-story.png` +- `4-dashboard.png` +- `5-knowledge-evidence.png` +- `6-highlights-mobile.png` + +## Deliberate boundary + +This is a completed, production-shaped public demo—not claimed customer adoption and not a general ERP. Accounting, payments, public reservations, CRM, inventory, HR, a second RAG stack, a separate MCP server and autonomous write agents remain intentionally excluded. A real personal-data rollout would additionally require the adopting organisation's identity provider, retention approvals, secrets lifecycle, alert ownership and disaster-recovery governance. diff --git a/artifacts/evidence/screenshots/3-engineering-story.png b/artifacts/evidence/screenshots/3-engineering-story.png index a267269..30ef47d 100644 Binary files a/artifacts/evidence/screenshots/3-engineering-story.png and b/artifacts/evidence/screenshots/3-engineering-story.png differ diff --git a/artifacts/evidence/screenshots/4-dashboard.png b/artifacts/evidence/screenshots/4-dashboard.png index c038ca4..923e225 100644 Binary files a/artifacts/evidence/screenshots/4-dashboard.png and b/artifacts/evidence/screenshots/4-dashboard.png differ diff --git a/artifacts/evidence/screenshots/5-knowledge-evidence.png b/artifacts/evidence/screenshots/5-knowledge-evidence.png index 8898872..02567b1 100644 Binary files a/artifacts/evidence/screenshots/5-knowledge-evidence.png and b/artifacts/evidence/screenshots/5-knowledge-evidence.png differ diff --git a/frontend/e2e/demo.spec.ts b/frontend/e2e/demo.spec.ts index 7bd1085..bb64892 100644 --- a/frontend/e2e/demo.spec.ts +++ b/frontend/e2e/demo.spec.ts @@ -75,7 +75,7 @@ test("five-minute demo script end to end", async ({ page, request }) => { .fill("Wat moet ik doen wanneer een voertuig terugkomt met schade?"); await page.getByRole("button", { name: "Vraag stellen" }).click(); await expect(page.getByText("Onderbouwd met geciteerde procedures")).toBeVisible({ timeout: 15_000 }); - const damageSource = page.locator(".source-card", { hasText: /damage-procedure\.md|Procedure schadeafhandeling/ }).first(); + const damageSource = page.locator(".source-card", { hasText: /zichtbare of gemelde schade/i }).first(); await expect(damageSource).toBeVisible(); await expect(damageSource).toContainText(/zichtbare of gemelde schade/i); }); diff --git a/frontend/e2e/fleet-ops-correction.spec.ts b/frontend/e2e/fleet-ops-correction.spec.ts index b1467ca..5426c42 100644 --- a/frontend/e2e/fleet-ops-correction.spec.ts +++ b/frontend/e2e/fleet-ops-correction.spec.ts @@ -260,7 +260,7 @@ test.describe("knowledge base is grounded in the operator's own language", () => await page.getByRole("button", { name: /^(Vraag stellen|Ask|Demander)$/ }).click(); const localizedSource = page.locator(".source-card", { hasText: sourceHint }).first(); await expect(localizedSource).toBeVisible({ timeout: 15_000 }); - await expect(localizedSource).toContainText(/damage-procedure\.md|Damage handling|schadeafhandeling|gestion des dommages/i); + await expect(localizedSource).toContainText(/Schade bij voertuigretour|Vehicle return damage|Dommages au retour du véhicule/i); }); } });