docs(demo): add demo concept, scenarios, data, guide and runbook docs
Documents the demo-productization work from this branch: the Northstar Mobility fictional concept and scope, the five named scenarios and their fixed records, the seed/date-anchoring strategy (including the real bug it fixed), the in-app Demo Guide's design and the English-suggested- questions decision, and an operational runbook covering 5/10-minute demo flows, reset, Unraid redeploy and rollback. Updates README with current test counts and pointers to the new docs.
This commit is contained in:
@@ -12,6 +12,17 @@ design decision and visual evidence.
|
||||
|
||||
All people, companies, vehicles, bookings and documents are synthetic. The workflows, validation, integrations, audit logging and access boundaries are intended to be real.
|
||||
|
||||
## Demo
|
||||
|
||||
The demo presents itself as **Northstar Mobility**, a fictitious Belgian camper/van
|
||||
rental company — the login screen, a permanent "Synthetische demo" indicator, an in-app
|
||||
guided tour (Demo Guide), a curated `/scenarios` overview, and an "Over deze demo" page
|
||||
all make the fictional context, synthetic-data status, and real-vs-simulated boundaries
|
||||
explicit without any verbal explanation. See `docs/demo-release/` for the full demo
|
||||
concept, the five named scenarios, the seed/date-anchoring strategy, the guided-tour
|
||||
design, and the operational runbook (5-minute and 10-minute demo flows, reset, redeploy,
|
||||
rollback).
|
||||
|
||||
## Scope
|
||||
|
||||
The PoC implements:
|
||||
@@ -77,6 +88,9 @@ and `artifacts/final-acceptance/summary.md` for the original M0–M7 acceptance
|
||||
- `artifacts/design-validation/` — baseline audit, Stitch direction references and implemented responsive captures.
|
||||
- `docs/functional-completion/` — the functional-completion audit and pre-work server baseline.
|
||||
- `artifacts/functional-completion/` — functional-completion acceptance evidence.
|
||||
- `docs/demo-release/` — demo concept, scenarios, seed/date-anchoring strategy, guided
|
||||
tour, and runbook.
|
||||
- `artifacts/demo-release/` — demo-productization acceptance evidence.
|
||||
|
||||
## Quickstart
|
||||
|
||||
@@ -100,9 +114,9 @@ All defaults are configurable via `.env` (see `.env.example`).
|
||||
## Quality gates
|
||||
|
||||
```bash
|
||||
make test # backend: pytest (117 tests)
|
||||
make test # backend: pytest (127 tests)
|
||||
make lint # backend: ruff + mypy (strict, zero errors)
|
||||
make e2e # frontend: Playwright end-to-end (37 tests, live stack required)
|
||||
make e2e # frontend: Playwright end-to-end (56 tests, live stack required)
|
||||
```
|
||||
|
||||
Frontend build/typecheck: `cd frontend && npm run build` (`tsc -b && vite build`).
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# PoC runbook
|
||||
|
||||
For the demo-specific 5-minute/10-minute walkthroughs, reset behaviour, Unraid
|
||||
redeploy/rollback steps and troubleshooting, see `docs/demo-release/demo-runbook.md`.
|
||||
This document covers general environment bootstrap and n8n setup.
|
||||
|
||||
## Bootstrap (clean checkout)
|
||||
|
||||
```bash
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Demo concept
|
||||
|
||||
## The fictional problem
|
||||
|
||||
**Northstar Mobility** is a fictional Belgian camper/van rental company with roughly 50
|
||||
vehicles, one main location, a rental team, an operations manager, and a small workshop.
|
||||
Northstar Mobility does not exist — this name and every customer, vehicle, booking and
|
||||
procedure in the demo are synthetic. Before MobilityOps, Northstar Mobility's bookings,
|
||||
returns, customer records and maintenance history lived in spreadsheets and verbal
|
||||
hand-offs, so problems (duplicate customers, incorrect odometer readings, double-booked
|
||||
vehicles) only surfaced late, after they had already caused friction. MobilityOps shows
|
||||
how one connected system detects these problems early and lets an Operations Manager
|
||||
resolve them under audit, with automation handling the routine follow-up.
|
||||
|
||||
## Target audience
|
||||
|
||||
Anyone evaluating how MobilityOps approaches operational data-quality and hand-off
|
||||
problems for a small rental fleet: Operations Managers, Rental Employees, and reviewers
|
||||
assessing the approach. No account setup or backend knowledge is required to start —
|
||||
the login screen explains the fictional context and offers a guided path.
|
||||
|
||||
## Demo scope
|
||||
|
||||
This is a focused proof of concept, not a full ERP. In scope: vehicle and booking
|
||||
management, return processing with server-side evaluation, five data-quality detection
|
||||
rules each with one bounded resolution flow, a full audit trail, and orchestration via a
|
||||
real n8n instance. Explicitly out of scope: accounting, payments, public reservations, a
|
||||
generic CRM, inventory, HR, a second RAG stack, or autonomous write actions from any
|
||||
external tool.
|
||||
|
||||
## What's really implemented
|
||||
|
||||
All of the following is functional code, not a mockup or hardcoded screen:
|
||||
|
||||
- Role-based authentication and server-verified sessions (Operations Manager, Rental
|
||||
Employee), enforced both server-side and in the frontend's navigation/route guards.
|
||||
- Vehicle and booking management, with return preview/commit sharing one authoritative
|
||||
evaluation function so they can never drift.
|
||||
- Five data-quality rules (possible duplicate customer, missing required field, odometer
|
||||
regression, booking overlap, vehicle status conflict), each with exactly one bounded,
|
||||
audited resolution endpoint.
|
||||
- A full audit trail with before/after state, actor, correlation IDs, and a
|
||||
"view related events" link reusing that correlation.
|
||||
- Reliable outbox-based delivery to a real n8n instance, with bounded retries and
|
||||
stale-delivery recovery.
|
||||
- Docker Compose deployment and an automated test suite (backend pytest, Ruff, mypy,
|
||||
and a full Playwright end-to-end suite covering the demo experience itself).
|
||||
- A demo manifest (`GET /api/v1/demo/manifest`) as the single source of truth for the
|
||||
demo's identity, synthetic-data status, reset state, scenario readiness, and honest
|
||||
per-integration labels — the frontend never hardcodes what mode it's in.
|
||||
|
||||
## What's synthetic
|
||||
|
||||
The organisation, all customers, vehicles, bookings, maintenance history, the knowledge
|
||||
base's procedures, and the five prepared demo scenarios are entirely fictional. No data
|
||||
refers to a real person, vehicle, or company. Every seeded email uses the `.test`
|
||||
reserved domain. See [`demo-data.md`](demo-data.md) for exactly how this data is
|
||||
generated and kept fresh across resets.
|
||||
|
||||
## What's not yet live-connected
|
||||
|
||||
- **RAGcore**: not connected. The knowledge assistant uses a local, deterministic
|
||||
keyword-matching "demo knowledge base" built from five procedure documents, honestly
|
||||
labelled as such everywhere in the UI (never presented as RAGcore). A
|
||||
`RAGcoreKnowledgeProvider` HTTP adapter exists and is unit-tested, ready to take over
|
||||
the same interface once a real RAGcore backend is available — swapping providers is a
|
||||
configuration change (`KNOWLEDGE_PROVIDER`), not a UI change.
|
||||
- **ITWorx MCP Hub**: not connected. Registration is disabled by default
|
||||
(`MCP_HUB_REGISTRATION_ENABLED=false`) and the UI always shows "Not connected" —
|
||||
never a fabricated successful registration.
|
||||
|
||||
## Where to go next
|
||||
|
||||
- [`demo-scenarios.md`](demo-scenarios.md) — the five guided scenarios and their fixed records.
|
||||
- [`demo-data.md`](demo-data.md) — seed strategy and date-anchoring.
|
||||
- [`demo-guide.md`](demo-guide.md) — the in-app 8-step guided tour.
|
||||
- [`demo-runbook.md`](demo-runbook.md) — how to run, reset, and redeploy the demo.
|
||||
@@ -0,0 +1,83 @@
|
||||
# Demo data strategy
|
||||
|
||||
## Three separate concepts
|
||||
|
||||
It's important to keep these distinct — they solve different problems:
|
||||
|
||||
1. **Deterministic records** — every seeded entity has a stable public reference
|
||||
(`BK-DEMO-RETURN`, `DQ-DEMO-DUPLICATE`, `MO-024`, `CUS-0012`, ...). These references
|
||||
never change between seed generations or resets; they are what the five demo
|
||||
scenarios, the Demo Guide, and `docs/13-seed-and-demo-scenarios.md` all link against.
|
||||
2. **Date anchoring** — the mechanism that keeps "today"/"near-future"/"currently
|
||||
overlapping" scenarios true to whenever the environment was actually last reset,
|
||||
described below.
|
||||
3. **The reset date** — the real wall-clock moment a reset actually happened. This
|
||||
changes every time someone resets; it's the input to date anchoring, not a fixed
|
||||
record.
|
||||
|
||||
## Generating the seed dataset
|
||||
|
||||
```bash
|
||||
python seed/generate_seed.py --anchor 2026-08-01 --seed 20260801
|
||||
```
|
||||
|
||||
This produces the committed CSVs in `seed/*.csv` with **absolute ISO timestamps**
|
||||
authored relative to a fixed anchor date (`2026-08-01`). Target scale: 50 vehicles, 180
|
||||
customers (including three duplicate pairs), ~245 historical/current/future bookings,
|
||||
realistic inspections and maintenance history, and the fixed quality/workflow scenarios
|
||||
described in [`demo-scenarios.md`](demo-scenarios.md). Names, towns and vehicle makes are
|
||||
drawn from believable Flemish/Kempen-region pools; all emails use the `.test` domain.
|
||||
|
||||
## Date anchoring
|
||||
|
||||
`backend/app/seed_loader.py` defines:
|
||||
|
||||
```python
|
||||
SEED_AUTHORED_ANCHOR = date(2026, 8, 1) # matches generate_seed.py's --anchor
|
||||
```
|
||||
|
||||
Every seed/reset computes `shift = today - SEED_AUTHORED_ANCHOR` and applies it to every
|
||||
seeded booking, inspection, maintenance and outbox timestamp before insertion. Public
|
||||
references and entity relationships are never touched by the shift — only datetime
|
||||
columns move. This means:
|
||||
|
||||
- `BK-DEMO-RETURN` always ends "today" (or very close to it) relative to whenever you
|
||||
actually reset, not relative to the frozen 2026-08-01 authoring date.
|
||||
- `BK-DEMO-NEXT` and the overlap-scenario bookings always read as "near future".
|
||||
- The shift is recomputed fresh on every reset, so scenarios never decay as real time
|
||||
passes between resets — this was a real, confirmed bug before this fix (see
|
||||
`docs/demo-release/current-demo-gap-audit.md`, gap #3): the environment would drift
|
||||
further out of sync with every day it wasn't reset, and a reset didn't fix it because
|
||||
nothing re-anchored the underlying stored dates.
|
||||
|
||||
`load_seed()` returns the resolved `anchor_date` (real today) and `seeded_at` timestamp,
|
||||
and records a `demo_data_seeded` audit event carrying both the resolved anchor and the
|
||||
original authoring anchor, so the shift applied on any given reset stays traceable via
|
||||
the audit trail.
|
||||
|
||||
`dashboard.py::_today()` uses real wall-clock UTC date (not a frozen setting) to filter
|
||||
"today's movements", consistent with the shifted data.
|
||||
|
||||
## Reset
|
||||
|
||||
`POST /api/v1/demo/reset` (Operations Manager only, and only if `DEMO_ALLOW_RESET=true`)
|
||||
clears all MobilityOps tables, reloads the seed with a fresh date shift, re-runs the
|
||||
data-quality scan, and runs a server-side **scenario-integrity check**
|
||||
(`scenario_integrity_report()` in `backend/app/services/demo_manifest.py`) confirming all
|
||||
five named scenarios are actually present and ready — recorded in both the response body
|
||||
and the `demo_reset` audit event's metadata. Reset only ever affects MobilityOps's own
|
||||
tables; it never touches shared n8n, RAGcore, or MCP data, other containers, or volumes.
|
||||
|
||||
## Seed-validation tests
|
||||
|
||||
`backend/tests/test_seed.py` proves, after every reset:
|
||||
|
||||
- S1 (`BK-DEMO-RETURN`/`MO-024`) is active with no end odometer recorded yet.
|
||||
- S2 (`CUS-0012`/`CUS-0178`/`DQ-DEMO-DUPLICATE`) is open with matching evidence.
|
||||
- S4 (`MO-016`/`BK-DEMO-OVERLAP-A`/`-B`/`DQ-DEMO-OVERLAP`) genuinely overlaps in time.
|
||||
- S5 (the seeded failed outbox event) is durably `failed` immediately after reset, not
|
||||
silently auto-healed by the background dispatcher (which only claims `pending` rows).
|
||||
- The date-anchoring shift and the `demo_data_seeded` audit marker are both correct.
|
||||
|
||||
`backend/tests/test_demo_manifest.py` additionally proves that all five manifest
|
||||
scenarios report `ready: true` with no `blocked_reason` right after a fresh reset.
|
||||
@@ -0,0 +1,71 @@
|
||||
# The in-app Demo Guide
|
||||
|
||||
## What it is (and isn't)
|
||||
|
||||
The Demo Guide is a compact, reusable side panel (a bottom sheet on mobile) that walks an
|
||||
Operations Manager through eight fixed steps covering the demo's core functionality. It is
|
||||
**not** a generic tutorial engine and **not** a source of business logic — every action it
|
||||
prompts is a real action against the real API; the guide only narrates, links, and tracks
|
||||
progress. It duplicates no business logic: routes for the two scenario-backed steps
|
||||
(return, duplicate-merge) are resolved from the live `GET /api/v1/demo/manifest` response
|
||||
rather than hardcoded, so they can never point at a stale or missing record.
|
||||
|
||||
## Where it lives
|
||||
|
||||
- `frontend/src/data/demoGuideSteps.ts` — the eight step definitions (title, what you'll
|
||||
see, why it matters, the exact start action, the expected outcome, and a `route()`
|
||||
function).
|
||||
- `frontend/src/context/DemoGuideContext.tsx` — open/close state and step progress,
|
||||
persisted to `sessionStorage` only (browser-local, never touches auth or business
|
||||
state; a "Demo opnieuw voorbereiden" restart or a new browser session starts fresh).
|
||||
- `frontend/src/components/DemoGuide.tsx` — the panel itself and its topbar trigger
|
||||
(`DemoGuideTrigger`, Operations-Manager-only, since all eight steps require that role).
|
||||
|
||||
## The eight steps
|
||||
|
||||
1. **Understand the operational state** — the dashboard's readiness and attention queue.
|
||||
2. **Open the booking needing attention** — `BK-DEMO-RETURN`, resolved from the manifest.
|
||||
3. **Process the return with an odometer anomaly** — same booking; the return form is
|
||||
pre-filled with the suspicious reading (see [`demo-scenarios.md`](demo-scenarios.md)
|
||||
scenario 1).
|
||||
4. **Handle the created data-quality issue** — the fresh odometer-regression issue that
|
||||
step 3 just created.
|
||||
5. **Review and merge the possible duplicate customer** — `DQ-DEMO-DUPLICATE`.
|
||||
6. **Ask the procedure assistant a question** — one of the suggested questions.
|
||||
7. **Check automation and the audit trail**.
|
||||
8. **Review what's real, simulated, or not yet connected** — the About page.
|
||||
|
||||
## How progression works
|
||||
|
||||
- **"Ga naar deze stap"** navigates to the step's resolved route without marking it done.
|
||||
- **"Volgende"** marks the current step complete and advances the index (used for steps
|
||||
with no dedicated in-page continuation, like the knowledge-assistant step).
|
||||
- Several real actions (a successful return, a resolved data-quality issue) show their
|
||||
own **"Ga verder met de demo"** button that both completes the current step and
|
||||
navigates straight to the next one — this is how the guide chains through steps 3→4→5
|
||||
without a detour back through the panel's own controls.
|
||||
- The step list on the panel lets you jump directly to any step.
|
||||
- **"Demo opnieuw voorbereiden"** calls the real reset endpoint, resets the guide's own
|
||||
progress, and returns to the login screen — mirroring the existing sidebar reset
|
||||
control, not a separate implementation.
|
||||
|
||||
## A known, deliberate limitation: suggested questions stay in English
|
||||
|
||||
The demo knowledge base's five procedure documents (`knowledge/procedures/*.md`) are
|
||||
written in English. Verified empirically while building step 6: an equivalent Dutch
|
||||
question returned `insufficient` evidence against the demo provider, while the English
|
||||
original returned `grounded`. Rather than mistranslate the demo's centerpiece "grounded
|
||||
answer" feature into something that silently answers incorrectly, the suggested questions
|
||||
on `/knowledge` and this guide's step 6 instructions stay in English, with the guide
|
||||
explicitly explaining why in Dutch. Retranslating the procedure documents themselves was
|
||||
judged out of scope for a demo-productization pass (see the language-split note in
|
||||
`docs/demo-release/current-demo-gap-audit.md`, gap #11).
|
||||
|
||||
## Layout note: the panel reserves space, it doesn't overlap content
|
||||
|
||||
On desktop the panel is a fixed 400px-wide right-side overlay. `Layout.tsx` adds a
|
||||
`guide-open` class to the main workspace while the guide is open, which reserves
|
||||
`padding-right` so page content reflows aside instead of sitting underneath the panel —
|
||||
this was a real bug found and fixed while building the full guided-demo Playwright test
|
||||
(see `PROJECT_STATE.md`, Batch 6): without it, the return form's "Review return" button
|
||||
was unclickable while the guide was open at ordinary desktop widths.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Demo runbook
|
||||
|
||||
## Starting the demo (any environment)
|
||||
|
||||
Open the deployed URL (Unraid review: `http://192.168.10.150:1236`; local:
|
||||
`http://localhost:1228`). The login screen names the fictional organisation, states that
|
||||
all data is synthetic and all workflows are really implemented, and offers:
|
||||
|
||||
- **Start begeleide demo** — logs in as Operations Manager and opens the Demo Guide at
|
||||
step 1.
|
||||
- **Verken als Operations Manager** / **Verken als Rental Employee** — free exploration,
|
||||
no guide.
|
||||
|
||||
No password is shown or required for either path.
|
||||
|
||||
## Five-minute demo (guided)
|
||||
|
||||
1. Click **Start begeleide demo**.
|
||||
2. Follow steps 1–3: dashboard → the booking needing attention → confirm the pre-filled
|
||||
odometer-anomaly return.
|
||||
3. Step 4: resolve the data-quality issue the return just created (any decision is fine
|
||||
for a quick pass — "Retain canonical" is the fastest).
|
||||
4. Step 6: ask a suggested knowledge question and show the cited source.
|
||||
5. Step 7: show the automation/audit trail link-through.
|
||||
6. Close with step 8, the About page's honest real/synthetic/not-connected breakdown.
|
||||
|
||||
## Ten-minute demo (guided + one extra scenario)
|
||||
|
||||
Do the five-minute path above, then from `/scenarios`:
|
||||
|
||||
- Run **scenario 2** (duplicate customer merge) if not already done via the guide's own
|
||||
step 5.
|
||||
- Run **scenario 3** (booking overlap) — `/data-quality`, resolve `DQ-DEMO-OVERLAP`.
|
||||
- Run **scenario 4** (failed automation retry) — `/automation`, filter to failed, retry.
|
||||
|
||||
All five scenarios can be run in any order and are independent of each other.
|
||||
|
||||
## Resetting the environment
|
||||
|
||||
Any Operations Manager can reset from: the sidebar ("Reset demo data"), the Demo Guide
|
||||
panel ("Demo opnieuw voorbereiden"), or the About page (points to the sidebar control).
|
||||
Reset requires confirmation, rebuilds the deterministic dataset with a fresh date anchor,
|
||||
runs a server-side scenario-integrity check, and signs the acting session out (the server
|
||||
invalidates the session as part of reset). It only ever touches MobilityOps's own tables
|
||||
— never shared n8n, RAGcore, or MCP data, other containers, or volumes. It can be
|
||||
disabled entirely via `DEMO_ALLOW_RESET=false` if an environment must not be rebuildable.
|
||||
|
||||
## Redeploying to Unraid
|
||||
|
||||
```bash
|
||||
# From a clean local checkout on the target branch/commit:
|
||||
git archive --format=tar.gz -o /tmp/mobilityops-source.tar.gz HEAD
|
||||
scp /tmp/mobilityops-source.tar.gz unraid:/mnt/user/appdata/mobilityops/.deploy/source-<short-sha>.tar.gz
|
||||
ssh unraid "cd /mnt/user/appdata/mobilityops \
|
||||
&& tar -xzf .deploy/source-<short-sha>.tar.gz \
|
||||
&& echo <full-sha> > .deploy/source-revision"
|
||||
|
||||
# Rebuild only what changed (api and/or web); db is never rebuilt:
|
||||
ssh unraid "cd /mnt/user/appdata/mobilityops \
|
||||
&& docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml up --build -d api web"
|
||||
|
||||
# Confirm migrations and reseed:
|
||||
ssh unraid "cd /mnt/user/appdata/mobilityops \
|
||||
&& docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec -T api python -m alembic current \
|
||||
&& docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec -T api python -m app.cli seed --reset"
|
||||
```
|
||||
|
||||
Extraction preserves the server's existing `.env` and named volumes (Postgres data, n8n
|
||||
data) — the tarball never contains `.env` since it's gitignored. Never edit source
|
||||
directly on the server; never deploy uncommitted changes.
|
||||
|
||||
## Rollback
|
||||
|
||||
`.deploy/source-revision` on the server records exactly which commit is live. Prior
|
||||
source tarballs remain in `.deploy/` for rollback: extract an earlier
|
||||
`source-<short-sha>.tar.gz`, update `source-revision` to match, and re-run the rebuild
|
||||
step above. Database rollback is out of scope for this demo (migrations are additive;
|
||||
there has been no destructive migration on this branch).
|
||||
|
||||
## Server safety (Unraid)
|
||||
|
||||
Only touch the `mobilityops` Compose project's own `api`/`web` services (and `db` only
|
||||
via migrations, never manually). Never stop other containers, run `docker system prune`,
|
||||
delete unrecognised images/networks/volumes, delete the MobilityOps database, overwrite
|
||||
the server `.env`, print secrets, start a second permanent n8n instance, or activate
|
||||
guessed RAGcore/MCP URLs. PostgreSQL is never exposed externally.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **A scenario shows "Niet beschikbaar" on `/scenarios`**: it has already been resolved
|
||||
since the last reset (expected once you've worked through it) — reset to restore it.
|
||||
- **Knowledge question returns "insufficient evidence"**: check the question is in
|
||||
English and close to one of the suggested phrasings — the demo knowledge base is
|
||||
English-only (see `demo-guide.md`).
|
||||
- **n8n shows a failed delivery that isn't the seeded demo one**: check `/automation`'s
|
||||
filter and retry — bounded retries mean it should self-heal within
|
||||
`n8n_max_attempts` attempts, or can be retried manually by an Operations Manager.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Demo scenarios
|
||||
|
||||
Five fixed scenarios are surfaced at `/scenarios` and via `GET /api/v1/demo/manifest`'s
|
||||
`scenarios` array, which derives each scenario's `ready`/`blocked_reason` from the actual
|
||||
underlying records — never hardcoded. All five are re-findable, using the same public
|
||||
references, after every demo reset (see [`demo-data.md`](demo-data.md)).
|
||||
|
||||
## 1 — Odometer regression on return
|
||||
|
||||
- **Fixed records**: booking `BK-DEMO-RETURN` on vehicle `MO-024`.
|
||||
- **Role**: Rental Employee or Operations Manager.
|
||||
- **Problem demonstrated**: a return is submitted with an odometer reading lower than the
|
||||
vehicle's canonical reading — usually a data-entry mistake or a return logged against
|
||||
the wrong vehicle.
|
||||
- **Flow**: open the booking. The return form is pre-filled with a suspicious reading
|
||||
below `MO-024`'s canonical odometer (the demo never asks a visitor to invent one), with
|
||||
a callout explaining why. Review the server-evaluated preview, then confirm. The
|
||||
canonical odometer is never silently lowered; a data-quality issue is opened
|
||||
automatically and the outcome is queued for delivery to n8n.
|
||||
- **Continue**: the result panel links to the vehicle, automation status, and audit
|
||||
trail, plus (inside the guided tour) a "Ga verder met de demo" button.
|
||||
|
||||
## 2 — Possible duplicate customer
|
||||
|
||||
- **Fixed records**: customers `CUS-0012` and `CUS-0178` (same email/phone), issue
|
||||
`DQ-DEMO-DUPLICATE`.
|
||||
- **Role**: Operations Manager (merge is a bounded, audited action).
|
||||
- **Problem demonstrated**: two customer profiles that are very likely the same person,
|
||||
registered twice — a risk for split booking history and duplicate contact.
|
||||
- **Flow**: open the issue, compare both profiles field by field, choose which survives,
|
||||
and merge. The losing profile becomes a tombstone linked to the survivor; its bookings
|
||||
are rewired. The result is recorded in the audit trail.
|
||||
|
||||
## 3 — Overlapping bookings
|
||||
|
||||
- **Fixed records**: vehicle `MO-016`, bookings `BK-DEMO-OVERLAP-A`/`BK-DEMO-OVERLAP-B`,
|
||||
issue `DQ-DEMO-OVERLAP`.
|
||||
- **Role**: Operations Manager.
|
||||
- **Problem demonstrated**: the same vehicle committed to two overlapping reservations —
|
||||
a legacy-import-style conflict that a normal booking command would reject outright.
|
||||
- **Flow**: open the issue, choose which of the two bookings to block; the other keeps
|
||||
its current status.
|
||||
|
||||
## 4 — Failed automation, retried
|
||||
|
||||
- **Fixed record**: a seeded outbox event (`00000000-0000-4000-8000-000000000020`,
|
||||
`BK-H-0020`) that is durably `failed` immediately after every reset — a safe, simulated
|
||||
connection error, not a deliberately destabilised n8n configuration.
|
||||
- **Role**: Operations Manager.
|
||||
- **Problem demonstrated**: bounded retries and visible failure/recovery state for
|
||||
workflow delivery, rather than a silent drop.
|
||||
- **Flow**: open Automation, filter to failed deliveries, retry the event; it moves out
|
||||
of the failed filter once delivered.
|
||||
|
||||
## 5 — Grounded procedure question
|
||||
|
||||
- **Role**: Rental Employee or Operations Manager.
|
||||
- **Problem demonstrated**: an operational question gets an answer with a citation from
|
||||
the demo knowledge base — or an honest "insufficient evidence" if nothing indexed
|
||||
answers it — never an invented answer.
|
||||
- **Flow**: open Knowledge, click one of the suggested questions (English, matching the
|
||||
indexed procedure content — see the note in [`demo-guide.md`](demo-guide.md) about why
|
||||
suggested questions stay in English even though the rest of the demo narrates in
|
||||
Dutch), and inspect the cited source and evidence state.
|
||||
|
||||
## A sixth scenario exists but isn't one of the five requested
|
||||
|
||||
`docs/13-seed-and-demo-scenarios.md`'s **S3** ("missing inspection before next booking",
|
||||
vehicle `MO-031`) is also seeded and shows up in the attention queue; it isn't surfaced
|
||||
on `/scenarios` because the brief names five specific scenarios, but it remains available
|
||||
for anyone exploring the attention queue directly.
|
||||
Reference in New Issue
Block a user