M30: record production recruiter acceptance
This commit is contained in:
@@ -2672,3 +2672,28 @@ evidence yet."
|
|||||||
- Exact next action: commit and push M29, create and verify a live database backup,
|
- 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
|
deploy the committed archive to Unraid, then run live health, migration, browser and
|
||||||
acceptance checks before recording the final production evidence.
|
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.
|
||||||
|
|||||||
@@ -1,83 +1,73 @@
|
|||||||
# MobilityOps — final acceptance evidence
|
# Fleet Ops — final acceptance evidence
|
||||||
|
|
||||||
## Accepted implementation
|
## Accepted implementation
|
||||||
|
|
||||||
- Implementation under test: `5dda574` (`master`). The final evidence commit contains
|
- Runtime commit: `29325b6c2775806080dc40e1988634d6ceb300a0` (`master`).
|
||||||
documentation only and does not change the accepted runtime.
|
- Live demo: `http://192.168.10.150:1236` — public passwordless synthetic demo.
|
||||||
- Live URL: `http://192.168.10.150:1236`.
|
- Deployment: Unraid `/mnt/user/appdata/mobilityops`, Compose project `mobilityops`.
|
||||||
- Deployment: Unraid, `/mnt/user/appdata/mobilityops`, Compose project `mobilityops`.
|
- Database migration: `b913a72e8c14 (head)`.
|
||||||
- Data: deterministic, explicitly labelled synthetic demo data.
|
- Product name: Fleet Ops; MobilityOps remains the technical repository/deployment ID.
|
||||||
- Database migration: `f43d829ab610 (head)`.
|
|
||||||
|
|
||||||
## Clean acceptance results — 2026-08-10
|
## Clean acceptance — 2026-08-10
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Backend, isolated PostgreSQL: 225 passed, 1 dependency deprecation warning (96.71 s)
|
Backend, isolated PostgreSQL: 239 passed, zero warnings
|
||||||
Playwright, live production: 145 passed (4.4 min)
|
Playwright, fresh local build: 150 passed (5.2 min)
|
||||||
|
Playwright, live production: 150 passed (4.2 min)
|
||||||
Ruff: clean
|
Ruff: clean
|
||||||
Mypy: clean
|
Mypy: clean across 58 source files
|
||||||
Frontend TypeScript/Vite: production build passed
|
Frontend lint/build: passed
|
||||||
npm audit (prod and full): 0 vulnerabilities
|
npm audit, full and prod: 0 vulnerabilities
|
||||||
Alembic: f43d829ab610 (head)
|
Alembic: b913a72e8c14 (head)
|
||||||
```
|
```
|
||||||
|
|
||||||
Backend tests ran through `compose.yaml` plus `compose.test.yaml` in the disposable
|
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.
|
||||||
`mobilityops-test` project. Its database, network and volume were removed afterward; no
|
|
||||||
test process ran inside the live API container.
|
|
||||||
|
|
||||||
The single serial Playwright run covers 145 browser scenarios: both roles, protected
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
## 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
|
```text
|
||||||
users 2 · customers 180 · vehicles 50 · bookings 254 · inspections 75
|
users 2 · customers 180 · vehicles 50 · bookings 254 · inspections 75
|
||||||
maintenance 40 · data-quality issues 33 · workflow runs 20
|
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
|
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.
|
||||||
healthy. A verified custom-format database backup was written to:
|
|
||||||
|
|
||||||
`/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.
|
## External integration evidence
|
||||||
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.
|
|
||||||
|
|
||||||
## 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
|
## Recruiter and visual acceptance
|
||||||
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.
|
|
||||||
|
|
||||||
## 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
|
Interactive live inspection confirmed:
|
||||||
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
|
- no horizontal overflow on Highlights or Engineering at desktop; automated coverage confirms 360/390 px mobile layouts;
|
||||||
personal data would still require an organisation identity provider, secrets rotation,
|
- clear hierarchy, consistent primary actions and readable proof cards;
|
||||||
central observability/alerting, retention policy and an operated disaster-recovery
|
- truthful live n8n/RAGcore/MCP labels after reset;
|
||||||
schedule. Those are deployment-governance concerns, not dead or simulated product
|
- no dead links, placeholder numbers or unexplained raw data-quality references;
|
||||||
functions in the accepted scope.
|
- 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.
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 304 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 194 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
@@ -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?");
|
.fill("Wat moet ik doen wanneer een voertuig terugkomt met schade?");
|
||||||
await page.getByRole("button", { name: "Vraag stellen" }).click();
|
await page.getByRole("button", { name: "Vraag stellen" }).click();
|
||||||
await expect(page.getByText("Onderbouwd met geciteerde procedures")).toBeVisible({ timeout: 15_000 });
|
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).toBeVisible();
|
||||||
await expect(damageSource).toContainText(/zichtbare of gemelde schade/i);
|
await expect(damageSource).toContainText(/zichtbare of gemelde schade/i);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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();
|
await page.getByRole("button", { name: /^(Vraag stellen|Ask|Demander)$/ }).click();
|
||||||
const localizedSource = page.locator(".source-card", { hasText: sourceHint }).first();
|
const localizedSource = page.locator(".source-card", { hasText: sourceHint }).first();
|
||||||
await expect(localizedSource).toBeVisible({ timeout: 15_000 });
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user