fix(flags): say why a save stops on an incomplete release condition - #102441
trunk-io[bot] merged 3 commits into
Conversation
|
😎 Merged successfully - details. |
|
Important Review skippedWe couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: QUIET Plan: Enterprise Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan provides up to 12 included reviews per hour; 0 remain after this review. 📝 WalkthroughWalkthroughFeature-flag release-condition validation now reports Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to Invalid collapsed condition sets are correctly identified and opened when saving is blocked, with no merge-blocking issue found. 🚥 Pre-merge checks | ❌ 1❌ Failed checks (1 warning)
Full details: Description checkExplanation The description clearly explains the problem, user-visible changes, testing, agent context, and documentation status. It does not include the required Release status section with exactly one option selected. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
🤖 CI report✅ Trunk lane — non-backend laneThis PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
ConditionContent |
frontend/src/scenes/feature-flags/FeatureFlagReleaseConditionsCollapsible.tsx:422 |
32 | 10 |
FeatureFlagReleaseConditionsCollapsible |
frontend/src/scenes/feature-flags/FeatureFlagReleaseConditionsCollapsible.tsx:872 |
25 | 10 |
loadFeatureFlag |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:3020 |
22 | 10 |
<anonymous> |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:5170 |
22 | 10 |
<anonymous> |
frontend/src/scenes/feature-flags/FeatureFlagReleaseConditionsCollapsible.tsx:140 |
17 | 10 |
saveFeatureFlagSuccess |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:3920 |
15 | 10 |
copyNewFlagToAdditionalProjects |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:566 |
14 | 10 |
saveFeatureFlag |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:3162 |
13 | 10 |
loadCopyDependencyRequirements |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:3648 |
11 | 10 |
createPairedSchedule |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:3765 |
11 | 10 |
refreshFeatureFlagSuccess |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:4055 |
11 | 10 |
loadFeatureFlagSuccess |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:4200 |
11 | 10 |
saveTagsInline |
frontend/src/scenes/feature-flags/featureFlagLogic.ts:4505 |
11 | 10 |
<anonymous> |
frontend/src/scenes/feature-flags/featureFlagReleaseConditionsLogic.ts:1150 |
11 | 10 |
✅ Duplication (Python) — clean
New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.
✅ Duplication (TypeScript) — clean
New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.
⚠️ Comment density — 5% of added code lines are comments (8 of 158)
This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.
Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.
Files with the most added comment lines:
| File | Comment lines | Added lines |
|---|---|---|
frontend/src/scenes/feature-flags/FeatureFlagReleaseConditions.incompleteFilterOnSave.test.tsx |
3 | 123 |
frontend/src/scenes/feature-flags/featureFlagLogic.ts |
3 | 22 |
frontend/src/scenes/feature-flags/propertySelectErrorMessages.tsx |
2 | 11 |
This check does not block merging. It updates on every push and clears when the share drops.
✅ Bundle size — 🟢 -246 B (-0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 69.76 MiB · 🟢 -246 B (-0.0%)
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.63 MiB · 22 files | no change | █████████░ 88.7% 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.72 MiB · 660 files | no change | █████████░ 92.3% of 4.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.59 MiB · 2,407 files | no change | █████████░ 91.0% of 8.34 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.66 MiB · 3,389 files | no change | ███████░░░ 71.7% of 13.48 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.60 MiB · 2,415 files | no change | █████████░ 88.5% of 8.58 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.28 MiB · 3,241 files | no change | ███████░░░ 73.5% of 12.64 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
12.12 MiB · 4,129 files | 🔺 +298 B (+0.0%) | ████████░░ 77.1% of 15.72 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
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.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 |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 220.3 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 |
| 100.5 KiB | src/lib/api.ts |
| 92.5 KiB | src/products.tsx |
| 69.4 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 40.1 KiB | src/lib/utils/eventUsageLogic.ts |
| 38.7 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 |
| 29.0 KiB | ../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/schemas.js |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 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 |
| 153.7 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 |
| 110.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.5 KiB | src/products.tsx |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 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 |
| 181.8 KiB | src/queries/validators.js |
| 153.7 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 |
| 110.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.5 KiB | src/products.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 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 |
| 153.7 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 |
| 110.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.5 KiB | src/products.tsx |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 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 |
| 181.8 KiB | src/queries/validators.js |
| 153.7 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 |
| 110.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.5 KiB | src/products.tsx |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 315.5 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 306.2 KiB | ../node_modules/.pnpm/posthog-js@1.435.5_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 279.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.3 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 |
| 181.8 KiB | src/queries/validators.js |
| 153.7 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 |
| 110.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 100.5 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
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.20 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.20 MiB · 19 files | no change | ████░░░░░░ 38.4% of 5.72 MiB |
| Deferred (lazy) | 2.11 MiB · 44 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.2 KiB | no change | █░░░░░░░░░ 6.0% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 834.2 KiB | dist/toolbar/toolbar-app-LXAUZCP3.css |
| 657.4 KiB | dist/toolbar/chunk-chunk-PDXEE7YG.js |
| 259.4 KiB | dist/toolbar/chunk-chunk-EXS5VGKQ.js |
| 138.2 KiB | dist/toolbar/chunk-chunk-YTISI4G3.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 75.2 KiB | dist/toolbar/toolbar-app-6G7F6XL7.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-U65TWWSR.js |
| 21.0 KiB | dist/toolbar/chunk-chunk-JYRTCG7P.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 — 🔺 +12.2 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 959.84 MiB · 🔺 +12.2 KiB (+0.0%)
✅ Playwright — all passed
All tests passed.
|
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 |
A release condition that holds a property row with no value blocks the submit, and the inline error lives inside a condition set panel that is collapsed whenever the flag has more than one set. A collapsed panel renders no children, so nothing reaches the screen and scrollToFormError has no target. A blocked save now opens every condition set that holds an error, names the set in the fallback toast, and the empty-value message says what to do about it. Generated-By: PostHog Desktop Task-Id: cee67a36-ae79-4c6d-97c4-75eaf3597f83
89eb9b4 to
7ede16f
Compare
New commits were pushed — dismissing the stamphog approval from an earlier head. This PR no longer qualifies for automatic review.
The collapsible release condition editor did not pass sendAllKeyUpdates to PropertyFilters. The filter logic then kept a row with no value out of the form. A new filter with no value disappeared on save. A removed value stayed in the form, so the old value saved. With the prop, the row reaches the form. The form stops the save and shows "Add a value or remove this filter" next to the row. Generated-By: PostHog Desktop Task-Id: f2fcf76f-8e09-46fc-859d-a524b1db4576
|
Tested it locally after pushing some fies ph.mp4 |
…when-an-incomplete-3c0b81
|
Risk: No findings The changes since the last review rework the agent-change notice handling in the feature-flag logic: an agent-path refresh failure now surfaces a retry toast with a per-attempt id, and successful loads/saves dismiss both notices. All of it is local UI state and static toast copy on an already-authenticated, own-project read endpoint; no security-relevant boundary is touched. Sentinel reviewed |
|
stamphog does not review bot-authored pull requests, so the trigger label has been removed. This change needs a human reviewer. |

Problem
scrollToFormErrorfinds no.Field--errorand falls back to a message that names nothing.Origin
963c271Changes
sendAllKeyUpdatesprop for this. The older condition set editor already passes it.openConditionSetsreuses the existingopenConditionaction andsort_key, so no new state and no new markup.Note
Nothing is drawn that was not there before: the panel and the error element already exist. Screenshots are not attached. The browser check below ran on a local dev stack with test data.
While a row has no value, the user count under the rollout slider shows its loading placeholder until the row is complete. This behavior is not new: the count code skips rows with no value.
How did you test this code?
frontend/src/scenes/feature-flags/FeatureFlagReleaseConditions.incompleteFilterOnSave.test.tsx. It renders two condition sets, both collapsed, one holding a value-less filter, then submits the flag.openConditionSetscall fails it on the message assertion.sendAllKeyUpdatesfails it on the message assertion.masterAutomatic notifications
Docs update
None. No documented workflow, API, or setting changes.
🤖 Agent context
Autonomy: Fully autonomous
Agent: PostHog Desktop (Claude Code), Claude Opus 5
/writing-user-facing-copy,/writing-tests,/writing-pr-descriptions,/simplify, plus thefrontend/srcagent guide./simplifypass ran by hand over the diff and replaced a hand-rolled open-and-dedup block with the existingopenConditionaction.gh pr list --state open --searchover the flag editor found fix(flags): keep release condition edits when a chunk fails to load #100464 (chunk-load failures) and fix(flags): stop the flag overview misreporting saved targeting #101315 (overview reporting), neither of which touches the blocked-save path.email,plan,enterprise). Nothing from the agent session reached the code, the comments, or this description.claude-opus-5-5), at a person's request: the browser check above found that the editor never sent rows with no value to the form. That session added thesendAllKeyUpdatescommit and its test, and rebased the branch ontomasterto clear a conflict infeatureFlagLogic.ts. Skills invoked:/writing-tests,/writing-pr-descriptions.Created with PostHog Desktop from this inbox report.