fix(insights): propagate rrweb counters & resolve click targets #1

Open
root wants to merge 0 commits from fix/insights-rage-click-pipeline into main
Owner

Summary

Three coupled fixes that together stop frustrated sessions from being mislabelled as power_user_path and make click timelines actually diagnosable.

1) Counter propagation

compress.ts now returns rageClickCount / network5xxCount / network4xxCount and compress-sessions.ts writes them back to SessionMeta. Previously these stayed at 0 forever — PostHog recording metadata doesn't expose them and nothing updated the row after compress ran. Knock-on effect: tagger.ts rules like ux_friction (rageClickCount > 0) never fired.

2) Tag rule hardening

  • power_user_path v1 fallback now requires rageClickCount===0. Without this guard any auth user with 20+ clicks (rage clusters included) was labelled a power user. This is the direct cause of the example session (019e4eda-…) showing power_user_path despite 13 rage clusters.
  • New frustrated_session tag (rageClickCount >= 3, P2) for sustained friction beyond a single cluster.
  • compress-sessions.ts re-runs tagSession+scoreSession after writing fresh counters (using cached person+group for full enrichment), so the corrected tags land on the row in the same transaction.

3) Click target enrichment

describeTarget used to read tagName/attributes off MouseInteraction events — fields that don't exist on rrweb type=3 source=2. Every click rendered as [el]. Now compress builds a node map from FullSnapshot (type=2) and keeps it in sync with mutations (type=3 source=0), then resolves clicks via d.id. Output goes from click [el] to click [button:"VIN Sorgula"].

Test plan

  • pnpm --filter worker typecheck passes (verified locally)
  • Deploy worker; let next compress cycle run and pick a frustrated session (e.g. 019e4eda-4d25-787f-bd75-19142eafe21f)
  • Verify SessionMeta.rageClickCount > 0 after compress
  • Verify tags switch from [power_user_path] to [ux_friction, frustrated_session], severity → P2
  • Verify semantic timeline shows resolved click targets (no [el] for elements present in the snapshot)

Known limitation (not addressed here)

Tag step still runs before compress. If a session is discarded at tag-time due to score threshold, compress never runs → re-tag never happens. Sessions with rage clicks but <20 clicks can slip through. Tracked separately.

🤖 Generated with Claude Code

## Summary Three coupled fixes that together stop frustrated sessions from being mislabelled as `power_user_path` and make click timelines actually diagnosable. ### 1) Counter propagation `compress.ts` now returns `rageClickCount` / `network5xxCount` / `network4xxCount` and `compress-sessions.ts` writes them back to `SessionMeta`. Previously these stayed at `0` forever — PostHog recording metadata doesn't expose them and nothing updated the row after compress ran. Knock-on effect: `tagger.ts` rules like `ux_friction` (`rageClickCount > 0`) never fired. ### 2) Tag rule hardening - `power_user_path` v1 fallback now requires `rageClickCount===0`. Without this guard any auth user with 20+ clicks (rage clusters included) was labelled a power user. This is the direct cause of the example session (`019e4eda-…`) showing `power_user_path` despite 13 rage clusters. - New `frustrated_session` tag (`rageClickCount >= 3`, P2) for sustained friction beyond a single cluster. - `compress-sessions.ts` re-runs `tagSession`+`scoreSession` after writing fresh counters (using cached person+group for full enrichment), so the corrected tags land on the row in the same transaction. ### 3) Click target enrichment `describeTarget` used to read `tagName`/`attributes` off MouseInteraction events — fields that don't exist on rrweb `type=3 source=2`. Every click rendered as `[el]`. Now compress builds a node map from FullSnapshot (`type=2`) and keeps it in sync with mutations (`type=3 source=0`), then resolves clicks via `d.id`. Output goes from `click [el]` to `click [button:"VIN Sorgula"]`. ## Test plan - [ ] `pnpm --filter worker typecheck` passes (verified locally) - [ ] Deploy worker; let next compress cycle run and pick a frustrated session (e.g. `019e4eda-4d25-787f-bd75-19142eafe21f`) - [ ] Verify `SessionMeta.rageClickCount > 0` after compress - [ ] Verify tags switch from `[power_user_path]` to `[ux_friction, frustrated_session]`, severity → P2 - [ ] Verify semantic timeline shows resolved click targets (no `[el]` for elements present in the snapshot) ## Known limitation (not addressed here) Tag step still runs before compress. If a session is `discarded` at tag-time due to score threshold, compress never runs → re-tag never happens. Sessions with rage clicks but <20 clicks can slip through. Tracked separately. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
root added 1 commit 2026-05-22 21:50:12 +03:00
Three coupled fixes that together stop frustrated sessions from being
mislabelled as `power_user_path` and make click timelines actually
diagnosable.

1) Counter propagation (compress.ts, compress-sessions.ts):
   compress now returns rageClickCount / network5xxCount / network4xxCount
   and writes them back to SessionMeta. Previously these stayed at 0
   forever because PostHog recording metadata doesn't expose them and
   nothing updated the row after compress ran.

2) Tag rule hardening (tagger.ts, compress-sessions.ts):
   - power_user_path v1 fallback now requires rageClickCount===0; without
     this guard any auth user with 20+ clicks (rage clusters included)
     was labelled a power user.
   - New frustrated_session tag (rageClickCount>=3, P2) for sustained
     friction beyond a single cluster.
   - compress-sessions re-runs tagSession+scoreSession after writing the
     fresh counters, so the corrected tags land on the row.

3) Click target enrichment (compress.ts):
   describeTarget used to read tagName/attributes off MouseInteraction
   events — fields that don't exist on rrweb type=3 source=2 — so every
   click rendered as `[el]`. Now compress builds a node map from
   FullSnapshot (type=2) and keeps it in sync with mutations
   (type=3 source=0), then resolves clicks via `d.id`. Clicks now show
   real tag + visible text / aria-label / name / data-testid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This branch is already included in the target branch. There is nothing to merge.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/insights-rage-click-pipeline:fix/insights-rage-click-pipeline
git checkout fix/insights-rage-click-pipeline
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: root/sp#1