App detail resource tiles: point-in-time CPU and memory
Two tiles on RFD-96's app detail view have no source anywhere in cloud: 34% CPU (now) and 512 MB Memory (now). Everything else across all five wireframed views is covered by the app sample, the deploy log, or MIR-1271. This issue is those two tiles and nothing else.
The older cluster status report looks like it might serve them and does not. Its ResourceUsage is whole-cluster utilization percentages and its Version is the Miren software version, both cluster-scoped. A cluster sitting at 34% tells you nothing about one app on it, and the memory tile reads in MB, which a percentage cannot express. Borrowing either would put a confident wrong number in a tile that reads as fact.
The runtime has what's needed on ApplicationStatus: LastMinCPU, LastHourCPU, and memory, all at the app level. Note this is app-scoped, not pool-scoped, so it has no dependency on the pool reporting work.
The cadence question
This is the part worth thinking about rather than the wiring. deriveAppState in appreport.go reduces one ListApps call to a name-keyed map every 15 seconds. ListApps is cheap and app-count-independent in cost. ApplicationStatus is per app, so a cluster running hundreds of apps turns one RPC into hundreds on every sample tick, and reporting is the one thing in that file that must never cost the cluster anything.
Options worth weighing: enrich only on the 15 minute snapshot floor and leave sample ticks cheap, which makes resources visibly coarser than health and obliges the UI to say so; fetch in bounded concurrent batches under a budget; or push the reduction into the runtime so one call returns what cloud needs. RFD-94's freshness target is what settles it.
One thing that helps: LastMinCPU is already a one minute average, so sampling it every 15 seconds smooths rather than fights, and memory bytes don't meaningfully oscillate. Neither of these is a signal where a slower cadence produces a jittery reading, which is why they suit this tier when an instantaneous per-version breakdown would not.
What lands
Runtime side, AppState gains the resource sample and appStateFrom sources it under whatever cadence the above settles. Cloud mirrors the fields in services/cluster_channel/app_handlers.go, extends Sample and the recordSample Lua HSET in services/apps/samples.go, and surfaces them on the app detail read. The tiles then render live instead of absent.
Both fields are nullable end to end and render as absent rather than zero. A cluster reporting under an older contract sends nothing, and 0% CPU is a real reading that must never stand in for "we did not hear." Same distinction MIR-1558 drew between a nil sample and health unknown, one level down.
Out of scope
Historical graphs, which are observability's job (RFD-54). Per-instance resource attribution. Running version, which MIR-1561 projects from the deploy log. Anything that turns the sample into a time series: this tier keeps the latest value and nothing else.