Skip to content

fix(replay-vision): hover a scan result to read its reasoning - #89485

Merged
trunk-io[bot] merged 3 commits into
masterfrom
posthog/vision-result-hover-reasoning
Sep 11, 2026
Merged

trunk-io[bot] merged 3 commits into
masterfrom
posthog/vision-result-hover-reasoning

Conversation

@fivestarspicy

Copy link
Copy Markdown
Contributor

Problem

Someone scanning a list of Replay vision observations hovers a row's Result to find out why the scanner said "Yes" or gave a 3/5. The hover showed the scanner's prompt instead. That prompt is the same on every row, so the hover repeated the scanner config and never explained the individual result — the reasoning was only reachable by opening the observation.

Changes

  • Hovering a result in the observations, calibration, and search lists now shows that observation's reasoning, with citation markers rendered as readable (mm:ss) timestamps.
  • A result with no reasoning gets no hover, rather than falling back to the prompt.
  • Detail and dock views are unchanged — they print the prompt inline and already show the reasoning in full underneath.

How did you test this code?

Not verified in a running app: this environment had no frontend dependencies installed, so no typecheck, Jest run, or screenshot. The change swaps the source of an existing Tooltip title within ObservationPrimaryOutput; both values are string | null. No tests were added — the behavior is a tooltip's text source, and a hover-render test would cost more than the regression it guards.

Automatic notifications

  • Publish to changelog?

Docs update

None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Reported from Slack as a UI bug: hovering the Result surfaced prompt text where reasoning was expected. Written by the PostHog Slack app (Claude Code). The reported screen was identified by tracing every "Result" column in the repo to the one whose hover renders a prompt — worth a reviewer's sanity check that Replay vision's observation lists are the surface in question, since the report did not name the product.

The tooltip is gated on the same showPrompt flag that already distinguishes compact list rendering from the detail views, so the two callers that print the prompt inline keep their current (empty) hover.


Created with PostHog from a Slack thread

@fivestarspicy fivestarspicy self-assigned this Aug 26, 2026
@trunk-io

trunk-io Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

😎 Merged successfully - details.

@github-actions

github-actions Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane (fe:product:replay_vision)

This PR is assigned to the non-backend lane (fe:product:replay_vision). It does not run backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 3 functions above the limit (max 54)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
ObservationPrimaryOutput products/replay_vision/frontend/components/ObservationCard.tsx:114 54 10
ObservationDockCard products/replay_vision/frontend/components/ObservationCard.tsx:403 20 10
ObservationStatusTag products/replay_vision/frontend/components/ObservationCard.tsx:27 12 10
✅ Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 68.44 MiB · no change

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.54 MiB · 22 files no change ████████░░ 83.5% of 1.84 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.51 MiB · 610 files no change █████████░ 87.0% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.28 MiB · 2,690 files no change █████████░ 87.1% of 9.51 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
854 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
291.3 KiB ../node_modules/.pnpm/posthog-js@1.429.2_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
103.5 KiB src/lib/api.ts
80.0 KiB src/products.tsx
68.9 KiB src/lib/lemon-ui/icons/icons.tsx
62.7 KiB src/lib/utils/eventUsageLogic.ts
38.8 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
33.9 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
33.2 KiB src/queries/schema/schema-general.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
291.3 KiB ../node_modules/.pnpm/posthog-js@1.429.2_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
261.1 KiB src/taxonomy/core-filter-definitions-by-group.json
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
103.5 KiB src/lib/api.ts
96.4 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
80.0 KiB src/products.tsx

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.31 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.31 MiB · 18 files no change ████░░░░░░ 40.3% of 5.72 MiB
Deferred (lazy) 2.09 MiB · 45 files no change n/a — loads on demand
Loader dist/toolbar.js 1.1 KiB no change █░░░░░░░░░ 5.8% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
763.0 KiB dist/toolbar/toolbar-app-2PQMAZRX.css
620.3 KiB dist/toolbar/chunk-chunk-ANDAMTKY.js
484.8 KiB dist/toolbar/chunk-chunk-OP5XRFCY.js
136.2 KiB dist/toolbar/chunk-chunk-4XNAERUF.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
72.2 KiB dist/toolbar/toolbar-app-VNKCNDJE.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-YV53UXZJ.js
21.0 KiB dist/toolbar/chunk-chunk-O3PYXV3V.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +766 B (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1468.58 MiB · 🔺 +766 B (+0.0%)

✅ Playwright — all passed

All tests passed.

View test results →

@trunk-io

trunk-io Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@scheduled-actions-posthog

Copy link
Copy Markdown
Contributor

This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, please remove the stale label – otherwise this will be closed in another week. If you want to permanently keep it open, use the waiting label.

@scheduled-actions-posthog

Copy link
Copy Markdown
Contributor

This PR was closed due to lack of activity. Feel free to reopen if it's still relevant.

@fasyy612 fasyy612 reopened this Sep 10, 2026
@fasyy612 fasyy612 removed the stale label Sep 10, 2026
@fivestarspicy
fivestarspicy marked this pull request as ready for review September 10, 2026 17:24
@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team, TueHaulund, arnohillen and ksvat and removed request for a team September 10, 2026 17:24
fivestarspicy and others added 2 commits September 11, 2026 17:16
The compact result rendering used in the observations, calibration, and search lists carried the scanner prompt in its hover. The prompt is identical on every row, so the hover repeated what the scanner config already says and gave no reason for that particular verdict or score.

The hover now carries the observation's reasoning, with citation markers rendered as readable timestamps. Detail views are unchanged: they print the prompt inline and already show the reasoning in full.

Generated-By: PostHog Desktop
Task-Id: f0468007-9d7b-40ab-b188-1795da2cf080
@fasyy612
fasyy612 force-pushed the posthog/vision-result-hover-reasoning branch from b1bf669 to fc4ebb5 Compare September 11, 2026 16:43
@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit fbadad1 · box box-81b6b76e0e29 · ready in 1212s (push → usable) · build log · rebuilds on every push, torn down on close

@fasyy612

Copy link
Copy Markdown
Contributor

/trunk merge

@trunk-io
trunk-io Bot merged commit 7c6df4a into master Sep 11, 2026
201 checks passed
@trunk-io
trunk-io Bot deleted the posthog/vision-result-hover-reasoning branch September 11, 2026 17:52
@deployment-status-posthog

deployment-status-posthog Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-09-11 18:31 UTC Run
prod-us ✅ Deployed 2026-09-11 18:45 UTC Run
prod-eu ✅ Deployed 2026-09-11 18:49 UTC Run

This branch was successfully deployed

1 active deployment
preview-pr-89485 — fbadad13 Deployed Sep 11, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants