Skip to content

feat(platform): governance feedback analytics page#1662

Merged
larryro merged 7 commits into
mainfrom
feat/governance-feedback-page
May 4, 2026
Merged

feat(platform): governance feedback analytics page#1662
larryro merged 7 commits into
mainfrom
feat/governance-feedback-page

Conversation

@larryro
Copy link
Copy Markdown
Collaborator

@larryro larryro commented May 4, 2026

Summary

  • New Settings → Governance → Feedback admin page surfacing chat thumbs and arena verdicts, with first-class agent / model / provider attribution.
  • Hardens submitFeedback / deleteFeedback with thread↔org checks and reads attribution from messageMetadata server-side instead of trusting the client.
  • Schema additions: messageFeedback.{agentSlug,model,provider} + by_org_createdAt index; messageMetadata.agentSlug (additive only).
  • New aggregations: top agents, top models, and per-pair model matchups (canonical lexicographic orientation, decisive / tie / both-bad triple), with a pure reducer covered by a 12-case unit suite.
  • Recent feedback uses paginationOptsValidator + DataTable with expandable rows; kind / comments-only filters are scoped to the section to match their effect, period stays global.
  • i18n: 70+ analytics.feedback.* keys + governance.groups.feedback added to en / de / fr (single-brace placeholders, parity).

Pre-PR checklist

  • Translation parity en/de/fr maintained on every commit.
  • Ran bun run check — please run before merge; not executed in this session.
  • Updated services/platform/messages/{en,de,fr}.json.
  • Updated docs/{,de/,fr/}not yet; admin governance docs still describe pre-feedback state. Recommend follow-up doc PR or extending this one before merge.
  • Ran bun run --filter @tale/docs lint — N/A pending docs update.
  • README* updates — N/A (no top-level surface change).

Test plan

  • Visit /dashboard/<org>/settings/governance/feedback as an org admin; verify period, kind, comments-only, agent, model, provider URL state round-trips.
  • Submit thumbs up/down on a chat message; confirm the row shows up in Recent feedback and increments the sentiment hero / Top Assistants / Top Models.
  • Submit an arena verdict (A better / B better / tie / both bad); confirm it lands in Top Model Matchups under the canonical pair regardless of which slot got which model.
  • Try submitFeedback with a threadId from another org — should be rejected.
  • Self-pair / one-side-missing arena rows should not appear in matchups.
  • Empty states: brand-new org (org-empty), org with feedback but none in selected period (period-empty), filters that match nothing (filter-empty).
  • Chat per-message metadata (cost / tokens / model popover) still loads — regression guard for the messageMetadataValidator fix in 564958d.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a Feedback analytics dashboard to governance settings, displaying sentiment metrics, arena verdict summaries, and rankings of top agents, models, and model matchups by user satisfaction
    • Added filtering by time period (1, 7, 30, 90 days, or all), feedback type (message feedback or arena battles), and optional comment-only view
    • Added recent feedback listings with agent and model attribution, expandable details, and pagination support

larryro added 7 commits May 4, 2026 14:38
…tion

Surface user-submitted feedback (chat thumbs up/down + arena verdicts) on
a new admin page under Settings → Governance, with first-class agent and
model breakdowns.

Backend:
- messageFeedback gains agentSlug/model/provider (optional) + a
  by_org_createdAt index for window-bounded scans
- messageMetadata gains agentSlug; saveMessageMetadata + onAgentComplete
  thread it through so feedback rows can attribute by agent
- submitFeedback now (a) validates threadId↔organizationId to close a
  cross-org write gap and (b) reads attribution from messageMetadata
  rather than trusting client-supplied values; deleteFeedback gets a
  matching defense-in-depth check
- feedback/stats.ts extracts a pure computeFeedbackStats reducer
  (byRating / byVerdict / topAgents / topModels) — no server-side
  sentimentPct, client derives ratios
- getFeedbackStats: admin guard + period filter (1/7/30/90/all-time,
  day-aligned UTC) + agent/model/provider filters + hasAnyFeedback flag
- listRecentFeedback: paginationOptsValidator + by_org_createdAt desc;
  projects user names, thread-deleted state, comment truncated at 4 KB

