Telemetry inside Sana: measure the product the way Tempo measures the process.
Tempo measures how we build. This proposal is the other half: Sana itself instrumented from the first screen, so what we ship gets measured with the same care as how we ship it. It's the layer that turns the loop's iteration from taste into evidence.
Where it sits in Tempo
Nightshift builds overnight and Pulse scores the pipeline. What neither can see today is what happens after a screen exists: where people click, what they ignore, which journeys stall. With telemetry in the product, the loop's discovery stage queries real usage before proposing what to improve, an iterating cycle can pull how reviewers actually moved through its proposed build, and at GA the revenue and retention measures on Pulse's outcome row light up. Without it, all of that stays opinion.
Why now, not later
Greenfield is the cheap moment
The frontend routes everything through shared UI primitives, so one instrumented layer captures nearly all of it. After GA it means touching every screen. Every screen shipped uninstrumented is retrofit debt.
The loop needs it as an input
When a cycle iterates on a UI or a flow, it should query where clicks go and where journeys stall, not guess. Heat maps and paths are overwhelming raw; rendered views make them readable for humans, and a query surface makes them usable by the loop.
Reviewer telemetry closes the iteration loop
Reviewers already click through proposed builds in preview environments. Instrument those the same way, and an iterating cycle can pull what the reviewer tried first, where they hesitated, what they never found.
It unlocks the outcome measures
Pulse reserves revenue, retention, ticket deflection, and customer signal as the primary arrow at GA. All four depend on product telemetry existing from day one.
The design, in five commitments
- One event vocabulary, versioned like the entity schema. Interaction (click, focus, submit, abandon), navigation (route enter and leave with timing), feature use, and journey markers. Generated types, the same discipline the entity events already use.
- PHI-safe at the schema, not by review. Events carry element ids, route names, field names, timings, and counts. Never values, never free text, never patient identifiers. Actors are pseudonymous per-tenant ids; heat-map coordinates are bucketed to a grid so density survives and identity doesn't. The repo's own guardrail-test pattern enforces it: a test fails if an event type grows a value-bearing field.
- A separate stream from the audit chain. Telemetry is high-volume, TTL-aged, aggregated. The audit chain is WORM and forever. Same append-row discipline, different table, different retention.
- Consumed two ways. Humans get rendered views: heat maps per screen, journey flows, funnel drop-offs. The loop gets a query surface, so discovery and iteration ask "what do users do on this screen" and get rows back. Both read the same stream.
- Discovery taps the existing products too. UserPilot data from the current products already lands in our analytics store; the discovery stage should query it when specifying what to build, so Sana learns from how ChiroHD and SKED are actually used, not just from support asks.
Sizing and sequence
The event vocabulary, the emit hook in the shared UI primitives, the ingest table. Small because the primitives already centralize the surface.
Journey markers, the aggregation job, the first heat-map and funnel views.
Reviewer-mode capture in preview environments; the query surface wired into the loop's iteration stage.
Placement: ahead of further screen buildout, for the retrofit reason above.
Open questions for the room
Retention windows per event class · whether tenant admins eventually see their own clinic's usage views (likely yes, later) · where aggregation runs (a scheduled job beside the existing verifier orchestration is the natural home).
← Back to the path · See where these measures land on Pulse →