Skip to content
ULAP ONE
Research preview
AI-on-RAN · operator console

ULAP ONE · Command

every capability tagged NOW / PHASE-1 / EXTENSION

Is every process alive, and what is it doing? A chip on this page says a service answered. It does not say the answer is right.

Mode unknown
Waiting Not a snapshot Updated nothing has answered yet Sources 0 of 10 sources answering · 10 waiting
Mode controller no answer yet Subscriber sim no answer yet Attached UEs no answer yet Video analytics no answer yet Workload health no answer yet Local LLM no answer yet
Data provenance

What this console reads, and what it is allowed to conclude

Waiting

Identity

Read by
Your browser, over this origin. No server-side cache sits in between.
Mode
Live poll. This is not a snapshot and it is not a recording.
Last read
not yet
Sources
10

Measurements

Mode controller
Waiting · never
GET /api/mode/status · every 3 s · operating mode, force lock, hysteresis thresholds and dwell
Subscriber sim
Waiting · never
GET /api/subscribers/status · every 3 s · the simulated demand counter and the active scenario. NOT the attach count — see the Attached UEs source below
Attached UEs
Waiting · never
GET /api/ran/ue/attached · every 4 s · the evidenced attach count — a UE holding an IPv4 address on a kernel tunnel that exists right now
Video analytics
Waiting · never
GET /api/analytics/status · every 3 s · frame rate, frames processed, detections and p50 per-frame time
Workload health
Waiting · never
GET /api/{sr,srq,analytics,tvws,paws,mode,evidence}/health · every 5 s · seven service health endpoints, fanned out in parallel
Local LLM
Waiting · never
GET /api/ollama/api/tags · every 5 s · the local model list on the host GPU
RAN manager host metrics
Waiting · never
GET /api/ran/metrics/host · every 5 s · uplink and downlink throughput, and unified GPU memory held by live CUDA contexts
Prometheus
Waiting · never
GET /api/prom/api/v1/query (5 instant queries) · every 5 s · host CPU, host memory, GPU util and network rates
Container list
Waiting · never
GET /api/logs/containers · every 10 s · the docker container inventory behind the log tail
Log tail
Waiting · never
GET /api/logs/logs/{container}?tail=200 · every 4 s · the last 200 lines from the selected container

Thresholds, and where they come from

Stale after 2.5 poll cadences (floor 4 s, cap 90 s)
Source: ui/src/lib/domain/liveness.svelte.ts — derived from wall clock, not set by the poll, so a loop that DIED is still detected
Not answering after 3 consecutive misses
Source: ui/src/lib/domain/liveness.svelte.ts — one miss is a blip, three is a fault
Static after 20 poll cadences with no change in the reported value (floor 60 s, cap 5 min)
Source: ui/src/lib/domain/liveness.svelte.ts — an ORTHOGONAL axis. A static source is still live: it answered. The two facts are separate because on 2026-08-03 a tile read 0.0 Mbps for fifteen minutes beside a chip that said "Live · just now". Only sources that report their value to feed.ok(id, value) are judged; the rest claim nothing.

What this proves

  • Each source above answered your browser at the stated time, over this origin.
  • Every service tile below reflects a real HTTP response, or the absence of one.

What this does NOT prove

  • A service that answered is not a service that is correct. The health endpoints return a status string; nothing here validates what the service then does.
  • The uplink and downlink figures are labelled with the producer’s own `source` field. When that field says "simulated" the number is a CSV trace played back, not a radio measurement.
  • The sim-load counter is not an attachment count and no part of this page treats it as one.
  • Nothing on this page is an authorisation to transmit.

Environment

Fabric
ZMQ virtual RF by default. No antenna is attached to this deployment.
ran-manager
A host process, opt-in. Absent reads as "not deployed", never as a fault.
Local LLM
Opt-in profile. Absent reads as "not deployed", never as a fault.

Provenance

Mode controller
GET /api/mode/status · every 3 s
Subscriber sim
GET /api/subscribers/status · every 3 s
Attached UEs
GET /api/ran/ue/attached · every 4 s
Video analytics
GET /api/analytics/status · every 3 s
Workload health
GET /api/{sr,srq,analytics,tvws,paws,mode,evidence}/health · every 5 s
Local LLM
GET /api/ollama/api/tags · every 5 s
RAN manager host metrics
GET /api/ran/metrics/host · every 5 s
Prometheus
GET /api/prom/api/v1/query (5 instant queries) · every 5 s
Container list
GET /api/logs/containers · every 10 s
Log tail
GET /api/logs/logs/{container}?tail=200 · every 4 s
Caveat, verbatim

Research preview. A healthy chip here means the service responded, not that it is correct. The TVWS classifier in particular answers quickly and was wrong on half of a real over-the-air record set.

Raw source

  • ui/src/lib/domain/gateway.ts the origin fan-out map and the metric-gap register

01 · Co-tenancy and demand

RAN L1 priority AI yields on degrade
Uplink throughput not measured Waiting for the first read from ran-manager /metrics/host.
Downlink throughput not measured Waiting for the first read from ran-manager /metrics/host.
Sim load (counter) -- source: subscriber-sim · counter only, NOT a real attach · scenario --
Attached UEs
Unknown — could not ask

The attach endpoint has not answered yet. Nothing is asserted.

A UE holding an IPv4 address on a kernel tunnel interface that exists right now. Same endpoint as Control Plane and Co-tenancy.

Not the tracked-UE list, and not the sim load beside it.

Source not read yet

Uplink · degrade at 9.0 · recover at 12.0 not measured
Mode unknown Waiting for the mode controller. dwell —

Sim load is a counter, not an attach: subscriber-sim generates demand and nothing registers on a radio for it. Attached UEs is the evidenced count from /api/ran/ue/attached — a UE holding an IPv4 address on a kernel tunnel interface that exists right now — and it is the same endpoint Control Plane and Co-tenancy read, so the three routes agree by construction. Until 2026-08-04 this tile relayed /ue/list through subscriber-sim, which is every UE we track, attached or not; both read 3 that day, so the mislabel was latent and would have diverged the moment a UE was tracked without an address. The relay also returned real_ue_count: 0 both when nothing was attached and when ran-manager never answered; the canonical endpoint keeps those two apart and prints no number at all for the second. Uplink and downlink come from /api/ran/metrics/host, labelled with that producer's own source field; they used to be read from /api/mode/status, which has never returned either field.

02 · AI workloads

AI-for-RAN · AI-and-RAN · AI-on-RAN
SR · SPAN Probing
Real-time x2 display path
not probed yet
AI-ON-RAN sr-worker :8083
SR · RealESRGAN Probing
Archive x4 · HQ capture
not probed yet
AI-ON-RAN sr-worker-quality :8086
Video analytics Probing
Local break-out · privacy-first
not probed yet
AI-ON-RAN :8006 · br-lbo
TVWS sensing Probing
ResNet18 · 6-class · advisory only, 2 of 10 live multiplexes on the 2026-08-04 UHF survey
not probed yet
AI-ON-RAN tvws :8002
Local brain · LLM Probing
Ollama on the GB10
not probed yet
AI-ON-RAN ollama :11434
PAWS · waiver Probing
RFC 7545 · not a regulatory assessment
not probed yet
AI-AND-RAN paws :8087
Mode controller Probing
Hysteresis · AND-gate
not probed yet
AI-FOR-RAN mc :8082
Evidence capture Probing
Pre/post buffer
not probed yet
AI-AND-RAN ec :8084

Three states, not two. Answering, deployed and not answering, and opt-in and never deployed. Absence is neither a pass nor a failure, and the tile names the command that would bring it up.

TVWS sensing is a research preview, not a spectrum-access authority. A healthy chip here means the service responded, not that it is correct. On the 28-channel UHF survey of 2026-08-04 — 560 records, 10 occupied / 15 vacant, ground truth derived from measured physics rather than annotation — this checkpoint detected 2 of 10 live multiplexes, including neither of the two strongest carriers in the band, and called 48 of 300 vacant records occupied, at 0.93 to 0.99 confidence. With the physics detector wired in (same unchanged checkpoint, both arms in one process, differing only in whether a calibrated control floor is passed) it detects 10 of 10 multiplexes and calls 0 of 15 vacant channels occupied. Still not clean: UHF 28 asserts OCCUPIED on 8 of 20 records, and that threshold was not moved. This caveat used to blame the threshold — calibrated on synthetic noise rather than real receiver noise, the same defect one layer down — and a measured receiver-noise null falsified that on 2026-08-05: real receiver noise tops out at comb z = 2.289 against the synthetic 2.19, and 0 of 300 records reach the 3.5 threshold. The firing arrives through the antenna and its cause is now open: a genuine emission below the energy floor, which would mean the ground truth needs revising rather than the detector, or front-end intermodulation. The RX-gain sweep that separates them has not been run. The earlier “40 of 80” figure came from a 2026-07-29 set that was entirely occupied: a detector answering OCCUPIED unconditionally also scores 80 of 80 on it, so it measured no discrimination. Rollout is opt-in and the running service was not restarted — with no calibrated control floor configured the engine falls back to the legacy CNN verdict and reports occupancy_source: cnn-confidence, so any live occupancy verdict here is the classifier’s unless a floor is set. Model confidence is not accuracy and not reliability: high confidence has been measured on wrong answers, so the theta_sense = 0.85 gate does not catch them. PAWS grant state is the authority; sensing is advisory.

