Skip to content

feat(signals): Record dismissal feedback as report artefact#57768

Merged
Twixes merged 9 commits into
masterfrom
posthog-code/dismissal-artefact-on-suppress
May 10, 2026
Merged

feat(signals): Record dismissal feedback as report artefact#57768
Twixes merged 9 commits into
masterfrom
posthog-code/dismissal-artefact-on-suppress

Conversation

@Twixes
Copy link
Copy Markdown
Member

@Twixes Twixes commented May 6, 2026

Problem

PostHog Code will surface a "Dismiss" dialog on the inbox where a reviewer can mark a report as not worth acting on, as of PostHog/code#2053. We need to record "why" alongside the status change so we can:

  • distinguish "already fixed" from "wontfix"
  • stack multiple dismissals over time when a report is unsnoozed and later re-dismissed for a different reason

The existing state action only flips a status flag and offers no place to attach this metadata.

Changes

Adding a new dismissal value on SignalReportArtefact.ArtefactType.

POST /api/projects/:team_id/signals/reports/:id/state/ now accepts two optional body fields:

  • dismissal_reason- Arbitrary string code. The set of valid codes is owned by PostHog Code, so we can iterate there without a backend change.
  • dismissal_note - Free-form text, capped at 4000 characters.

When either is provided and the target state is suppressed or potential, the action creates a dismissal artefact alongside the status change capturing reason, note, and the dismissing user's ID.

Important note: Reingestion is now available to all users. We need it e.g. to let people re-run failed research, which we've gotten reports about in Discord.

Why an artefact rather than a column on the report

The existing SUPPRESSED status is a single flag. We need history (the same report can be dismissed multiple times for different reasons over its lifetime), and a typed artefact matches the existing pattern for everything else attached to a report.

How did you test this code?

TestSignalReportSuppressionAPI

Publish to changelog?

no

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Migration SQL Changes

Hey 👋, we've detected some migrations on this PR. Here's the SQL output for each migration, make sure they make sense:

products/signals/backend/migrations/0018_alter_signalreportartefact_type.py

BEGIN;
--
-- Alter field type on signalreportartefact
--
-- (no-op)
COMMIT;

Last updated: 2026-05-10 15:35 UTC (5a4bed2)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🔍 Migration Risk Analysis

We've analyzed your migrations for potential risks.

Summary: 0 Safe | 1 Needs Review | 0 Blocked

⚠️ Needs Review

May have performance impact

signals.0018_alter_signalreportartefact_type
  └─ #1 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: signalreportartefact, field: type, field_type: CharField

Last updated: 2026-05-10 15:36 UTC (5a4bed2)

@Twixes Twixes changed the title feat(signals): record dismissal feedback as a report artefact feat(signals): Record dismissal feedback as report artefact May 7, 2026
@Twixes Twixes marked this pull request as ready for review May 7, 2026 11:03
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 7, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
products/signals/backend/views.py:877
Inconsistent nullability between `note` and `reason` in the stored artefact. `reason` is stored as `None` when absent, but `note` is stored as `""` (empty string) when absent due to the `or ""` fallback. A downstream consumer must handle `null` for `reason` but would receive `""` for `note`, making the contract asymmetric. Using `None` for both keeps the JSON schema consistent.

```suggestion
                "note": dismissal_note,
```

### Issue 2 of 2
products/signals/backend/test/test_signal_report_api.py:554-663
**Prefer parametrised tests** — the team's convention is to use parametrised tests where the same assertion logic repeats across multiple inputs. Several cases here (suppress-with-reason-only, suppress-with-note-only, snooze-with-both, oversized-note, etc.) share the same structure: build a request body, POST, assert status, inspect the artefact. Collapsing the happy-path variants into a single `@pytest.mark.parametrize` call and the error cases into another would reduce duplication without losing coverage.

Reviews (1): Last reviewed commit: "Simplify" | Re-trigger Greptile

Comment thread products/signals/backend/views.py Outdated
Comment thread products/signals/backend/test/test_signal_report_api.py
@Twixes Twixes force-pushed the posthog-code/dismissal-artefact-on-suppress branch from cf3b5f2 to 05740d9 Compare May 7, 2026 11:07
Comment thread products/signals/backend/views.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

🎭 Playwright didn't run on this PR — your changes touch code that could affect E2E behavior, but Playwright is opt-in via label now to keep CI cost down.

Add the run-playwright label if you want an E2E sweep before merging — CI will pick it up automatically.

Most PRs don't need this. Real regressions still get caught on master and fix-forward.

@Twixes Twixes requested a review from a team May 7, 2026 11:14
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Size Change: -17.2 kB (-0.01%)

Total Size: 116 MB

📦 View Changed
Filename Size Change
frontend/dist/CalendarHeatMap 5.04 kB -3.97 kB (-44.05%) 🎉
frontend/dist/EndpointsScene 21.6 kB -2.14 kB (-9.02%)
frontend/dist/TransformationsScene 2.16 kB -4.24 kB (-66.24%) 🏆
frontend/dist/WorkflowScene 109 kB -6.81 kB (-5.86%)
ℹ️ View Unchanged
Filename Size Change
frontend/dist/368Hedgehogs 5.47 kB 0 B
frontend/dist/abap 14.2 kB 0 B
frontend/dist/AccountConnected 2.99 kB 0 B
frontend/dist/Action 24 kB 0 B
frontend/dist/Actions 1.26 kB +63 B (+5.25%) 🔍
frontend/dist/AdvancedActivityLogsScene 39.9 kB 0 B
frontend/dist/AgenticAuthorize 5.7 kB 0 B
frontend/dist/apex 3.99 kB 0 B
frontend/dist/ApprovalDetail 16.5 kB 0 B
frontend/dist/architecture-YZFGNWBL 474 B 0 B
frontend/dist/architectureDiagram-Q4EWVU46 151 kB 0 B
frontend/dist/array.full.es5.js 345 kB 0 B
frontend/dist/array.full.js 424 kB 0 B
frontend/dist/array.js 189 kB 0 B
frontend/dist/AsyncMigrations 13.4 kB 0 B
frontend/dist/AuthenticatedShell 173 kB 0 B
frontend/dist/AuthorizationStatus 969 B 0 B
frontend/dist/azcli 885 B 0 B
frontend/dist/bat 1.88 kB 0 B
frontend/dist/BatchExportScene 60.7 kB 0 B
frontend/dist/bicep 2.59 kB 0 B
frontend/dist/Billing 731 B 0 B
frontend/dist/BillingSection 21 kB 0 B
frontend/dist/blockDiagram-DXYQGD6D 71.9 kB 0 B
frontend/dist/BoxPlot 5.29 kB +35 B (+0.67%)
frontend/dist/browserAll-0QZMN1W2 37.4 kB 0 B
frontend/dist/ButtonPrimitives 762 B -34 B (-4.27%)
frontend/dist/c4Diagram-AHTNJAMY 70.9 kB 0 B
frontend/dist/cameligo 2.23 kB 0 B
frontend/dist/changeRequestsLogic 782 B 0 B
frontend/dist/classDiagram-6PBFFD2Q 1.32 kB 0 B
frontend/dist/classDiagram-v2-HSJHXN6E 1.32 kB 0 B
frontend/dist/CLIAuthorize 11.6 kB 0 B
frontend/dist/CLILive 4.26 kB 0 B
frontend/dist/clojure 9.68 kB 0 B
frontend/dist/CodeEditorInline 696 B -34 B (-4.66%)
frontend/dist/coffee 3.63 kB 0 B
frontend/dist/Cohort 25 kB 0 B
frontend/dist/CohortCalculationHistory 6.47 kB 0 B
frontend/dist/Cohorts 9.64 kB 0 B
frontend/dist/ConfirmOrganization 4.76 kB 0 B
frontend/dist/conversations.js 67.3 kB 0 B
frontend/dist/cose-bilkent-S5V4N54A 82.8 kB 0 B
frontend/dist/Coupons 968 B 0 B
frontend/dist/cpp 5.33 kB 0 B
frontend/dist/Create 898 B 0 B
frontend/dist/crisp-chat-integration.js 1.97 kB 0 B
frontend/dist/csharp 4.56 kB 0 B
frontend/dist/csp 1.45 kB 0 B
frontend/dist/css 4.54 kB 0 B
frontend/dist/cssMode 4.2 kB 0 B
frontend/dist/CustomCssScene 3.81 kB 0 B
frontend/dist/CustomerAnalyticsConfigurationScene 2.27 kB 0 B
frontend/dist/CustomerAnalyticsScene 28.1 kB 0 B
frontend/dist/CustomerJourneyBuilderScene 2.08 kB +35 B (+1.71%)
frontend/dist/CustomerJourneyTemplatesScene 7.72 kB 0 B
frontend/dist/customizations.full.js 18 kB 0 B
frontend/dist/CyclotronJobInputAssignee 1.57 kB +35 B (+2.28%)
frontend/dist/CyclotronJobInputBusinessHours 2.96 kB +35 B (+1.2%)
frontend/dist/CyclotronJobInputTicketTags 954 B +34 B (+3.7%)
frontend/dist/cypher 3.42 kB 0 B
frontend/dist/dagre-KV5264BT 11.8 kB 0 B
frontend/dist/dart 4.29 kB 0 B
frontend/dist/Dashboard 1.38 kB 0 B
frontend/dist/Dashboards 21.8 kB 0 B
frontend/dist/DashboardTemplateCopyScene 5.95 kB 0 B
frontend/dist/DataManagementScene 884 B 0 B
frontend/dist/DataPipelinesNewScene 2.55 kB 0 B
frontend/dist/DataWarehouseScene 46.5 kB 0 B
frontend/dist/Deactivated 1.37 kB 0 B
frontend/dist/dead-clicks-autocapture.js 13.2 kB 0 B
frontend/dist/DeadLetterQueue 5.63 kB 0 B
frontend/dist/DebugScene 20.2 kB 0 B
frontend/dist/decompressionWorker 2.85 kB 0 B
frontend/dist/decompressionWorker.js 2.85 kB 0 B
frontend/dist/DecompressionWorkerManager 329 B 0 B
frontend/dist/DefinitionEdit 8.82 kB 0 B
frontend/dist/DefinitionView 24.3 kB 0 B
frontend/dist/DestinationsScene 2.92 kB 0 B
frontend/dist/diagram-5BDNPKRD 3.67 kB 0 B
frontend/dist/diagram-G4DWMVQ6 11.9 kB 0 B
frontend/dist/diagram-MMDJMWI5 6.72 kB 0 B
frontend/dist/diagram-TYMM5635 5.09 kB 0 B
frontend/dist/dist 643 B 0 B
frontend/dist/dockerfile 1.91 kB 0 B
frontend/dist/EarlyAccessFeature 855 B 0 B
frontend/dist/EarlyAccessFeatures 3.09 kB +36 B (+1.18%)
frontend/dist/ecl 5.38 kB 0 B
frontend/dist/EditorScene 1.38 kB 0 B
frontend/dist/elixir 10.3 kB 0 B
frontend/dist/elk.bundled 1.44 MB 0 B
frontend/dist/EmailMFAVerify 3.26 kB 0 B
frontend/dist/EndpointScene 39.2 kB +37 B (+0.09%)
frontend/dist/erDiagram-SMLLAGMA 27.8 kB 0 B
frontend/dist/ErrorTrackingIssueFingerprintsScene 7.26 kB +41 B (+0.57%)
frontend/dist/ErrorTrackingIssueScene 100 kB 0 B
frontend/dist/ErrorTrackingScene 27.1 kB +75 B (+0.28%)
frontend/dist/EvaluationTemplates 779 B 0 B
frontend/dist/EventsScene 2.81 kB 0 B
frontend/dist/exception-autocapture.js 11.8 kB 0 B
frontend/dist/Experiment 210 kB 0 B
frontend/dist/Experiments 19.3 kB 0 B
frontend/dist/exporter 18.7 kB 0 B
frontend/dist/exporter.js 18.7 kB 0 B
frontend/dist/ExporterDashboardScene 1.78 kB 0 B
frontend/dist/ExporterHeatmapScene 19.5 kB 0 B
frontend/dist/ExporterInsightScene 2.88 kB 0 B
frontend/dist/ExporterNotebookScene 2.69 MB 0 B
frontend/dist/ExporterRecordingScene 995 B 0 B
frontend/dist/exporterSharedChunkAnchors 288 kB 0 B
frontend/dist/exporterSharedChunkAnchors.js 288 kB 0 B
frontend/dist/ExportsScene 4.23 kB 0 B
frontend/dist/FeatureFlag 131 kB 0 B
frontend/dist/FeatureFlags 844 B 0 B
frontend/dist/FeatureFlagTemplatesScene 7.28 kB +36 B (+0.5%)
frontend/dist/FlappyHog 6.02 kB +34 B (+0.57%)
frontend/dist/flow9 1.85 kB 0 B
frontend/dist/flowDiagram-DWJPFMVM 61.7 kB 0 B
frontend/dist/freemarker2 16.7 kB 0 B
frontend/dist/fsharp 3.02 kB 0 B
frontend/dist/ganttDiagram-T4ZO3ILL 50.8 kB 0 B
frontend/dist/gitGraph-7Q5UKJZL 462 B 0 B
frontend/dist/gitGraphDiagram-UUTBAWPF 30.3 kB 0 B
frontend/dist/go 2.69 kB 0 B
frontend/dist/graphql 2.3 kB 0 B
frontend/dist/Group 14.8 kB 0 B
frontend/dist/Groups 4.15 kB 0 B
frontend/dist/GroupsNew 7.58 kB 0 B
frontend/dist/handlebars 7.38 kB 0 B
frontend/dist/hcl 3.63 kB 0 B
frontend/dist/HealthCategoryDetailScene 7.48 kB 0 B
frontend/dist/HealthScene 10.8 kB 0 B
frontend/dist/HeatmapNewScene 4.86 kB 0 B
frontend/dist/HeatmapRecordingScene 4.25 kB 0 B
frontend/dist/HeatmapScene 6.87 kB 0 B
frontend/dist/HeatmapsScene 4.13 kB 0 B
frontend/dist/hls 394 kB 0 B
frontend/dist/HogFunctionScene 59.5 kB 0 B
frontend/dist/hogql_parser_wasm_browser 1.52 MB 0 B
frontend/dist/HogRepl 7.61 kB 0 B
frontend/dist/html 5.62 kB 0 B
frontend/dist/htmlMode 4.65 kB 0 B
frontend/dist/image-blob-reduce.esm 49.5 kB 0 B
frontend/dist/InboxScene 59.9 kB 0 B
frontend/dist/index 60.7 kB 0 B
frontend/dist/index.js 60.7 kB 0 B
frontend/dist/info-OMHHGYJF 445 B 0 B
frontend/dist/infoDiagram-42DDH7IO 1.38 kB 0 B
frontend/dist/ini 1.14 kB 0 B
frontend/dist/InsightQuickStart 5.67 kB 0 B
frontend/dist/InsightScene 28.8 kB 0 B
frontend/dist/IntegrationsRedirect 976 B 0 B
frontend/dist/intercom-integration.js 2.03 kB 0 B
frontend/dist/InviteSignup 15.2 kB 0 B
frontend/dist/ishikawaDiagram-UXIWVN3A 18 kB 0 B
frontend/dist/java 3.26 kB 0 B
frontend/dist/javascript 1.02 kB 0 B
frontend/dist/journeyDiagram-VCZTEJTY 24 kB 0 B
frontend/dist/jsonMode 13.9 kB 0 B
frontend/dist/julia 7.26 kB 0 B
frontend/dist/kanban-definition-6JOO6SKY 21.3 kB 0 B
frontend/dist/katex 266 kB 0 B
frontend/dist/kotlin 3.44 kB 0 B
frontend/dist/lazy 146 kB 0 B
frontend/dist/LegacyPluginScene 20.9 kB 0 B
frontend/dist/LegalDocumentNewScene 59.6 kB 0 B
frontend/dist/LegalDocumentsScene 5.17 kB 0 B
frontend/dist/LemonTextAreaMarkdown 706 B 0 B
frontend/dist/less 3.93 kB 0 B
frontend/dist/lexon 2.47 kB 0 B
frontend/dist/lib 2.25 kB 0 B
frontend/dist/Link 706 B 0 B
frontend/dist/LinkScene 25 kB 0 B
frontend/dist/LinksScene 4.44 kB +36 B (+0.82%)
frontend/dist/liquid 4.57 kB 0 B
frontend/dist/LiveDebugger 19.3 kB 0 B
frontend/dist/LiveEventsTable 5.47 kB 0 B
frontend/dist/LLMAnalyticsClusterScene 21.5 kB +40 B (+0.19%)
frontend/dist/LLMAnalyticsClustersScene 54.8 kB +38 B (+0.07%)
frontend/dist/LLMAnalyticsDatasetScene 19.9 kB +31 B (+0.16%)
frontend/dist/LLMAnalyticsDatasetsScene 3.49 kB 0 B
frontend/dist/LLMAnalyticsEvaluation 59.6 kB +38 B (+0.06%)
frontend/dist/LLMAnalyticsEvaluationsScene 28 kB -34 B (-0.12%)
frontend/dist/LLMAnalyticsPlaygroundScene 37.5 kB 0 B
frontend/dist/LLMAnalyticsScene 115 kB 0 B
frontend/dist/LLMAnalyticsSessionScene 13.6 kB +41 B (+0.3%)
frontend/dist/LLMAnalyticsTag 27.3 kB +36 B (+0.13%)
frontend/dist/LLMAnalyticsTagsScene 7.19 kB +36 B (+0.5%)
frontend/dist/LLMAnalyticsTraceScene 130 kB +39 B (+0.03%)
frontend/dist/LLMAnalyticsUsers 764 B +34 B (+4.66%) 🔍
frontend/dist/LLMASessionFeedbackDisplay 5.04 kB 0 B
frontend/dist/LLMPromptScene 17.8 kB +38 B (+0.21%)
frontend/dist/LLMPromptsScene 4.72 kB +36 B (+0.77%)
frontend/dist/LLMSkillScene 793 B 0 B
frontend/dist/LLMSkillsScene 844 B 0 B
frontend/dist/Login 8.86 kB 0 B
frontend/dist/Login2FA 4.49 kB 0 B
frontend/dist/logs.js 38.5 kB 0 B
frontend/dist/LogsAlertDetailScene 17.2 kB 0 B
frontend/dist/LogsSamplingDetailScene 4.44 kB 0 B
frontend/dist/LogsSamplingNewScene 1.97 kB 0 B
frontend/dist/LogsScene 18.1 kB 0 B
frontend/dist/lua 2.16 kB 0 B
frontend/dist/m3 2.85 kB 0 B
frontend/dist/main 819 kB 0 B
frontend/dist/ManagedMigration 14.4 kB 0 B
frontend/dist/markdown 3.83 kB 0 B
frontend/dist/MarketingAnalyticsScene 40.2 kB 0 B
frontend/dist/MaterializedColumns 10.4 kB 0 B
frontend/dist/Max 888 B 0 B
frontend/dist/mdx 5.43 kB 0 B
frontend/dist/memlens.lib.bundle 27.9 kB 0 B
frontend/dist/mermaid.core 27.5 kB 0 B
frontend/dist/MermaidDiagram 2.15 kB +40 B (+1.89%)
frontend/dist/MessageTemplate 16.5 kB 0 B
frontend/dist/MetricsScene 1.04 kB 0 B
frontend/dist/mindmap-definition-QFDTVHPH 24.8 kB 0 B
frontend/dist/mips 2.62 kB 0 B
frontend/dist/ModelsScene 14.6 kB +35 B (+0.24%)
frontend/dist/MonacoDiffEditor 471 B 0 B
frontend/dist/monacoEditorWorker 288 kB 0 B
frontend/dist/monacoEditorWorker.js 288 kB 0 B
frontend/dist/monacoJsonWorker 419 kB 0 B
frontend/dist/monacoJsonWorker.js 419 kB 0 B
frontend/dist/monacoTsWorker 7.02 MB 0 B
frontend/dist/monacoTsWorker.js 7.02 MB 0 B
frontend/dist/MoveToPostHogCloud 4.7 kB 0 B
frontend/dist/msdax 4.95 kB 0 B
frontend/dist/mysql 11.3 kB 0 B
frontend/dist/NavTabChat 7.41 kB 0 B
frontend/dist/NewSourceScene 980 B 0 B
frontend/dist/NewTabScene 1.72 kB 0 B
frontend/dist/NodeDetailScene 16.9 kB +33 B (+0.2%)
frontend/dist/NotebookCanvasScene 3.51 kB 0 B
frontend/dist/NotebookPanel 5.48 kB 0 B
frontend/dist/NotebookScene 8.72 kB 0 B
frontend/dist/NotebooksScene 7.84 kB 0 B
frontend/dist/OAuthAuthorize 844 B 0 B
frontend/dist/objective-c 2.44 kB 0 B
frontend/dist/Onboarding 771 kB 0 B
frontend/dist/OnboardingCouponRedemption 1.44 kB 0 B
frontend/dist/packet-4T2RLAQJ 456 B 0 B
frontend/dist/pascal 3.03 kB 0 B
frontend/dist/pascaligo 2.04 kB 0 B
frontend/dist/passkeyLogic 688 B 0 B
frontend/dist/PasswordReset 4.6 kB 0 B
frontend/dist/PasswordResetComplete 3.23 kB 0 B
frontend/dist/PendingDeletion 2.38 kB 0 B
frontend/dist/perl 8.29 kB 0 B
frontend/dist/PersonScene 18.1 kB 0 B
frontend/dist/PersonsScene 4.94 kB 0 B
frontend/dist/pgsql 13.5 kB 0 B
frontend/dist/php 8.06 kB 0 B
frontend/dist/pie-ZZUOXDRM 447 B 0 B
frontend/dist/pieDiagram-DEJITSTG 4.98 kB 0 B
frontend/dist/PipelineStatusScene 9.35 kB 0 B
frontend/dist/pla 1.72 kB 0 B
frontend/dist/posthog 146 kB 0 B
frontend/dist/postiats 7.9 kB 0 B
frontend/dist/powerquery 17 kB 0 B
frontend/dist/powershell 3.31 kB 0 B
frontend/dist/PreflightCheck 5.81 kB 0 B
frontend/dist/product-tours.js 115 kB 0 B
frontend/dist/ProductTour 274 kB 0 B
frontend/dist/ProductTours 4.92 kB 0 B
frontend/dist/ProjectHomepage 19.9 kB 0 B
frontend/dist/protobuf 9.09 kB 0 B
frontend/dist/pug 4.86 kB 0 B
frontend/dist/python 4.8 kB 0 B
frontend/dist/qsharp 3.23 kB 0 B
frontend/dist/quadrantDiagram-34T5L4WZ 34.2 kB 0 B
frontend/dist/QueryPerformance 8.86 kB 0 B
frontend/dist/r 3.16 kB 0 B
frontend/dist/radar-PYXPWWZC 453 B 0 B
frontend/dist/razor 9.38 kB 0 B
frontend/dist/react-json-view 121 kB 0 B
frontend/dist/recorder-v2.js 98.6 kB 0 B
frontend/dist/recorder.js 98.6 kB 0 B
frontend/dist/redis 3.59 kB 0 B
frontend/dist/redshift 11.8 kB 0 B
frontend/dist/RegionMap 29.7 kB +35 B (+0.12%)
frontend/dist/render-query 26.4 MB 0 B
frontend/dist/render-query.js 26.4 MB 0 B
frontend/dist/requirementDiagram-MS252O5E 31.9 kB 0 B
frontend/dist/ResourceTransfer 9.42 kB 0 B
frontend/dist/restructuredtext 3.94 kB 0 B
frontend/dist/RevenueAnalyticsScene 25.8 kB +65 B (+0.25%)
frontend/dist/ruby 8.54 kB 0 B
frontend/dist/rust 4.2 kB 0 B
frontend/dist/sankeyDiagram-XADWPNL6 22.9 kB 0 B
frontend/dist/SavedInsights 902 B 0 B
frontend/dist/sb 1.86 kB 0 B
frontend/dist/scala 7.36 kB 0 B
frontend/dist/schema 704 kB 0 B
frontend/dist/SchemaScene 21.2 kB 0 B
frontend/dist/scheme 1.8 kB 0 B
frontend/dist/scss 6.45 kB 0 B
frontend/dist/SdkDoctorScene 9.66 kB 0 B
frontend/dist/sequenceDiagram-FGHM5R23 117 kB 0 B
frontend/dist/SessionAttributionExplorerScene 6.87 kB 0 B
frontend/dist/SessionGroupSummariesTable 4.84 kB 0 B
frontend/dist/SessionGroupSummaryScene 17.2 kB 0 B
frontend/dist/SessionProfileScene 15.3 kB 0 B
frontend/dist/SessionRecordingDetail 2 kB 0 B
frontend/dist/SessionRecordingFilePlaybackScene 4.71 kB 0 B
frontend/dist/SessionRecordings 980 B 0 B
frontend/dist/SessionRecordingsKiosk 9.09 kB 0 B
frontend/dist/SessionRecordingsPlaylistScene 4.39 kB 0 B
frontend/dist/SessionRecordingsSettingsScene 2.14 kB 0 B
frontend/dist/SessionsScene 4.22 kB 0 B
frontend/dist/SettingsScene 3.23 kB 0 B
frontend/dist/sharedChunkAnchors 236 kB 0 B
frontend/dist/sharedChunkAnchors.js 236 kB 0 B
frontend/dist/SharedMetric 5.14 kB 0 B
frontend/dist/SharedMetrics 787 B 0 B
frontend/dist/shell 3.11 kB 0 B
frontend/dist/SignupContainer 28.4 kB 0 B
frontend/dist/Site 1.43 kB 0 B
frontend/dist/solidity 18.6 kB 0 B
frontend/dist/sophia 2.8 kB 0 B
frontend/dist/SourceScene 962 B +34 B (+3.66%)
frontend/dist/SourcesScene 6.17 kB 0 B
frontend/dist/sparql 2.59 kB 0 B
frontend/dist/sql 10.3 kB 0 B
frontend/dist/SqlVariableEditScene 7.49 kB 0 B
frontend/dist/st 7.44 kB 0 B
frontend/dist/StartupProgram 21.4 kB 0 B
frontend/dist/stateDiagram-FHFEXIEX 11.4 kB +5 B (+0.04%)
frontend/dist/stateDiagram-v2-QKLJ7IA2 1.22 kB 0 B
frontend/dist/StripeConfirmInstall 3.78 kB 0 B
frontend/dist/SubscriptionScene 14.4 kB 0 B
frontend/dist/SubscriptionsScene 5.42 kB 0 B
frontend/dist/SupportSettingsScene 1.68 kB +35 B (+2.13%)
frontend/dist/SupportTicketScene 45.7 kB 0 B
frontend/dist/SupportTicketsScene 937 B 0 B
frontend/dist/Survey 1.09 kB 0 B
frontend/dist/SurveyFormBuilder 1.78 kB 0 B
frontend/dist/Surveys 18.5 kB 0 B
frontend/dist/surveys.js 94.7 kB 0 B
frontend/dist/SurveyWizard 74.6 kB 0 B
frontend/dist/swift 5.3 kB 0 B
frontend/dist/SystemStatus 17.1 kB 0 B
frontend/dist/systemverilog 7.65 kB 0 B
frontend/dist/TaskDetailScene 22.6 kB +38 B (+0.17%)
frontend/dist/TaskTracker 14.5 kB +38 B (+0.26%)
frontend/dist/tcl 3.61 kB 0 B
frontend/dist/TextCardMarkdownEditor 11.2 kB +28 B (+0.25%)
frontend/dist/timeline-definition-GMOUNBTQ 31.4 kB 0 B
frontend/dist/toolbar 14.7 MB 0 B
frontend/dist/toolbar.js 14.7 MB 0 B
frontend/dist/ToolbarLaunch 2.71 kB 0 B
frontend/dist/tracing-headers.js 1.74 kB 0 B
frontend/dist/TracingScene 31.6 kB 0 B
frontend/dist/treemap-W4RFUUIX 459 B 0 B
frontend/dist/treeView-SZITEDCU 462 B 0 B
frontend/dist/TrendsBarChart 6.78 kB +37 B (+0.55%)
frontend/dist/TrendsLineChart 6.8 kB 0 B
frontend/dist/tsMode 24 kB 0 B
frontend/dist/twig 6.01 kB 0 B
frontend/dist/TwoFactorReset 4.27 kB 0 B
frontend/dist/typescript 274 B 0 B
frontend/dist/typespec 2.86 kB 0 B
frontend/dist/Unsubscribe 1.9 kB 0 B
frontend/dist/UserInterview 4.78 kB +39 B (+0.82%)
frontend/dist/UserInterviews 2.26 kB +35 B (+1.57%)
frontend/dist/vb 5.83 kB 0 B
frontend/dist/vennDiagram-DHZGUBPP 41.7 kB 0 B
frontend/dist/VercelConnect 5.23 kB 0 B
frontend/dist/VercelLinkError 2.5 kB 0 B
frontend/dist/VerifyEmail 5.02 kB 0 B
frontend/dist/vimMode 211 kB 0 B
frontend/dist/VisualReviewIndexScene 2.45 kB +36 B (+1.49%)
frontend/dist/VisualReviewRunScene 44.3 kB 0 B
frontend/dist/VisualReviewRunsScene 7.17 kB 0 B
frontend/dist/VisualReviewSettingsScene 11 kB 0 B
frontend/dist/VisualReviewSnapshotHistoryScene 12.4 kB +37 B (+0.3%)
frontend/dist/VisualReviewSnapshotOverviewScene 17.5 kB 0 B
frontend/dist/wardley-RL74JXVD 449 B 0 B
frontend/dist/wardleyDiagram-NUSXRM2D 24.9 kB 0 B
frontend/dist/web-vitals-with-attribution.js 11.8 kB 0 B
frontend/dist/web-vitals.js 6.39 kB 0 B
frontend/dist/WebAnalyticsScene 6 kB 0 B
frontend/dist/WebGLRenderer-DYjOwNoG 60.4 kB 0 B
frontend/dist/WebGPURenderer-B_wkl_Ja 36.3 kB 0 B
frontend/dist/WebScriptsScene 2.78 kB 0 B
frontend/dist/webworkerAll-puPV1rBA 397 B 0 B
frontend/dist/wgsl 7.38 kB 0 B
frontend/dist/Wizard 4.7 kB 0 B
frontend/dist/WorkflowsScene 60.1 kB +91 B (+0.15%)
frontend/dist/WorldMap 1.04 MB 0 B
frontend/dist/xml 3.02 kB 0 B
frontend/dist/xychartDiagram-5P7HB3ND 39.6 kB 0 B
frontend/dist/yaml 4.64 kB 0 B

compressed-size-action

Copy link
Copy Markdown
Member

@andrewm4894 andrewm4894 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this!

Twixes and others added 8 commits May 10, 2026 16:01
Extend POST /signals/reports/:id/state/ to optionally accept
`dismissal_reason` and `dismissal_note` when transitioning a report to
the suppressed state. When provided, persist a new `dismissal`-type
SignalReportArtefact alongside the status change so the rationale
survives status changes and multiple dismissals can stack over time.

Reasons surfaced by the PostHog Code UI: already_fixed,
analysis_wrong, wontfix_intentional, wontfix_irrelevant,
wrong_reviewer, other. The note field is bounded at 4000 characters.

Generated-By: PostHog Code
Task-Id: d3d675ab-707a-4a35-939b-9a9ab0f5c5b5
- Collapse test filter expressions onto single lines so ruff format no
  longer wants to reformat them.
- The "dismissal_reason rejected when not suppressing" test was creating
  a SUPPRESSED report, which is filtered out of the default queryset
  before validation runs and so returned 404 rather than 400. Use a
  READY report and target state=potential to exercise the validation
  path the test was meant to cover.

Generated-By: PostHog Code
Task-Id: d3d675ab-707a-4a35-939b-9a9ab0f5c5b5
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 10, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
products/signals/backend/views.py:869-889
**Non-atomic status change and artefact creation**

`report.save()` commits the state transition immediately. If `SignalReportArtefact.objects.create()` then fails (e.g., a DB error or an unhandled exception), the report status is persisted as `suppressed`/`potential` while the dismissal artefact is silently lost. Wrapping both writes in `transaction.atomic()` (and adding `from django.db import transaction` to the imports) keeps them as a single commit-or-rollback unit.

Reviews (2): Last reviewed commit: "fix(signals): expect null dismissal note" | Re-trigger Greptile

Comment thread products/signals/backend/views.py Outdated
@Twixes Twixes force-pushed the posthog-code/dismissal-artefact-on-suppress branch from 74e28ad to d61dd13 Compare May 10, 2026 15:08
Copy link
Copy Markdown
Member Author

Twixes commented May 10, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 10, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
products/signals/backend/views.py:874
The `target in ("suppressed", "potential")` check is always `True` at this point — the earlier guard at line 823 already rejects any other value with a 400. The redundant check makes it look like `target` might hold an unexpected value here, which is misleading and violates the "no superfluous parts" simplicity rule.

```suggestion
        if dismissal_reason or dismissal_note:
```

Reviews (3): Last reviewed commit: "ruff" | Re-trigger Greptile

status=status.HTTP_403_FORBIDDEN,
)

"""Re-ingest a report's signals (same team access as other report actions)."""
report = cast(SignalReport, self.get_object())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Reingestion authorization bypass

Any authenticated project member, or a personal API key with task:write, can now POST to this endpoint and start a reingestion workflow for a team report. That workflow soft-deletes the report's existing signals and re-emits them, so this should stay behind a privileged server-side check rather than relying on normal report write access.

@veria-ai
Copy link
Copy Markdown

veria-ai Bot commented May 10, 2026

Dismissal feedback recorded as report artefacts

This PR adds a dismissal artefact type and records optional dismissal feedback during report state transitions. I checked the state endpoint, artefact serialization, team scoping, and the current reingest authorization lines referenced by prior review comments; I did not find any new security issues in the dismissal artefact handling.


Status: 2 open
Risk: 2/10


@extend_schema(exclude=True)
@action(detail=True, methods=["post"], url_path="reingest", required_scopes=["task:write"])
def reingest(self, request, pk=None, **kwargs):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Reingestion authorization bypass

Removing the request.user.is_staff guard lets any project user with task:write start SignalReportReingestionWorkflow, which soft-deletes the report's signals and re-emits them through grouping. Keep this server-side staff/admin check, or replace it with an explicit maintenance/admin permission before exposing the frontend action.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 10, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
products/signals/backend/views.py:875
Redundant guard — `target` can only be `"suppressed"` or `"potential"` at this point, because any other value was already rejected at line 823. The `target in (...)` predicate is always `True` here and adds a superfluous branch (simplicity rule 4).

```suggestion
            if dismissal_reason or dismissal_note:
```

### Issue 2 of 2
products/signals/backend/test/test_signal_report_api.py:639-655
**Untested type-validation paths** — the view explicitly rejects non-string `dismissal_reason` and non-string `dismissal_note` with a `400`, but neither branch has a test case. Given the team's preference for parameterised tests, these cases fit naturally into the existing `test_state_transition_rejects_invalid_dismissal` parametrize block alongside `oversized_dismissal_note`: e.g. `{"state": "suppressed", "dismissal_reason": 123}` and `{"state": "suppressed", "dismissal_note": 456}`.

Reviews (4): Last reviewed commit: "Add atomic()" | Re-trigger Greptile

@Twixes Twixes merged commit 582b79d into master May 10, 2026
251 of 253 checks passed
Copy link
Copy Markdown
Member Author

Twixes commented May 10, 2026

Merge activity

@Twixes Twixes deleted the posthog-code/dismissal-artefact-on-suppress branch May 10, 2026 15:48
@deployment-status-posthog
Copy link
Copy Markdown

deployment-status-posthog Bot commented May 10, 2026

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-05-10 16:06 UTC Run
prod-us ✅ Deployed 2026-05-10 16:17 UTC Run
prod-eu ✅ Deployed 2026-05-10 16:21 UTC Run

