Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 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.
|
| First copy | Second copy | Lines | Tokens |
|---|---|---|---|
posthog/hogql_queries/ai/test/test_trace_query_runner.py:43 |
posthog/hogql_queries/ai/test/test_traces_query_runner.py:31 |
209 | 1017 |
products/review_hog/eval/experiments/2026-08-model-glm53-flash/scripts/glm_mts_smoke.py:7 |
products/review_hog/eval/experiments/2026-09-model-kimi-k3/scripts/kimi_mts_smoke.py:12 |
107 | 517 |
products/review_hog/eval/experiments/2026-08-model-glm53-flash/scripts/glm_mts_smoke.py:7 |
products/review_hog/eval/experiments/2026-08-validator-model-sol/scripts/codex_mts_smoke.py:7 |
83 | 372 |
products/data_warehouse/backend/tests/api/test_warehouse_table_file_upload.py:16 |
products/warehouse_sources/backend/tests/test_file_upload_sources.py:22 |
45 | 264 |
products/warehouse_sources/sources/impact/impact.py:94 |
products/warehouse_sources/sources/impact_partner/impact_partner.py:75 |
35 | 260 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:613 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:726 |
32 | 236 |
products/web_analytics/backend/hogql_queries/web_analytics_lazy_precompute.py:152 |
products/web_analytics/backend/hogql_queries/web_lazy_precompute_common.py:881 |
66 | 227 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:613 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:658 |
27 | 207 |
products/warehouse_sources/backend/tests/api/test_external_data_source.py:6572 |
products/warehouse_sources/backend/tests/api/test_external_data_source.py:6651 |
49 | 200 |
products/logs/backend/test/test_explain.py:270 |
products/logs/backend/test/test_explain.py:355 |
29 | 184 |
products/slack_app/backend/task_profiles.py:18 |
products/tasks/backend/task_profiles.py:35 |
37 | 173 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:71 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:794 |
22 | 167 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:381 |
products/warehouse_sources/backend/temporal/data_imports/pipelines/core/test/test_cdp_producer.py:613 |
20 | 161 |
products/logs/backend/test/test_explain.py:270 |
products/logs/backend/test/test_explain.py:310 |
22 | 151 |
products/warehouse_sources/sources/impact/impact.py:105 |
products/warehouse_sources/sources/impact_partner/impact_partner.py:86 |
27 | 149 |
posthog/clickhouse/metrics/metrics4.py:143 |
posthog/clickhouse/metrics/metrics4.py:242 |
14 | 132 |
posthog/hogql/type_system.py:2119 |
posthog/hogql/type_system.py:2138 |
14 | 99 |
ee/hogai/llm.py:665 |
ee/hogai/llm.py:843 |
16 | 96 |
products/warehouse_sources/backend/temporal/data_imports/sources/common/mixins.py:191 |
products/warehouse_sources/backend/temporal/data_imports/sources/common/mixins.py:281 |
11 | 93 |
products/engineering_analytics/backend/logic/queries/workflow_run_activity.py:74 |
products/engineering_analytics/backend/logic/queries/workflow_run_list.py:46 |
11 | 90 |
products/web_analytics/backend/hogql_queries/web_calendar_heatmap.py:193 |
products/web_analytics/backend/hogql_queries/web_trends_lazy_precompute.py:449 |
18 | 87 |
products/web_analytics/backend/hogql_queries/web_stats_frustration_lazy_precompute.py:131 |
products/web_analytics/backend/hogql_queries/web_stats_paths_lazy_precompute.py:176 |
13 | 87 |
products/context_layer/backend/task_profiles.py:16 |
products/review_hog/backend/task_profiles.py:28 |
17 | 85 |
products/warehouse_sources/sources/less_annoying_crm/less_annoying_crm.py:287 |
products/warehouse_sources/sources/shipstation/shipstation.py:299 |
13 | 83 |
products/experiments/backend/task_profiles.py:21 |
products/slack_app/backend/task_profiles.py:23 |
16 | 82 |
products/mcp_analytics/backend/hogql_queries/tool_tables.py:618 |
products/mcp_analytics/backend/hogql_queries/tool_tables.py:767 |
12 | 77 |
products/demo/backend/logic/legacy/app_data_generator.py:9 |
products/demo/backend/logic/legacy/revenue_data_generator.py:17 |
11 | 71 |
⚠️ Duplication (TypeScript) — 20 new duplicated blocks (worst 351 tokens)
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.
| First copy | Second copy | Lines | Tokens |
|---|---|---|---|
products/mcp_analytics/frontend/notifications/mcpAnalyticsNotificationsLogic.ts:171 |
products/product_analytics/frontend/notifications/productAnalyticsNotificationsLogic.ts:157 |
77 | 351 |
products/surveys/frontend/draftReview/surveyProvenanceLogic.ts:36 |
products/surveys/frontend/draftReview/surveyProvenanceLogic.ts:96 |
57 | 339 |
frontend/src/products.tsx:1857 |
products/product_analytics/manifest.tsx:44 |
38 | 312 |
frontend/src/scenes/insights/insightLogic.tsx:502 |
frontend/src/scenes/insights/insightLogic.tsx:553 |
45 | 309 |
frontend/src/scenes/insights/insightDataLogic.tsx:334 |
frontend/src/scenes/insights/insightDataLogic.tsx:392 |
49 | 281 |
frontend/src/scenes/insights/insightDataLogic.tsx:391 |
frontend/src/scenes/insights/insightLogic.tsx:342 |
45 | 263 |
products/logs/frontend/components/LogsSqlEditor/logsSqlEditorTrackingLogic.ts:17 |
products/tracing/frontend/components/TracingSqlEditor/tracingSqlEditorTrackingLogic.ts:17 |
49 | 209 |
products/logs/frontend/components/LogsSqlEditor/logsSqlEditorTrackingLogic.ts:17 |
products/metrics/frontend/components/metricsSqlEditorTrackingLogic.ts:18 |
45 | 206 |
products/ai_observability/frontend/playground/llmPlaygroundLogic.test.ts:321 |
products/ai_observability/frontend/playground/llmPlaygroundLogic.test.ts:442 |
41 | 187 |
products/ai_observability/frontend/playground/llmPlaygroundLogic.test.ts:272 |
products/ai_observability/frontend/playground/llmPlaygroundLogic.test.ts:324 |
39 | 169 |
products/ai_observability/frontend/modelPickerLogic.test.ts:268 |
products/ai_observability/frontend/modelPickerLogic.test.ts:499 |
34 | 158 |
common/storybook/.storybook/test-runner.ts:562 |
packages/quill/apps/storybook/.storybook/test-runner.ts:32 |
41 | 137 |
nodejs/src/logs/framework/resolve-log-buffer.ts:114 |
nodejs/src/logs/logs-ingestion-consumer.ts:627 |
23 | 133 |
frontend/src/scenes/surveys/surveyNotificationModalLogic.ts:1054 |
products/surveys/frontend/draftReview/surveyProvenanceLogic.ts:43 |
13 | 90 |
packages/quill/packages/charts/src/charts/TimeSeriesBarChart/TimeSeriesBarChart.tsx:134 |
packages/quill/packages/charts/src/charts/TimeSeriesComboChart/TimeSeriesComboChart.tsx:113 |
27 | 85 |
frontend/src/scenes/insights/insightLogic.tsx:320 |
frontend/src/scenes/insights/insightLogic.tsx:372 |
16 | 82 |
frontend/src/scenes/insights/insightDataLogic.tsx:361 |
frontend/src/scenes/insights/insightLogic.tsx:318 |
15 | 79 |
frontend/src/scenes/surveys/surveyNotificationModalLogic.ts:1083 |
products/surveys/frontend/draftReview/surveyProvenanceLogic.ts:72 |
19 | 74 |
services/mcp/src/lib/instructions.ts:208 |
services/mcp/tests/unit/instructions.test.ts:123 |
37 | 74 |
nodejs/src/servers/ingestion-logs-server.ts:195 |
nodejs/src/servers/ingestion-metrics-server.ts:127 |
11 | 72 |
⚠️ Comment density — 4% of added code lines are comments (10 of 239)
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 |
|---|---|---|
nodejs/src/cdp/services/managers/organization-members.service.ts |
6 | 64 |
nodejs/src/cdp/utils/deadline-transaction.ts |
4 | 46 |
This check does not block merging. It updates on every push and clears when the share drops.
There was a problem hiding this comment.
PostHog Review · Standard · reviewed d5da565: 1 Should fix.
This is the only automatic review while this pull request is a draft. Comment @posthog review to review new changes sooner. Otherwise, a review of the new changes runs when you mark it ready for review.
See this review and its findings in PostHog Review. Comment @posthog review --deep for a Deep review. A Deep review takes longer and looks deeper than a Standard review.
…on late A lookup that waits for a pooled connection past its deadline no longer runs its query once the connection arrives, so a slow pool does not replay abandoned lookups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The member lookup now takes its pooled connection itself. A connection that arrives after the deadline goes back to the pool before BEGIN, and a connection still busy at the deadline, in BEGIN or any later statement, is destroyed instead of held or reused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Risk: No findings This increment is a two-line fail-closed tightening: organization members with a NULL Sentinel reviewed |
A new stamphog review started for this PR — the fresh verdict replaces this approval.
A null is_email_verified marks an account from before email verification existed. The web app lets those accounts log in and change email as verified and never asks them to verify, so a strict check skipped every sandbox send to them with no way out. Only an explicit false now counts as unverified. Also drop rejection handlers that Promise.race already attaches, and test the deadline cases through the router's public connect, on a bare Postgres router instead of a full hub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ox-split/org-members
A new stamphog review started for this PR — the fresh verdict replaces this approval.
A member whose account predates email verification has a null is_email_verified and never proved the address. The sandbox sender mails from a PostHog-owned identity and was decided to reach verified members only, so null counts as unverified again, as in the OAuth email_verified claim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new stamphog review started for this PR — the fresh verdict replaces this approval.
There was a problem hiding this comment.
Approved.
The security-sensitive lookup has owning-team authorship and targeted tests, providing the policy's assurance path. No concrete unresolved review concern or showstopper was found; the discussion bot's account of null verification does not match the current code.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 122L, 2F substantive, 266L/3F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1c-medium (266L, 3F, single-area, feat) |
| stamphog 2.7.0 | .stamphog/policy.yml @ 9ddec86 · reviewed head 9ddec86 |
|
Note 🤖 Claude Opus 5.5 responding on behalf of Michael Replaced by #131731 in the isolated sandbox rebuild. |
Problem
Merge danger
Note
🔵 Merge risk: low · two-way door (merge-risk rubric)
git revertthe merge commit. Nothing to clean up.Changes
getBlockedRecipientsreturns every address that is not a verified member, and flags the unverified members among them.is_email_verifiedis true. A null value counts as unverified.BEGIN. A connection still busy at the deadline is destroyed.How did you test this code?
jscpdfor memory.organization-members.service.test.tsruns against the real test Postgres. It allows a padded or uppercase verified member, and flags unverified and null-verified members.BEGINgets its client destroyed.Earlier runs at older heads, not this head
Live run at older head (c36ef47). Nothing calls the lookup at this layer, so a script called it from the head build with a real
PostgresRouter, against the kit database and the team's real organization.is_activefalse, then NULLACCESS EXCLUSIVEon the membership tableEarlier live run through the send path, at d6b91d7
Run on a devbox at d6b91d7, the Node stack top with this PR's head 5195b18, merged with the product stack top 9379fbf. Same setup as #128946: private Django and Node
cdp-api, a seeded org, and a local server that records each SES request. One Node process ran throughout.ACCESS EXCLUSIVElock on the membership table, sendidle in transactionSELECTeachcdp-api, because Django's own auth reads the locked table.Test rationale: each case catches a lookup that lets a non-member through or hangs a send. No existing test covers member lookups in the worker.
Release status
Docs update
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5
Skills:
/writing-tests,/writing-code-comments,/stacking-prs,/writing-pr-descriptionsMore context for AI agents
organization-members.service.ts: no LazyLoader,freshoption, limiter ordeadline-slots.team_idcolumn stay, because #129049 batches teams.runTransactionBeforeDeadlineinnodejs/src/cdp/utils/deadline-transaction.ts, andlookupMembersinorganization-members.service.ts.Stack decisions, moved here from the visible body:
sandbox, created only by PostHog codeWORKFLOWS_SANDBOX_SENDER_ENABLED, no feature flag in CDP Node code🤖 Generated with Claude Code