03 · Video pipeline

SPAN real-time · RealESRGAN archive · local break-out analytics
Degraded · uplink · 480p
SR · SPAN · 1080p
Analytics fps --fps source: video-analytics · target, not achieved rate
Frames processed -- cumulative · local break-out
Detections -- profile · --
p50 per-frame --ms privacy: local-break-out bound

The two players are the degraded uplink and the SPAN super-resolution output, side by side. Neither panel probes its own geometry, so the captions state the pipeline's configured geometry rather than a measured one.

04 · NTN backhaul

declared metric gap no producer · not polled
No producer GET /api/mode/ntn asked by this card

NO PRODUCER. mode-controller has no /ntn route; its OpenAPI is /health /mode /status /events /config /force /reset /metrics.

The panel reads "not reported" and stops polling after the first miss. It previously rendered a hardcoded "clear", which is a claim that no impairment is applied — exactly the claim nobody measured.

Profiles make ntn-simulate can apply — reference only. None of the four is ever drawn as active, because nothing reports which one is.
Clear
Terrestrial baseline
0 ms · unlimited
LEO
Low-earth orbit
~30 ms · 150 Mbps
MEO
Medium-earth orbit
~150 ms · 50 Mbps
GEO
Geostationary fallback
~540 ms · 10 Mbps

No service reports which profile is applied, so none of the four above is highlighted and this page does not poll for it. Apply one from the operator host: make ntn-simulate MODE=leo|meo|geo|clear. The profile is applied on the UPF N6 uplink with tc netem; the link becomes high-latency and low-rate while the 5G core keeps serving UEs through the local break-out for the AI workloads.

05 · Containers

logs-proxy Logs-proxy has not answered yet.
Docker containers reported by logs-proxy, with their state, health and first published port
CONTAINERSTATEHEALTHPORT
Logs-proxy has not answered yet.

06 · Logs

logs-proxy
Select a container to tail its logs.

Read-only. logs-proxy exposes the docker log tail and the container list and nothing else. When it stops answering the pane keeps the last lines it did return and says so above, rather than blanking and implying silence.

07 · Host metrics

prometheus
Host CPU no series source: prometheus via /api/prom
Host memory no series source: prometheus via /api/prom
GPU util no series source: prometheus via /api/prom
Net RX no series source: prometheus via /api/prom
Net TX no series source: prometheus via /api/prom
GPU memory (unified) not measured no DCGM framebuffer series exists on the GB10

A tile reading no series means the query returned nothing: either the exporter is not running, or the metric does not exist on this host. Those are different faults. GPU memory is the exception and does not come from Prometheus — the GB10 exports no DCGM_FI_DEV_FB_USED series at all, so the tile reads ran-manager instead and is labelled unified, because this part shares one pool with the CPU and has no dedicated framebuffer. The full method is one click away.

Demand and throughput

What the UE counts and the throughput figures on this card actually are

Sim load is a counter Throughput not measured

Identity

Sim load
subscriber-sim, an in-process demand generator with no radio behind it
Attached UEs
ran-manager GET /ue/attached — the EVIDENCED count. Until 2026-08-04 this tile relayed /ue/list (every UE we track, attached or not) through subscriber-sim and called it attached.
Throughput
ran-manager /metrics/host, throughput block
Throughput kind
not reported by the producer

Measurements

Sim load
--
A counter only, NOT a real attach. This figure used to be printed under the label "Attached UEs".
Attached UEs
unknown — could not ask
Nothing is asserted. The attach endpoint has not answered yet. Nothing is asserted.
Uplink
not measured
source: ran-manager /metrics/host
Downlink
not measured
source: ran-manager /metrics/host

Thresholds, and where they come from

Degrade below 9.0 Mbps uplink, held for 3 s
Source: mode-controller settings — ul_degrade_threshold and degrade_dwell_seconds
Recover above 12.0 Mbps uplink, held for 12 s
Source: mode-controller settings — ul_recover_threshold and recover_dwell_seconds