fasyy612 pushed a commit that referenced this pull request May 13, 2026
## Problem

PostHog Code will surface a "Dismiss" dialog on the inbox where a reviewer can mark a report as not worth acting on, as of PostHog/code#2053. We need to record "why" alongside the status change so we can:

- distinguish "already fixed" from "wontfix"
- stack multiple dismissals over time when a report is unsnoozed and later re-dismissed for a different reason

The existing `state` action only flips a status flag and offers no place to attach this metadata.

## Changes

Adding a new `dismissal` value on `SignalReportArtefact.ArtefactType`.

`POST /api/projects/:team_id/signals/reports/:id/state/` now accepts two optional body fields:
  - `dismissal_reason`- Arbitrary string code. The set of valid codes is owned by PostHog Code, so we can iterate there without a backend change.
  - `dismissal_note` - Free-form text, capped at 4000 characters.

When either is provided and the target state is `suppressed` **or** `potential`, the action creates a `dismissal` artefact alongside the status change capturing reason, note, and the dismissing user's ID.

Important note: Reingestion is now available to all users. We need it e.g. to let people re-run failed research, which we've gotten reports about in Discord.

### Why an artefact rather than a column on the report

The existing `SUPPRESSED` status is a single flag. We need history (the same report can be dismissed multiple times for different reasons over its lifetime), and a typed artefact matches the existing pattern for everything else attached to a report.

## How did you test this code?

`TestSignalReportSuppressionAPI`

## Publish to changelog?

no
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