feat(inbox): add Dismissed tab with restore#2704
Conversation
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
|
Reviews (2): Last reviewed commit: "feat(inbox): add read-only detail view f..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e17a9f273d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
6c67481 to
79333c6
Compare
Adds a fourth inbox tab listing dismissed (suppressed) reports, newest first, with a per-card Restore action that reopens a report back into the pipeline (reuses the state action's 'potential' transition). - Dedicated useInboxDismissedReports query (status=suppressed); the main pipeline query excludes suppressed, so the tab fetches them separately. - useInboxRestoreReport invalidates reportKeys.all so a restored report moves out of Dismissed and back into the pipeline tabs. - Cards are read-only (no detail link): the report detail endpoint currently 404s for suppressed reports. Clicking-through depends on PostHog/posthog#64019 shipping; until then Restore is the only action. - No count badge on the tab (an open-ended archive total adds no signal), so no extra always-on query in the inbox shell. - Reviewer-scope selector hidden on the tab (the dismissed list isn't scoped). Updates the feature CLAUDE.md IA map to four tabs.
Dismissed cards now link into a detail view (summary + evidence) with a single Restore action; no triage affordances since the report is out of the pipeline. - DismissedReportDetail reuses InboxReportDetailGate + InboxDetailFrame. - InboxDetailFrame gains a showDismiss opt-out (a dismissed report shouldn't show 'Dismiss'); the gate skips OPENED/CLOSED engagement tracking for the dismissed tab (its rank would be measured against the wrong list). - Routes restructured: dismissed.tsx is now an Outlet layout, with dismissed.index (list) and dismissed.$reportId (detail). - The route loader resolves the cached report from the dismissed list cache, so navigation renders instantly; the detail's own fetch depends on the backend serving suppressed reports on retrieve/signals (PostHog/posthog#64019).
- DismissedReportDetail gains a copy-link button beside Restore (same deep-link util the other detail screens use), so a dismissed report can be shared. - useOpenInboxReport now routes a suppressed report to the Dismissed detail (was falling through to the Reports detail, which showed a stray Dismiss action on an already-dismissed report). Adds navigateToInboxDismissedDetail.
79333c6 to
4de74ab
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95690b4824
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Surface why each report was suppressed: render the dismissal reason (with the note as a tooltip) as a chip in the DismissedReportCard meta row. The reason and note are denormalised onto the list SignalReport by the backend serializer, mirroring how priority/actionability/already_addressed are lifted from their artefacts, so cards avoid an N+1 per-card fetch. Reason codes are client-owned, so an unknown value falls back to the raw code via dismissalReasonLabel rather than being dropped.
|
Added: the dismissed report cards now show why each report was suppressed — the dismissal reason as a chip (with the note as a tooltip). The reason/note are denormalised onto the list |
A /code/inbox/dismissed/$reportId URL can go stale (history, bookmark, or copied deep link) after the report was restored and moved on. The detail view rendered Restore unconditionally, and READY/RESOLVED -> POTENTIAL is an allowed server-side transition, so restoring re-queued an active report. Redirect non-suppressed reports to their current home (pulls when a PR exists, else reports), mirroring useOpenInboxReport's routing, instead of offering Restore.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c06b7d57e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Follow-ups on the dismissed-detail guard: - Don't redirect on a stale cache snapshot. After a dismissal the suppress mutation invalidates but doesn't rewrite reportKeys.detail, so the gate can briefly surface the pre-dismissal (e.g. ready) record via initialData. The redirect now waits for the detail query to settle (!isFetching) — which the query forces fresh on mount via initialDataUpdatedAt: 0 — so a just-dismissed report opened from the Dismissed list no longer bounces straight out. - Route non-suppressed reports by the same membership predicates the tabs use: Pulls when a PR exists, Runs for in-flight runs (potential/candidate/ in_progress/pending_input), else Reports — instead of sending every non-PR report to Reports, which left run-state reports on the wrong tab.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f391b98053
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…direct isReportTabReport excludes failed (failed runs live only in the Runs tab), so the previous isAgentRunReport check sent a restored-then-failed report to /reports, which doesn't list it. Route by membership precedence instead: PR -> pulls, isReportTabReport -> reports, else -> runs.
#54: a suppressed report reached via a stale /pulls, /reports, or /runs URL rendered that tab's full triage actions (dismiss, discuss, create PR) on an out-of-pipeline report, now that the backend serves suppressed reports on retrieve. Centralize the status<->route guard in InboxReportDetailGate: redirect across the dismissed<->pipeline boundary in both directions (suppressed off the triage routes -> dismissed; non-suppressed off /dismissed -> its current home), gated on a settled fetch. This subsumes the bespoke guard that lived in DismissedReportDetail, so that component is back to just rendering. #59: harden useInboxRestoreReport to re-read the report and no-op (with a toast + list refresh) if it's no longer suppressed, covering the card-level Restore on a row left stale by a change in another session — not just the detail path.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b870732fd7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const onDismissedRoute = backTo === "/code/inbox/dismissed"; | ||
| const isSuppressed = resolvedReport?.status === "suppressed"; | ||
| let redirectTo: InboxDetailRoute | null = null; | ||
| if (resolvedReport && !isFetching) { |
There was a problem hiding this comment.
Hide stale detail actions during status refetch
When a report is already cached as a normal inbox report but has been suppressed in another session, useInboxReportById returns that cached row while the forced fresh fetch is still pending. This branch only postpones the redirect while isFetching, but the component then falls through and renders children(resolvedReport), so /reports, /pulls, or /runs can briefly show full triage controls (including Create PR/Discuss) for a now-suppressed report until the fetch settles. Consider rendering the spinner or disabling actions while the route-boundary status is being confirmed.
Useful? React with 👍 / 👎.
Adds a Dismissed tab to the inbox: lists dismissed (suppressed) reports, lets you re-read one, restore it, or grab a shareable link.
Backend dependency (PostHog/posthog#64019) is merged + deployed, and the whole feature has been verified end-to-end against the live app (including a real restore round-trip — status confirmed flipping
suppressed → potentialserver-side).What's in it
Tab + list
useInboxDismissedReportsfetchesstatus=suppressed(the main pipeline query excludes suppressed reports), no polling — relies onreportKeys.allinvalidation, which dismiss/restore both trigger.reportMembership.ts(isDismissedReport), unit-tested.Restore
useInboxRestoreReportreuses thestateaction'spotential("reopen") transition — the only reopen path the backend exposes. InvalidatesreportKeys.allso the report leaves Dismissed.potential, which is a queued run status, so a restored report lands in the Runs tab (Queued), not Reports — it re-enters the pipeline rather than popping back to its prior state (that prior status isn't persisted, and thestateendpoint only acceptspotential/suppressed). It cycles back to Reports on its own once it re-reachesready. It stays re-dismissible throughout (via the run → report detail, or from Reports once ready).Read-only detail
DismissedReportDetailreusesInboxReportDetailGate+InboxDetailFrame— summary + evidence + Restore + copy-link. No triage affordances (dismiss / discuss / create PR / reviewers): the report is out of the pipeline until restored.InboxDetailFramegains ashowDismissopt-out; the gate skips OPENED/CLOSED engagement tracking for the dismissed tab (not a trackedInboxDetailTab— its rank would be measured against the wrong list).dismissed.tsxis anOutletlayout, withdismissed.index(list) anddismissed.$reportId(detail). The loader resolves the cached report from the dismissed list cache, so navigation renders instantly.Shareable link
copyInboxReportLinkdeep-link util the other detail screens use).useOpenInboxReportnow routes a suppressed report to the Dismissed detail (it previously had no suppressed branch and fell through to the Reports detail, which showed a stray Dismiss action on an already-dismissed report). AddsnavigateToInboxDismissedDetail.Verification
@posthog/core+@posthog/uitypecheck ✅ · core tests 1550 passed ✅ · biome lint ✅ (pre-commit runs biome + full typecheck)019eced2…wentsuppressed → potential.Reviewer notes
suppressed → potentialrestore → Runs behaviour above is intentional, not a bug — it's the only reopen transition the backend supports. Flagged here so it doesn't read as one.