What this proves

  • The mode controller answered, and the mode shown is the one it reported.
  • The two UE figures come from two different producers and are never added together.

What this does NOT prove

  • The sim load is NOT an attach count. No UE registered, no PDU session was created, no radio carried anything for it.
  • A "simulated" throughput source is a CSV trace played back, not a measurement of a radio link.
  • A real-attached count of 0 does not prove zero attaches: subscriber-sim reports 0 when ran-manager does not answer it.

Environment

Fabric
ZMQ virtual RF by default. No antenna, no over-the-air transmission.
ran-manager
A HOST process, opt-in. Compose never brings it up; `make ran-start` does.

Provenance

Mode
GET /api/mode/status
Sim load and real attach
GET /api/subscribers/status
Throughput
GET /api/ran/metrics/host — throughput.ul_mbps / dl_mbps / source
Caveat, verbatim

Until 2026-08-04 this card printed "Attached UEs 50" from a payload that reported real_ue_count: 0 in the next field, and read ul_mbps / dl_mbps off /api/mode/status — an endpoint that has never returned either field, so both tiles showed a permanent dash while naming a source. Three routes gave three different answers for one quantity; only Control Plane distinguished them.

Raw source

  • services/subscriber-sim/main.py — GET /status where real_ue_count is computed, and swallowed
  • services/mode-controller/main.py — ModeController.get_status the full field list; there is no uplink in it
Host and GPU

What the host tiles measure, and the one counter this part does not have

GPU memory not measured Unified, not VRAM

Identity

CPU, memory, network
node-exporter, scraped by Prometheus
GPU util
dcgm-exporter — DCGM_FI_DEV_GPU_UTIL, a live series on this part
GPU memory
ran-manager /metrics/host — nvidia-smi --query-compute-apps=used_memory, summed
Part
NVIDIA GB10, aarch64, sm_121 — a dev-class ARM box, not a qualified RAN platform

Measurements

Host CPU
no series
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100)
Host memory
no series
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
GPU util
no series
avg(DCGM_FI_DEV_GPU_UTIL)
Net RX
no series
sum(rate(node_network_receive_bytes_total{device!~"lo|docker.*|veth.*|br-.*"}[1m])) / 1048576
Net TX
no series
sum(rate(node_network_transmit_bytes_total{device!~"lo|docker.*|veth.*|br-.*"}[1m])) / 1048576
GPU memory (unified)
not measured
Not measured yet — DCGM on the GB10 exports no FB_USED/FB_FREE series, so this tile waits on ran-manager /metrics/host.

Thresholds, and where they come from

A tile reading "no series" the query returned nothing
Source: Either the exporter is not running, or the metric does not exist on this host. Those are different faults and the drawer names which applies to GPU memory.

What this proves

  • The host figures shown were returned by Prometheus for the exact query printed beside each one.
  • GPU utilisation on the GB10 IS a live DCGM series — that part of the exporter works.

What this does NOT prove

  • The GPU memory figure is NOT framebuffer occupancy. It is a share of one pool the CPU also allocates from, so it cannot be read as "how full the card is".
  • A missing series is not a zero. Nothing on this card substitutes a plausible-looking number for one it could not read.

Environment

Scrape
Prometheus, through the same-origin gateway at /api/prom
Refresh
Five seconds, from this browser

Provenance

Host metrics
GET /api/prom/api/v1/query
GPU memory
GET /api/ran/metrics/host
Caveat, verbatim

COUNTER DOES NOT EXIST ON GB10 — this is not a broken scrape. dcgm-exporter DOES enumerate the GB10 (GPU_UTIL, GPU_TEMP, MEMORY_TEMP, MEM_COPY_UTIL, POWER_USAGE, SM_CLOCK all return series) but it exports zero DCGM_FI_DEV_FB_USED / FB_FREE / FB_TOTAL series for this part, and `nvidia-smi --query-gpu=memory.used/free/total` returns literal N/A. The earlier note here — "dcgm-exporter does not enumerate the GB10" — was wrong; GPU util has been live all along.

Raw source

  • ui/src/lib/domain/gateway.ts — METRIC_GAPS the register Explorer renders
Amini Amini Infratech for the Global South

Every link and every data fetch on this console is origin-relative. One origin fans out by path: / gateway, /video/, /grafana/, /prom/, /api/. An absolute http://localhost:NNNN URL works on exactly one machine, the one it was written on, and is blocked as mixed content the moment the page is served over https, which is how every operator actually reaches this stack.