Skip to content

Omni Session Metrics

EmiliaVision's Omni Session Metrics module calculates 37 service quality metrics per dining session, combining video annotations, POS data, and real-time AI suggestions into a unified quality profile.


Architecture

flowchart TD
    A["Shift Map Storage<br/>shift_map_storage"] --> B["Metrics Engine<br/>metrics.py"]
    C["POS Sessions v1<br/>pos_sessions_storage"] --> B
    D["POS Sessions v2<br/>pos_sessions_v2_storage"] --> B
    E["EchoBase Events<br/>metadata.tables[].echobase_events"] --> B
    B --> F["Enriched Shift<br/>version N+1"]
    F --> G["ClickHouse<br/>shift_map_storage"]

The enrichment CLI reads the latest shift version, calculates metrics for every session, and inserts a new version with session.metrics populated. A SHA-256 fingerprint prevents unnecessary writes when metrics haven't changed.

POS v1 and POS v2 Inputs

The metrics engine supports both POS generations:

  • Legacy POS v1 uses session.pos_correlation.pos_session_id to read echobasematrix_{env}_pos_sessions_storage.
  • POS Sessions v2 uses session.pos_correlation.pos_uuid to read the latest non-deleted row for pos_session_uuid from echobasematrix_{env}_pos_sessions_v2_storage.

POS v2 separates metadata.items (final financial state for totals, revenue, and item counts) from metadata.order_events (raw operational evidence, including non-order events). The backend selects positive orders using the canonical eligibility policy.

Changed in version 2.6.0

POS v2 no longer falls back to financial items when operational evidence is missing. Category inheritance remains backend-owned and never copies financial timestamps or prices. Legacy POS v1 retains its item timeline, with invalid/pre-video chronology rejected before rounding.

Category-dependent metrics read POS v2 final item categories and may apply them to operational order-event items at read time. If POS v2 item categories are backfilled or corrected, run enrichment again so affected sessions receive new metric fingerprints and updated shift versions.


Service Timing Contract

Changed in version 2.6.0

The producer emits numeric service_timing_contract_version: 1 and canonical navigation evidence. An application version string is not proof of compatibility. Missing, boolean, string, or unknown contract revisions must not enable local POS recalculation in clients.

The existing duration fields remain nullable integer seconds. The new service_timing_evidence object accompanies them:

Field Shape Meaning
order interval or null Start-session → first positive POS order (M-2)
drink interval or null First drink order → drinks-arrived (M-10)
food interval or null First main-dish order → food-arrived (M-11)
cleaning interval or null End-session → bounded table-cleaned (M-6), independent of POS
orders array Backend-selected positive orders for timeline display; empty when unavailable

An interval contains finite non-negative start_offset_seconds and end_offset_seconds, relative to the original shift video, preserving fractions. It is null when the metric is unavailable or contradictory. An order contains offset_seconds, event_ids (source references, possibly empty), items (name, nullable category, nullable quantity, nullable line price), and nullable total. A total is available only when all included line prices are known. This operational total is not the final bill total.

Player validates the version/types, renders the supplied values and markers, and seeks to the supplied offsets. It must not select operational events, resolve category conflicts, reconstruct anchors from rounded durations, or substitute manual/generic timing formulas. Raw POS panels can still display financial context without treating it as timing evidence. SLA delay labels use the same canonical category anchor and order items.

Release and bounded reenrichment

This contract needs no DDL: it is additive JSON in the existing Shift Map metadata. Deploying code does not update an archived session or report.

  1. Review the backend change, run producer and consumer contract tests, and publish the metrics image from the reviewed revision. Verify the actual published image, not just local source or a successful build job.
  2. Inventory the permitted shifts, dates, and locations privately. Dry-run by --video-task-id, then write and reread a pilot only with operator approval. Continue in resumable batches over that closed inventory; preserve source annotations/POS rows and append new Shift Map versions normally.
  3. Review all three infra/k8s/metrics/ image pins and deploy explicitly using the documented Kubernetes context. The existing jobs have no date filter: changing the metrics version changes every processed fingerprint and can reenrich all selected history even without --force. Do not apply the new pins before approving that scope or an appropriately bounded job policy.
  4. Validate Player, Reports, Workspace, and SLA on the same reenriched sessions before declaring operational completion. Reader-specific compatibility work and immutable report publication are separate steps, not automatic effects of a metrics image release.
  5. Rollback may restore a previous reviewed image pin. It does not erase appended data versions or authorize overwriting report snapshots.

