Confidential · Draft · Jul 2026
System Architecture · Flow

LumicIQ — end-to-end flow, as built

Whatever the store has — read by on-prem connectors, an edge perception unit, and the sensor doors — becomes one canonical event stream → a learned attention gate → an LLM agent reasoning over composed context & scoped knowledge → a routed, quantified recommendation to the right person. Every call is audited. This diagram is the shipped system: every solid box is running code with tests, deployed to the Azure dev environment (or, for the on-prem and simulation planes, running on real hardware next to it). Dashed boxes are the one plane still ahead.

16 service projects 10 shared SDKs 12 Azure Container Apps ~27 test projects 5 event hubs · 9 consumer groups 2 web clients · 2 connectors · 1 UE5 twin build phases 0–5 complete
On-prem / dev plane Source / ingress Simulation Spine / projection Detect Agent / LLM Deliver Storage Platform / control data / control flow planned (build phase 6)
virtual cameras the same doors, real or simulated events project state · memory · knowledge (RAG) prompt layers LLM call proposed LlmCallRecord ask · converse planned · outcomes → prompt evolution 01 · AT THE STORE · ON-PREM NO-API SYSTEMS POS · labor · inventory web dashboards · no vendor API CONNECTORS Connector agents dashboard (Loyverse) · screen schema-gated extract → events creds never leave the store SENSORS & FEEDS Devices & externals IoT · counters · weather · events EDGE VIDEO Edge Perception Unit cameras → detect · track · re-ID YOLO11 · ByteTrack · CLIP (ONNX) no VLM at the edge · ADR-0009 SIMULATION · DEV & TRAINING UE5 ENGINE Photoreal store twin shoppers · 5 virtual cameras WORLD ENGINE Twin brain + control UI scenarios · truth · same doors ADR-0010 · single entry path 02 · INGRESS Adapters — the doors /ingest/events · sensor.raw@1 /ingest/video/frames · segments pull: weather · local events cloud VLM cascade (no edge box) dedupe · rate-limit · dead-letter source.heartbeat + health marker ES256 tokens · fail-closed Sources registry · deploy-free kill-switch · admin-owned 03 · SPINE Event Hubs — one stream events · suggestions-proposed suggestions-published conversations · module-metrics ULID · idempotent on eventId partition hash(tenant, store) 9 variant-scoped consumer groups PROJECT StateProjection emit-then-project · idempotent state + suggestion lifecycle OPERATIONAL Stores Cosmos · Redis · Azure SQL · Blob records · hot state · registry immutable event archive 04 · ATTENTION Interestingness learned Welford baselines per store·type·subject·hour no per-tenant config 04 · FLOOR SafetyNet 10 critical conditions · no LLM agent-down templated fallback CONTEXT Composed context 5 prompt layers + live NOW prompt-as-code · versioned LLM ILlmProvider OpenRouter · per-task models routing as data · $ budgets 05 · REASONING The Agent StoreAgent.single@1.0 · one per (tenant, store) composes the context layers + NOW tools: knowledge · state · source health validates → quantified suggestion writes memory + the immutable audit 05b · CONVERSE BFF — chat, SignalR, fan-out the same agent, solicited · streamed answers conversation turns onto the spine KNOWLEDGE Vector index · RAG pgvector — the same engine local and in Azure scopes: platform → enterprise → store ingestion host + console uploads · versioned 06 · ROUTE Router recipient + channel · escalation coalesce · durable retry to TTL 07 · CHANNELS Deliverers in-app SignalR · Web Push (VAPID) fallback chain · delivered→cancel sms · earpiece — not built 08 · PEOPLE Manager & admin apps manager PWA · push · chat admin console · config + monitoring act · dismiss · delegate · ask AUDIT LlmCallRecord every prompt + response · immutable Cosmos + Blob · replayable IDENTITY & TENANCY Fail-closed multi-tenancy IdentityMapper — the Entra External ID callout claims → a (tenant, store) scope on every request no tenant claim ⇒ 401 · isolation failure = P0 every stateful key is variant-namespaced CONTROL PLANE Admin plane & config registry Azure SQL — tenants · stores · users · grants sources registry: every door, admin-owned routing policy · escalation ladder LLM routing as data · daily $ budget gate OPERATIONS Run it anywhere one laptop via .NET Aspire ⇄ 12 Container Apps keyless managed identity · azd + GitHub OIDC OpenTelemetry → Azure Monitor · partition lag /healthz + /readyz · 4 alert rules → alerts@ 09 · LEARN — BUILD PHASE 6 Learning loop outcomes → backtest → prompt evolution improvements ship as context edits via the experiments / variant machinery the audit substrate it needs already exists
§ Inventory Every component, and where it lives
01 · On-prem — at the store
Dashboard connectorconnectors/dashboard
Node/TypeScript + Stagehand. Rides a saved login session on customer hardware, walks the URL-addressable report views of a retail back-office (site adapters; Loyverse is adapter #1), and runs one schema-gated LLM extraction per view. Emits sensor.raw@1 to the platform door; a failed schema is never emitted. Credentials never leave the store.
Screen connectorconnectors/screen
Human-in-the-loop companion UI: the operator shares a tab, the connector narrates it and extracts the readable numbers. Change-detection gates the model calls.
Edge Perception Unitsrc/LumicIQ.Edge
.NET + ONNX. Per-camera pipeline: YOLO11 detect → ByteTrack → subject aggregation, with CLIP appearance re-ID carrying identity across track loss. Two doors: a frame door and a continuous H.264/TS stream door. Emits typed video events + a periodic world-state aggregate, and ships 60-second segments to the cloud world store for lookback. Model artifacts are SHA-pinned and verified at load. Runs on a store box — or, for the synthetic twin only, as a cloud Container App.
Producer tokens · fake cameratools/
ES256 token minting scoped per source (the ingress auth for every door), and a camera stand-in that proves the whole video path without UE5.
Simulation — dev & training
UE5 photoreal store twinsimulator/engine
A digital-twin store: modular kit build, walking shoppers, five virtual cameras producing real video frames. The visual front half of the simulator.
Twin brain — the world enginesimulator/brain
A standalone .NET world engine (its own solution, deliberately outside the platform build): scenarios, shopper behaviour, ground truth, batch mode for load, plus the operator control UI. It docks at the same /ingest/events webhook a real store's sensors use — behind ES256 producer tokens in cloud — so nothing inside the platform fabricates events (ADR-0010).
Eval harnessessimulator/tools · tools/edge-ml
Model export/exporters, the real-model gate, and the scoring scripts that grade edge world-state and the video→VLM cascade against the twin's ground truth.
02–03 · Ingress & spine
Adapters — the doorssrc/LumicIQ.Adapters
The one ingress host: the sensor webhook, the video frame + segment-SAS doors, the pull adapters (OpenWeather, Ticketmaster), and the cloud VLM cascade for stores with no edge box. Dedupes and rate-limits before publish (over-limit is dead-lettered, never dropped), emits source.heartbeat even when quiet, and writes the source-health marker the attention gate reads. Every door is a row in the admin-owned Sources registry — new sources are deploy-free and kill-switchable.
Event Hubs — the spine
Five hubs (events, suggestions-proposed, suggestions-published, conversations, module-metrics) and nine variant-scoped consumer groups. ULID eventId is the platform-wide idempotency key; partitioned by hash(tenant, store).
StateProjectionsrc/LumicIQ.StateProjection
The only writer of current truth. Consumes two hubs on two cursors — the event stream (archive + hot-state markers) and the suggestion lifecycle. Emit-then-project: it never writes back to the spine.
04–05 · Decide & reason
InterestingnessDetectorsrc/LumicIQ.Interestingness
The learned attention gate and the cost control: per-(store, event type, subject, hour-of-week) Welford baselines in Redis with a durable Cosmos backing, emitting anomaly and periodic-tick candidates. No per-tenant configuration — it learns each store's normal.
SafetyNetsrc/LumicIQ.SafetyNet
The deterministic floor: a small set of hardcoded critical conditions, no LLM, plus the one audited-exempt path in the platform — the templated fallback that fires when the agent is down.
The Agentsrc/LumicIQ.Agent · src/LumicIQ.AgentWorker
A persistent reasoner per (tenant, store). The eight-stage pipeline composes the five context layers plus a live NOW block, retrieves scoped knowledge, calls tools (knowledge search, state, source health), validates the model's output, and emits a quantified suggestion — or declines. Writes memory and an immutable LlmCallRecord for every call.
BFFsrc/LumicIQ.Bff
Hosts the same agent in-process for the solicited path: chat answers streamed over SignalR, conversation turns published to the spine, and the published-suggestion fan-out to connected clients. Serves the manager app.
LlmProvider SDKshared/sdks/llmprovider-dotnet
The vendor-agnostic seam (OpenRouter today, a deterministic fake at $0 for gates). Per-task model routing is data — model hint → store assignment → platform table — with a daily USD budget gate and spend roll-up behind the console's LLM Control page.
06–08 · Route, deliver, act
Routersrc/LumicIQ.Router
Coalesces proposals, parses the target expression, resolves recipients (Cosmos employees joined with the Redis roster overlay), walks the tenant's escalation ladder, and durably retries to TTL. It never edits agent-authored content.
PushDeliverersrc/LumicIQ.PushDeliverer
The real Web Push channel (VAPID), with a durable claim row per (suggestion, user) as the dedup gate; a delivery cancels the Router's matching fallback timer.
Manager appweb/manager
The shipped mobile-first PWA: suggestion queue, tasks, team, and chat with the store's agent. Push subscriptions, offline-capable shell, dispositions (acted · dismissed · delegated) back onto the spine.
Admin consoleweb/console
Workspace-scoped admin + monitoring: tenants and stores, access grants, the sources registry, knowledge (upload, versioning, restore), cameras, the segments explorer, LLM control and LLM observability.
Shared design tokensweb/_design
One token + primitive layer both web clients build on, so console and manager stay one product.
Knowledge & memory
KnowledgeIngestionsrc/LumicIQ.KnowledgeIngestion
Ingests the seed corpus idempotently on start and serves the tenancy-gated document surface: chunk → embed → index, retire-and-purge on delete.
Knowledge SDKshared/sdks/knowledge-dotnet
Retrieval with scope precedence (platform → enterprise → store) over a pgvector index — the same engine locally and in Azure. Documents are versioned: immutable snapshots with a current pointer, and retrieval always reads the current version.
Prompts & seed datashared/sdks/prompts-dotnet · prompts/ · data/
Prompt-as-code with pinned composition ids (recorded on every audit record), plus the vertical packs, reasoning contexts, layouts, employees and scenarios the seeder provisions.
Operational stores
Cosmos (records, memory, baselines, audit), Redis (hot state, cooldowns, rate limits, dedup claims, delay queues), Azure SQL (the config registry), Blob (the immutable archive, video frames and segments).
Platform & control plane
Admin hostsrc/LumicIQ.Admin
A separate host from the BFF — the cross-tenant admin posture can't share the BFF's fail-closed-401 pipeline. Owns tenant/store CRUD, admin grants, the sources registry, the platform knowledge plane, the recorded-feed reads, and per-door token minting.
IdentityMappersrc/LumicIQ.IdentityMapper
The Entra External ID custom-auth-extension endpoint: at token issuance it resolves the signing-in user against the SQL registry and returns the lumiciq_* claims the BFF reads (ADR-0006).
Config & registrysrc/LumicIQ.Config
EF Core over Azure SQL: the system-of-record for tenants, stores, users, grants, routing policy, sources, LLM control and the knowledge-document registry. Migrations run at startup.
Cross-cutting SDKsshared/sdks/
Contracts (the one canonical serializer — wire = Cosmos = audit), Tenancy (fail-closed ITenantContext), Variants (the resolver behind every variant-namespaced state key), Persistence, Adapter + Adapter.Abstractions, Seeding.
AppHost & ServiceDefaultssrc/LumicIQ.AppHost
.NET Aspire stands the entire platform — spine, Cosmos, SQL, Redis, Blob, pgvector, every service, and the twin brain — up on one laptop with Docker emulators; the same manifest publishes 12 Azure Container Apps via azd, keyless, on managed identity.
Build phase 6 — not built yet
Learning loop
Outcomes → backtest → prompt evolution, shipped as context edits. The substrate it needs is already there and has been from day one: every LLM call is an immutable, replayable record, and every disposition is captured. What's missing is the machinery that scores and proposes.
Experiments machinery
The variant resolver and variant-namespaced state exist and are load-bearing today; assignment, holdouts and readouts on top of them do not.
Further channels
SMS and the earpiece / walkie-talkie endpoint are designed, not built. In-app SignalR and real Web Push are.
Native mobile client
A React Native client remains a later track; the shipped manager surface is the mobile-first PWA.