Frontend:
- New /settings/governance/feedback route with zod validateSearch URL
  state (period / kind / comments / agent / model / provider), mirroring
  the automations/metrics pattern
- feedback-metrics-page orchestrator with loading / org-empty /
  period-empty / filter-empty / capped states
- Hero sentiment cell + 2-color stacked bar (CSS only); arena summary
  reuses chat.arena.* i18n keys
- Top Assistants + Top Models feedback tables (clickable rows set URL
  filters); filter chips strip
- Recent feedback uses DataTable + enableExpanding to show full comment
  and arena pairing inline; renders "—" when source thread is deleted

i18n: 70+ analytics.feedback.* keys + governance.groups.feedback added
to en / de / fr (parity test passes).

Tests: 12-case unit suite for the pure reducer.
Today's governance feedback commit (14bbf13) added agentSlug to the
messageMetadata schema but not to messageMetadataValidator, so the
getMessageMetadata query rejected every row written since with
ReturnsValidationError, breaking the chat UI's per-message metadata
fetch (cost, tokens, model).
The Open-thread link in the governance feedback page is only navigable
when the admin happens to be the thread owner — `canAccessThread` blocks
all non-owner reads, so for every other user's feedback the link lands
on a "thread not found" page. Remove the column until a proper
governance-reviewer role with audit logging lands.

Side benefit: drops the per-page N+1 `threadMetadata` lookup from
`listRecentFeedback` and the now-unused `feedback.recent.openThread` /
`columns.thread` i18n keys (en/de/fr).
i18next is configured with `interpolation.prefix:'{'`/`suffix:'}'`
(see lib/i18n/i18n.ts), so `{{value}}` doesn't interpolate — it
renders verbatim. The new feedback page leaked five keys with
double-brace placeholders, causing literal `{{helpful}} / {{total}}`
under the sentiment hero and `Assistant: {{value}}` in filter chips.
Fix in en/de/fr.
Aggregating "A is better" / "B is better" across rows mixes different
model pairs (A/B is a user-picked position, not a random assignment),
so the count carries no actionable signal. Replace the four-cell arena
summary with a position-agnostic triple — Decisive / Tie / Both bad —
and surface a new "Top Model Matchups" table that buckets verdicts by
canonical (lexicographic) model pair, projecting wins onto a stable
left/right orientation so (X,Y) and (Y,X) merge.

The reducer skips matchup aggregation on self-pairs and rows missing
either model name. New tests cover orientation flipping and the
self-pair / missing-side guards.
The matchup, top-models, and recent-feedback tables truncated model
strings (e.g. `openrouter:deepseek/deepseek-v4-flash-...`) to a fixed
max-width with ellipsis, which hides the actual identity that admins
need to read. Replace `truncate`/`max-w-*` on every model and matchup
cell with `break-all` so long IDs wrap to multiple lines instead.
Comment previews keep their truncation since the expanded row shows
the full text.
The page-level toolbar mixed three filters of different reach: period
flowed through every query, but kind ("All types"/"Message thumbs"/
"Arena verdicts") and comments-only fed only `listRecentFeedback`.
Placing them at the top suggested they affected the sentiment cards,
arena summary, and top tables too. Move both controls into the Recent
feedback section header so the affordance matches the effect; only
period stays in the global toolbar.
@larryro larryro merged commit 7d92f85 into main May 4, 2026
16 of 17 checks passed
@larryro larryro deleted the feat/governance-feedback-page branch May 4, 2026 08:02
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive feedback analytics dashboard for the platform. It adds new React components for displaying feedback metrics, including a metrics page with filtering and pagination, summary cards, arena verdict summaries, and data tables (recent feedback, top agents, top models, top matchups). Backend support includes new Convex queries for feedback statistics and recent feedback listings, a pure stats computation function, and mutations updated to capture server-side message attribution. Schema changes add optional agent slug, model, and provider fields to feedback records. The implementation also introduces a new route under governance settings and includes i18n translations in English, French, and German.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main change: adding a governance feedback analytics page.
Description check ✅ Passed The description covers the key changes with a summary section and detailed implementation notes; however, the pre-merge checklist is incomplete with unchecked items for running bun run check, updating docs, and running docs linter.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/governance-feedback-page

Review rate limit: 4/5 reviews remaining, refill in 12 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

1 participant