Metric Catalog

All metrics live at metadata.tables[].sessions[].metrics in the shift_map_storage JSON metadata.

ID Field Type Source Details
M-1 manager_touch_count int Annotations Annotation Metrics
M-2 time_to_first_pos_order_seconds int | null Annotations + POS POS Metrics
M-3 time_from_session_start_to_drink_arrival_seconds int | null Annotations Annotation Metrics
M-4 waiter_touch_count int Annotations Annotation Metrics
M-5 hand_raise_count int Annotations Annotation Metrics
M-6 table_cleaned_time_seconds int | null Annotations Annotation Metrics
M-7 food_delivery_from_first_pos_item_seconds int | null Annotations + POS POS Metrics
M-8 first_waiter_contact_time_seconds int | null Annotations Annotation Metrics
M-9 drink_delivery_from_first_pos_item_seconds int | null Annotations + POS POS Metrics
M-10 drink_delivery_from_first_drink_order_seconds int | null Annotations + POS POS Metrics
M-11 food_delivery_from_first_main_dish_order_seconds int | null Annotations + POS POS Metrics
M-12 drink_delivery_from_order_taken_seconds int | null Annotations Annotation Metrics
M-13 food_delivery_from_order_taken_seconds int | null Annotations Annotation Metrics
M-14 bill_payment_to_end_session_seconds int | null Annotations Annotation Metrics
M-25 menu_delivery_time_seconds int | null Annotations Annotation Metrics
M-26 bill_closing_time_seconds int | null Annotations Annotation Metrics
M-27 courtesy_delivery_from_session_start_seconds int | null Annotations Annotation Metrics
M-15 drink_item_count int POS POS Metrics
M-16 main_dish_item_count int POS POS Metrics
M-17 dessert_item_count int POS POS Metrics
M-18 pos_ticket_subtotal float | null POS POS Metrics
M-19 pos_ticket_avg float | null POS POS Metrics
M-20 pos_drink_ticket_total float | null POS POS Metrics
M-21 pos_dessert_ticket_total float | null POS POS Metrics
M-22 pos_server_name_open str | null POS POS Metrics
M-23 pos_server_name_close str | null POS POS Metrics
M-24 pos_top_seller str | null POS POS Metrics
drink_suggestion_count int EchoBase Events Compliance
drink_suggestion_compliance_pct float | null EchoBase Events Compliance
dessert_suggestion_count int EchoBase Events Compliance
dessert_suggestion_compliance_pct float | null EchoBase Events Compliance
dessert_compliance_conversion bool | null EchoBase + POS Compliance
dessert_compliance_conversion_items int EchoBase + POS Compliance
dessert_compliance_conversion_revenue float | null EchoBase + POS Compliance
dessert_compliance_conversion_delta_seconds int | null EchoBase + POS Compliance
drink_compliance_conversion bool | null EchoBase + POS Compliance
drink_compliance_conversion_count int EchoBase + POS Compliance
drink_compliance_compliant_clusters int EchoBase + POS Compliance
drink_compliance_conversion_items list[int] EchoBase + POS Compliance
drink_compliance_conversion_revenue list[float | null] EchoBase + POS Compliance
drink_compliance_conversion_deltas list[int] EchoBase + POS Compliance
delayed_food_items list[str] POS + Metrics SLA Detection
delayed_drink_items list[str] POS + Metrics SLA Detection

Metadata Fields

Every enriched session also includes:

Field Type Description
service_timing_contract_version number Explicit service timing contract revision; currently 1
service_timing_evidence object Nullable canonical intervals and normalized positive order markers
omni_metrics_version str Version of the Omni Metrics module that calculated these metrics
fingerprint str 8-char SHA-256 hash of all metrics + version — used to skip re-writes
calculated_at str ISO 8601 timestamp of when metrics were calculated

Null Convention

Duration metrics return null when their prerequisite annotations are missing:

  • Metrics gated on start-session: M-2, M-3, M-8, M-25, M-27
  • Metrics gated on end-session: M-6, M-14
  • Metrics gated on bill-dropped + bill-payment: M-26
  • Metrics gated on order-taken: M-12, M-13
  • Metrics gated on confirmed POS + video_start_utc: M-2, M-7, M-9, M-10, M-11

A null metric is not an error — it means the required data was not available for that session.

Count metrics (M-1, M-4, M-5, M-15, M-16, M-17) default to 0, never null.