import type { AnyEvent, SceneProxy, SceneRegion } from "@uptimizr/schema"; import type { AgentAuditEntry, AgentAuditInput, AuditQueryOptions, CameraDistanceBucketRow, CameraModeOptions, ClickGazeRayRow, CoverageVoxelRow, DeadClickRow, DirectionBinRow, ViewCoverageHistogramRow, EventTypeCountRow, FlowLinkRow, FunnelStepInput, FunnelStepResultRow, SceneRetentionOptions, SceneRetentionRow, LoadBounceFunnelOptions, LoadBounceBandRow, VariantLeaderboardOptions, VariantLeaderboardRow, HeatmapBinRow, HoverDwellRow, CompileStallRow, ArPlacementTimeToPlaceRow, ArPlacementAttemptsRow, ArPlacementSurfaceRow, ResourceSummaryRow, CapabilityChangeRow, CameraGestureRow, MeshCountRow, MetricBucketOptions, MetricBucketRow, MeshDwellRow, MeshBlindSpotRow, MeshInteractionKindRow, ReachabilityBinRow, MeshSourceCountRow, MeshTrendPointRow, MetricQueryOptions, InputActionCountRow, CustomEventVocabularyOptions, CustomEventVocabularyRow, PositionBinRow, PerfHeatmapVoxelRow, RageClickRow, NavigationStatsRow, BacktrackRatioRow, XrRotationRateRow, XrSourceUsageRow, XrAbandonmentRow, XrLocomotionRow, BoundaryContactsRow, TrackingQualityRow, InteractionSourceRow, PerfSummaryRow, PerfDistributionRow, FpsHistogramRow, FrameTimePercentileRow, JankRateRow, PerfChurnOptions, PerfChurnRow, PerfByDeviceRow, PerfBySceneRow, ResourcePercentileRow, RenderScaleTruthRow, AggregateTrajectoryPointRow, ResolvedApiKey, StabilityCountRow, GraphicsDiagnosticCountRow, RenderingTechnologyRow, RangeOptions, RegionOptions, ErrorHeatmapOptions, SceneOptions, SceneRegionRecord, SceneRegionSummary, AnnotationRecord, CreateAnnotationInput, CreatePanelSpecInput, CreateSavedAnalysisInput, GlossaryEntryRecord, ListAnnotationsOptions, MetadataListOptions, PanelSpecRecord, PutGlossaryEntryInput, SavedAnalysisRecord, UpdatePanelSpecInput, SceneRepresentation, SceneRepresentationSummary, SceneRow, SourceOptions, SubscriptionStore, SessionOptions, MeshOptions, SessionMeta, SessionSummaryRow, SpatialStatsRow, TimeseriesBucketRow, TimeseriesOptions, TrajectoryPointRow, WorldHeatmapBinRow, QuerySpec } from "@uptimizr/db"; import type { MetricId } from "@uptimizr/metrics"; /** The storage engines a collector can be wired to (`COLLECTOR_STORE`). */ export type StoreEngine = "duckdb" | "postgres" | "mssql" | "clickhouse" | "memory"; /** * The data-access surface the routes depend on. Abstracting it behind an * interface keeps handlers thin and lets tests inject a fake store without a * live ClickHouse/Postgres (the framework and the DB stay swappable — ADR 0005). */ export interface CollectorStore extends SubscriptionStore { /** * Which storage engine is behind this store. Descriptive only — no handler * branches on it — but the project context document reports it (ADR 0051 §5) * so an agent knows whether it is reading a single-file DuckDB collector or a * scale-tier engine before it reasons about freshness or volume. */ readonly engine: StoreEngine; /** * Resolve a plaintext API key to its project id, key id, capability set and * optional per-key rate limit, or `null` if invalid/revoked. The capability * set scopes what the key may do at the request boundaries (query, raw * session access, metadata writes, live token exchange). */ resolveApiKey(key: string): Promise; /** * Append one agent-audit row (#309, ADR 0051 §7). Called fire-and-forget after * the response is sent — it must never be relied on to block a request. */ recordAudit(entry: AgentAuditInput): Promise; /** Read a project's audit rows, newest first, within an optional range. */ listAudit(projectId: string, opts?: AuditQueryOptions): Promise; /** Delete audit rows older than `cutoffMs` (epoch ms). Idempotent. */ pruneAudit(cutoffMs: number): Promise; /** * Whether a project with this id exists. The ingest route uses it to reject * events for unknown projects — the public `projectId` is the ingest credential, * so a non-existent project must never have data written under it. */ projectExists(projectId: string): Promise; /** Batched insert of enriched, validated events. */ insertEvents(events: readonly AnyEvent[]): Promise; /** * Run **any** registry metric by id, with an option bag the query DSL * assembled from a validated `queryV1` document (ADR 0051 §3). * * The one method the DSL needs, and deliberately the only one it adds: every * store implements it as `runQuery(compileMetric(…, Dialect))`, * so a DSL query takes exactly the path a canned aggregate takes — the same * builders, the same dialect, the same cross-engine parity harness and the * same numeric coercion at the driver edge. Putting the dispatch in the * collector instead would have given the DSL a second, unverified query path. * * Rows are returned untyped because the shape depends on the metric; the * registry `row` schema is what describes them, and the response layer * (`format=table|summary`) reads that. */ runMetric(projectId: string, metric: MetricId, options: MetricQueryOptions): Promise[]>; /** * Render the same query {@link runMetric} would run, **without running it** — * the compiled `QuerySpec` and the name of the engine that would execute it * (ADR 0051 §3, #304). * * This is what `explain: true` answers with. It has to be a store method for * the one reason the DSL has a store seam at all: the dialect is the store’s, * and the collector deliberately does not know which engine it is talking to. * Returning the spec rather than a rendered string keeps the redaction * decision (`explainSpec`) in one place instead of four. * * `null` from a store that compiles no SQL (the in-memory one), so `explain` * degrades to the warnings rather than failing. */ describeMetric(projectId: string, metric: MetricId, options: MetricQueryOptions): { dialect: string; spec: QuerySpec; } | null; listSessions(projectId: string, opts?: RangeOptions & CameraModeOptions & { limit?: number; }): Promise; pointerHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & CameraModeOptions & { bins?: number; }): Promise; /** * Per-mesh texture-space (UV) heatmap (#149): bin the `uv` texture coordinates * of interaction events on one mesh into a `bins x bins` grid over the object's * own UV space — the surface-attention companion to {@link worldHeatmap}. Pass * `mesh` to scope it to a single object (the usual per-product view). */ meshUvHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & MeshOptions & { bins?: number; }): Promise; /** World-space (3D) pointer heatmap: voxel-binned raycast hit points. */ worldHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & RegionOptions & CameraModeOptions & { cellSize?: number; limit?: number; }): Promise; /** * Scene-wide totals for the world heatmap (ADR 0040 §3): true occupied-cell and * hit counts behind the truncated top-N voxels (no `LIMIT`), so the viewer can * report coverage/cold-spots and "showing top N of M cells". Region-aware. */ worldHeatmapStats(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & RegionOptions & CameraModeOptions & { cellSize?: number; }): Promise; /** * World-space (3D) gaze heatmap (ADR 0030): voxel-binned camera-pose gaze * surface hits (`camera_sample.hitPoint`). The "what did people actually look * at" map — distinct from the click-driven world heatmap. Optional `session` * scopes it to one visit (ADR 0010 §1a). */ gazeHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & RegionOptions & CameraModeOptions & { cellSize?: number; limit?: number; }): Promise; /** Scene-wide totals for the gaze heatmap (ADR 0040 §3); region-aware, no `LIMIT`. */ gazeHeatmapStats(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & RegionOptions & CameraModeOptions & { cellSize?: number; }): Promise; cameraHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & CameraModeOptions & { bins?: number; }): Promise; /** * 360° view-coverage histogram (#146): how much of a 3D object each session * actually looked at, bucketed across sessions. Each session's `camera_sample` * directions are binned into the view-direction dome grid; the fraction of the * `bins × bins` cells it visited is its coverage score, and sessions are grouped * into 25%-wide coverage buckets (`0`/`25`/`50`/`75`). Purely derived — no schema * change. */ viewCoverageHistogram(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & CameraModeOptions & { bins?: number; }): Promise; /** * Top-down "floor plan" camera-position heatmap (ADR 0026): `camera_sample` * world positions binned on the X/Z ground plane. The first-person analog of * the 2D pointer heatmap. */ cameraPositionHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & RegionOptions & CameraModeOptions & { cellSize?: number; limit?: number; }): Promise; /** One session's ordered walked path (ADR 0026): camera positions, oldest first. */ sessionTrajectory(projectId: string, sessionId: string, opts?: RangeOptions & SceneOptions & { limit?: number; }): Promise; /** * Aggregate desire lines (#73, ADR 0037): every session's `camera_sample` * path binned onto the X/Z ground grid and returned as ordered points keyed by * session, so the consumer can overlay many low-opacity poly-lines into a * crowd-level picture of the routes visitors actually walk. */ aggregateTrajectories(projectId: string, opts?: RangeOptions & SceneOptions & CameraModeOptions & { cellSize?: number; limit?: number; }): Promise; /** * View-gated click rays (design §7.2/§7.3): each `pointer_click` correlated to * the nearest preceding `camera_sample`, aggregated into camera-origin → hit * rays grouped by voxel and clicked mesh. */ clickGazeRays(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { cellSize?: number; limit?: number; }): Promise; /** * Aggregate gaze→mesh flow links (design §7.5): click-time camera direction * bins joined to clicked meshes. In position-aware mode (§7.8) the click-time * camera position is restored as a standpoint voxel dimension. */ flowHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & CameraModeOptions & { bins?: number; limit?: number; cellSize?: number; groupByOrigin?: boolean; originVoxel?: readonly [number, number, number]; }): Promise; topMeshes(projectId: string, opts?: RangeOptions & SessionOptions & { limit?: number; }): Promise; /** * Per-mesh source split (#74): the most-interacted-mesh tally broken out by the * input `source` that drove each interaction. Summing a mesh's rows reproduces * its `topMeshes` total, so the leaderboard reads rank + per-row breakdown here. */ topMeshesBySource(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { limit?: number; }): Promise; /** * Per-mesh interaction trend (#74): the most-interacted-mesh tally bucketed into * fixed `interval`-second windows, for the leaderboard's per-mesh sparkline and * rising/falling delta. Each row is a `(mesh, bucket)` count, oldest bucket first. */ topMeshesTrend(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { interval?: number; limit?: number; }): Promise; /** * Object dwell ranking (#37): per-mesh attention from `mesh_visibility` * summaries — total visible/centered time and peak screen fraction. */ meshDwell(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * Blind-spot / never-noticed meshes (#143): per mesh, `mesh_visibility` * on-screen time cross-referenced against `mesh_interaction` + `hover_dwell` * engagement. Surfaces objects that render but are never noticed (high * visibility, zero/near-zero engagement) — the inverse of the leaderboard. */ meshBlindSpots(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * Interaction-kind breakdown (#72, ADR 0023): per-mesh counts of each * interaction kind (hover / pick / click / drag / …) from `mesh_interaction` * events — *how* people act on objects, not just which ones draw attention. */ meshInteractionKinds(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { limit?: number; }): Promise; /** * Reachability report (#151): per-mesh histogram of the standpoint→interaction * distance — how far each interacted mesh sat from the click-time camera * position. Far distance bands flag meshes/UI reached from an uncomfortable * range (VR/first-person layout feedback). Derived by ASOF-joining * `mesh_interaction` world points to the nearest preceding `camera_sample`. */ reachability(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { bucketSize?: number; limit?: number; }): Promise; /** * Dead-click rate (#46): total clicks vs. clicks that hit empty space, from * `pointer_click` events. The consumer derives the rate. */ deadClicks(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions): Promise; /** * Rage clicks (#47): rapid repeated clicks on the same mesh, bucketed into * fixed time windows; a frustration signal derived from the click stream. */ rageClicks(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { interval?: number; minRepeats?: number; limit?: number; }): Promise; /** * Hover hesitation (#48): per-mesh dwell time spent hovering an object without * clicking it, from `hover_dwell` summaries. Surfaces objects that look * interactive but aren't (or aren't obviously clickable). */ hoverDwell(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { limit?: number; }): Promise; /** * Compile stalls (#42): per-phase shader/pipeline compilation hitches from * `compile_stall` events — the felt first-interaction jank `frame_perf` * averages away. */ compileStalls(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * AR placement time-to-place distribution (#156, ADR 0048): a histogram of how * long each `ar_placement` settle took, in `bucketMs`-wide bins — the AR * analogue of add-to-cart latency for "view in your room" experiences. */ arPlacementTimeToPlace(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { bucketMs?: number; }): Promise; /** * AR re-placement distribution (#156, ADR 0048): settles grouped by their * `attempts` count — a long right tail flags placement friction. */ arPlacementAttempts(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * AR placement surface breakdown (#156, ADR 0048): per coarse surface bucket, * the number of settles and their average committed scale. */ arPlacementSurfaces(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Resource footprint (#44): GPU / memory cost summary from `resource_sample` * events — average and peak texture/geometry bytes, triangles/vertices, and JS * heap the scene asked of the device (vs. the device caps in `session_start`). */ resourceSummary(projectId: string, opts?: RangeOptions & SessionOptions): Promise; /** * Capability changes (#49): per-transition fallback/recovery counts from * `capability_change` events (e.g. how many sessions fell back WebGPU→WebGL2) * — explains perf / visual-fidelity variance across the user base. */ capabilityChanges(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * Camera gestures (ADR 0025): per-kind navigation breakdown from * `camera_gesture` events (orbit / pan / dolly / zoom / roll / fly) — how an * audience moves the viewpoint, separated from object selection. */ cameraGestures(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { limit?: number; }): Promise; perfSummary(projectId: string, opts?: RangeOptions & SessionOptions): Promise; /** * Render-scale truth (#71, ADR 0021): the FPS headline paired with the * resolution the engine actually rendered at, so a "good FPS" reading can be * read honestly against the `render_scale` an adaptive renderer bought it with. */ renderScaleTruth(projectId: string, opts?: RangeOptions & SessionOptions): Promise; /** * FPS distribution (ADR 0028 §1): per-session p05/p50/p95 FPS summarized across * sessions (median-of-medians), so neither long sessions nor fast devices skew * the headline. The distribution-honest replacement for the volume-chart mean. */ perfDistribution(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** Histogram of per-session median FPS in `bucket`-wide bins (ADR 0028 §1). */ fpsHistogram(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { bucket?: number; }): Promise; /** * Frame-time percentiles in ms (ADR 0028 §1): per-session median frame time and * worst-window p95, summarized across sessions. */ frameTimePercentiles(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Jank rate (ADR 0028 §1): per-session long-frames-per-window rate, reported as * the median and worst-decile session. */ jankRate(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Perf-correlated churn (#144): of the sessions that ended in range, how many * ended within `windowMs` of an FPS dip (`fps < fpsThreshold`) or a * `compile_stall` of at least `stallMs`, with the cause attributed. A single * correlation row — does a stutter actually cost sessions? */ perfChurn(projectId: string, opts?: PerfChurnOptions): Promise; /** * FPS by device class (ADR 0028 §2): per-session median FPS attributed to the * `session_start.device` block (graphics backend, mobile flag, GPU renderer) — * data already on the wire, no SDK change. */ perfByDevice(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** FPS by scene (ADR 0028 §1): per-session median FPS grouped by scene. */ perfByScene(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Resource-footprint percentiles (ADR 0028 §1): per-session p50/p95 of JS heap, * texture bytes, and triangle count summarized across sessions. */ resourcePercentiles(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** Stability incidents: context-loss and compile-stall counts over the range. */ stabilityCounts(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Opt-in engine diagnostics (#16, ADR 0021 part 2): `graphics_diagnostic` * incident counts crossed by `(severity, category, backend)` over the range, * folding discrete markers and per-session rollups into the same counters. */ graphicsDiagnosticCounts(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Spatial error heatmap (#154): voxel-binned world `position` of positioned * `runtime_error` and `graphics_diagnostic` events — *where* in the scene things * break. Optional `severity`/`category` narrow to engine diagnostics, `errorKind` * to JS errors. Region-aware; reuses the promoted `position` column (no migration). */ errorHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & RegionOptions & ErrorHeatmapOptions & { cellSize?: number; limit?: number; }): Promise; /** * Guardian/boundary-touch heatmap (#157, ADR 0048): voxel-binned world * `position` of `xr_boundary_proximity` events — *where* in the play space the * headset approached its guardian boundary. The boundary polygon and room * geometry are never captured; only the coarse position + duration each event * already carries (computed on-device) participate (ADR 0003 / ADR 0048). * Region-aware; reuses the promoted `position` column (no migration). */ boundaryHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & RegionOptions & { cellSize?: number; limit?: number; }): Promise; /** * Scene-wide totals for the boundary-touch heatmap (ADR 0040 §3): true * occupied-cell and contact counts behind the truncated top-N voxels (no * `LIMIT`), so the viewer can report coverage and "showing top N of M cells". * Region-aware; shares every filter with {@link boundaryHeatmap}. */ boundaryHeatmapStats(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & RegionOptions & { cellSize?: number; }): Promise; /** * Always-on rendering-technology mix (#120, ADR 0021 part 1): `session_start` * counts crossed by `(api, backend, api_version, shading_language)` over the * range. Always-on, so a populated result is the common case. */ renderingTechnology(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions): Promise; /** * Scene coverage / dead zones (derived, scene-metrics §B): occupied * camera-position voxels. Coverage % is computed by the consumer against the * scene AABB. */ sceneCoverage(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { cellSize?: number; limit?: number; }): Promise; /** * Spatial FPS heatmap (#145): `frame_perf` samples voxel-binned by their captured * camera position, each cell reporting its sample count, mean FPS, and worst FPS. * The spatial complement to the time-bucketed perf distribution. */ perfHeatmap(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { cellSize?: number; limit?: number; }): Promise; /** * Camera distance / zoom distribution (derived, scene-metrics §B): histogram of * camera-to-`center` distance, bucketed by `bucketSize` world units. */ cameraDistance(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { center?: readonly [number, number, number]; bucketSize?: number; limit?: number; }): Promise; /** * Navigation effort / friction (derived, scene-metrics §B): per-session travel * distance with active-vs-idle segmentation. */ navigationStats(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { moveThreshold?: number; limit?: number; }): Promise; /** * Path-retrace / backtracking ratio (#153): a per-scene leaderboard of how * often visitors re-walk a coarse grid cell, derived from the `camera_sample` * position stream — a confusion / unclear-signage signal. */ backtrackRatio(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { cellSize?: number; limit?: number; }): Promise; /** * XR motion-sickness proxy (#50, scene-metrics §F): per-session head/view * rotation rate over the `camera_sample` pose stream — rapid view rotation is * the comfort/discomfort signal. */ xrRotationRate(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { rapidTurn?: number; limit?: number; }): Promise; /** * XR input-source usage (#50, scene-metrics §F): hand vs. controller (vs. gaze) * split read from `source` on the interaction events. */ xrSourceUsage(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * XR session abandonment (#50, scene-metrics §F): per XR session, its time * bounds and event/interaction counts — a short span signals headset drop-off. */ xrAbandonment(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * XR locomotion & comfort (#148): per XR session, its locomotion-style * breakdown (fly / navigate / teleport counts + duration) and wall-clock span, * so heavy locomotion can be correlated with early exits (a discomfort proxy). */ xrLocomotion(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * Per-session guardian/boundary-contact rollup (#157, ADR 0048): for every * session that approached its play-space boundary, the number of approaches and * the total time spent in the near-boundary zone — a room-scale comfort signal * shown alongside the VR locomotion dashboard. Built from `xr_boundary_proximity` * events (one per approach); no boundary geometry participates. */ boundaryContacts(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * XR tracking quality (#155, ADR 0048): per XR session that reported a tracking * transition, how much of the session ran with degraded / lost spatial tracking, * split by hand vs. controller. Turns `capability_change { kind: "tracking" }` * transitions into a tracking-quality timeline (% of a session spent degraded) * that FPS/perf metrics can't reveal. */ trackingQuality(projectId: string, opts?: RangeOptions & SceneOptions & SessionOptions & { limit?: number; }): Promise; /** * Input-source breakdown (ADR 0011): per `(event_type, source)`, how many * interactions came from each input source (mouse / touch / xr-controller / * hand / …) and across how many sessions — turns `source` into an insight. */ interactionsBySource(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { limit?: number; }): Promise; /** * Most-used shortcuts / actions (#75, ADR 0023): rank `input_action` events by * their app-level `action` label, split by `source` (keyboard / gamepad / …). * Pairs with `interactionsBySource` (the modality share) for the input panel. */ topInputActions(projectId: string, opts?: RangeOptions & SceneOptions & SourceOptions & SessionOptions & { limit?: number; }): Promise; /** * Discovered custom-event vocabulary (ADR 0051 §5): the developer-defined * `custom` event names the project emits, with their counts, distinct sessions * and the union of `props` keys observed on a bounded sample of each name's * most recent payloads. The store folds the sampled payloads into prop types * itself — the raw payload is an implementation detail and never leaves this * layer. */ customEventVocabulary(projectId: string, opts?: CustomEventVocabularyOptions): Promise; /** Distinct scenes (+counts, last-seen) for the project; time-range aware (ADR 0010). */ scenes(projectId: string, opts?: RangeOptions & { limit?: number; }): Promise; /** Event-volume time-series bucketed by interval (the 4th dimension). */ timeseries(projectId: string, opts?: RangeOptions & SceneOptions & TimeseriesOptions): Promise; /** Per-event-type counts over the range (powers the scene health panel). */ eventTypeCounts(projectId: string, opts?: RangeOptions & SceneOptions): Promise; /** * The per-bucket series of one metric's comparable headline column — the one * store read both insight primitives are built on (ADR 0051 §4). * * A single generic aggregation rather than one store method per insight: what * differs between metrics is the *series*, and that difference is declared as * data in `@uptimizr/db`'s `src/insights/measures.ts`. Everything computed * from the series — mean, median, MAD, quantiles, slope, robust z — is pure * TypeScript, so no two engines can disagree about an insight. * * `opts.metric` must name a metric that has a portable bucket series; the * route validates that at the edge and answers `400` with the list of ids that * do, so an implementation may assume it. * * `opts.series` (#307) selects one of that metric’s **named auxiliary * series** instead — a rate denominator, an FPS tail — declared beside the * main measure in the same catalog. It is a compile-time union set by the * insight layer, never a caller-supplied string, and a metric may declare a * variant without being bucketable in its own right. */ metricBuckets(projectId: string, opts: MetricBucketOptions): Promise; /** * Single-project configurator funnel (#78, ADR 0038): ordered, per-session * step-reach with the drop-off between consecutive steps. Each row is * `(step, sessions)` — the number of sessions that reached step `k` in order. * `steps` are supplied by the caller (request input / CLI / hosted), since the * OSS dashboard is a passive viewer with no authoring surface. */ funnel(projectId: string, opts: RangeOptions & SceneOptions & CameraModeOptions & { steps: readonly FunnelStepInput[]; }): Promise; /** * Canned scene/level retention funnel (#147): session counts flowing scene → * scene in observed order, built directly from `scene_change` markers with no * caller-authored steps. Each row is `(from_scene, to_scene, sessions)` — the * number of distinct sessions that made that consecutive transition — so * level-to-level drop-off is visible with zero configuration. Complements the * caller-authored funnel (ADR 0038). */ sceneRetention(projectId: string, opts: SceneRetentionOptions): Promise; /** * Load → bounce/abandon funnel (#152): bucket sessions by their initial * `asset_load` load time and report, per band, how many sessions **bounced** — * produced no interaction (`pointer_*` / `mesh_interaction` / `camera_gesture`) * at or after that load. Makes "slow load costs you customers" a concrete * number. Bands are caller-supplied ascending ms boundaries (a sensible default * applies when omitted); no schema change — derived from existing events. */ loadBounceFunnel(projectId: string, opts?: LoadBounceFunnelOptions): Promise; /** * Variant → conversion leaderboard for product configurators (#150): per * variant (a `custom` event grouped by its `name`), the view count, distinct * sessions, conversions to an optional "success" event, and mean dwell before * the next variant switch or conversion. Like the funnel, the `variant` / * `conversion` predicates are supplied by the caller (OSS is a passive viewer, * ADR 0038); ranked by views and capped by `limit`. */ variantLeaderboard(projectId: string, opts: VariantLeaderboardOptions): Promise; /** Ordered session timeline for replay (gated by raw-session retention). */ getSessionEvents(projectId: string, sessionId: string): Promise; /** * Streaming counterpart to {@link getSessionEvents}: yields events in `ts` * order without materializing the whole session, powering the NDJSON replay * response (ADR 0015). Gated by raw-session retention like the array form. */ streamSessionEvents(projectId: string, sessionId: string): AsyncIterable; /** Coarse per-session descriptor (device/scene/user) from `session_start`. */ getSessionMeta(projectId: string, sessionId: string): Promise; /** Register/replace a scene's proxy geometry in the spatial registry (ADR 0010/0014). */ putSceneProxy(projectId: string, proxy: SceneProxy, label?: string): Promise; /** Fetch one scene representation (including the proxy blob), or `null`. */ getSceneRepresentation(projectId: string, sceneId: string): Promise; /** List a project's scene representations (summaries, no proxy blobs). */ listSceneRepresentations(projectId: string): Promise; /** * Replace a scene's whole region set (ADR 0051 §2 / sketch §B.2) and return * the stored rows. Replace-the-set — not per-region upsert — keeps authoring * a single idempotent declaration: removing a region is leaving it out, and * an empty array clears the scene. Every store applies it atomically, so a * concurrent reader never sees a half-replaced set. */ putSceneRegions(projectId: string, sceneId: string, regions: readonly SceneRegion[]): Promise; /** Read one scene's regions, ordered by region id. Empty when none are registered. */ getSceneRegions(projectId: string, sceneId: string): Promise; /** * Lightweight project-wide region listing (scene id, region id, label — no * boxes): the whole spatial vocabulary in one read, for a region picker or an * agent's project context. The sibling of {@link listSceneRepresentations}; * kept separate so the scene listing stays exactly as it is. */ listSceneRegions(projectId: string): Promise; /** Create one annotation and return the stored row. */ createAnnotation(projectId: string, input: CreateAnnotationInput): Promise; /** * A project's annotations, newest first. `since`/`until` are an **overlap** * filter — an annotation matches when its period intersects the window, and a * standing note (no period) always matches. */ listAnnotations(projectId: string, opts?: ListAnnotationsOptions): Promise; /** Delete one annotation of this project; `false` when the id is unknown. */ deleteAnnotation(projectId: string, id: string): Promise; /** Upsert one glossary entry — the term is the identity, so writes are idempotent. */ putGlossaryEntry(projectId: string, input: PutGlossaryEntryInput): Promise; /** A project's whole glossary, ordered by term. */ listGlossary(projectId: string, opts?: MetadataListOptions): Promise; /** Delete one term; `false` when it was not defined. */ deleteGlossaryEntry(projectId: string, term: string): Promise; /** Create one saved analysis and return the stored row. */ createSavedAnalysis(projectId: string, input: CreateSavedAnalysisInput): Promise; /** A project's saved analyses, newest first. */ listSavedAnalyses(projectId: string, opts?: MetadataListOptions): Promise; /** Delete one saved analysis; `false` when the id is unknown. */ deleteSavedAnalysis(projectId: string, id: string): Promise; /** Pin one panel and return the stored row. */ createPanelSpec(projectId: string, input: CreatePanelSpecInput): Promise; /** * A project's pinned panels, **oldest first** — the opposite order to the * other metadata listings, because these are grid positions rather than a * feed and newest-first would reshuffle the dashboard on every pin. */ listPanelSpecs(projectId: string, opts?: MetadataListOptions): Promise; /** * Replace one panel's spec, keeping its id, its place and its original * authorship; `null` when the id is unknown (or belongs to another project). */ updatePanelSpec(projectId: string, id: string, input: UpdatePanelSpecInput): Promise; /** Unpin one panel; `false` when the id is unknown. */ deletePanelSpec(projectId: string, id: string): Promise; /** Release underlying connections. */ close(): Promise; } //# sourceMappingURL=store.d.ts.map