Analytics and warehouse
Current analytics facts, typed metrics and explicit source coverage.
The local Sky service now queries durable raw facts through src/sky/events.zig: exact scalar count/sum at coherent data/configuration snapshots, explicit metric version and island, bounded parsing, and cooperative cancellation. It uses observed source coverage and always reports unknown external completeness. Service group/bucket/rolling views and corrections remain pending; the P16 fixture APIs below retain their separate scope.
P16 copies a bounded P15 fact snapshot and records that capture's query-visible position on every result. Metric definitions are versioned and declare whether they count facts or sum integer units; a sum cannot be defined without an explicit asset and scale. Results use [start_ms,end_ms) event-time bounds. Replacements and deletes have already been applied by intake, while reversals remain ordinary signed facts, so refunds subtract exactly once.
Scalar, island-grouped and fixed-duration bucket analyses are bounded to 200 rows. Each result names requested sources, the sources with observations in its window, and the processed position. Missing required source coverage is visible and requireComplete rejects treating it as a zero-valued complete answer.
Rolling schedulers calculate their next expiry from the resolved request time. Polling expired(now) advances expiry even if no intake write occurs. A result holds no mutation lock; later/late intake can change a later capture but cannot alter an already computed result.
Coverage is observed coverage, not proof that every external event arrived. complete() requires a nonempty declared population and at least one matching observation for each required source. Observations must match the selected metric, island (when specified), and half-open time window. Required sources must be unique and number at most 64; duplicates and oversized populations are rejected before evaluation or narrowing counts. An empty population remains incomplete, including when the computed sum is zero. Durable producer manifests/checkpoints and external intake completeness are outside this component.
Bucket row keys have one owner: successful insertion transfers the key to the result, successful accumulation consumes the duplicate key, and errors leave the new key with the caller for rollback. Tests cover the 201st bucket rejection, checked sum/timestamp bucket-boundary overflow and allocation failures without double-free or leaks. A bucket boundary outside the signed timestamp range returns Overflow rather than terminating the process.