Skip to content

Stop POSSIBLY_NSFW_ACCOUNT from requiring 11 matches in a window of 10 - #49

Closed
Pitchfork-and-Torch wants to merge 19 commits into
mainfrom
cursor/nsfw-user-agg-window-8d30
Closed

Stop POSSIBLY_NSFW_ACCOUNT from requiring 11 matches in a window of 10#49
Pitchfork-and-Torch wants to merge 19 commits into
mainfrom
cursor/nsfw-user-agg-window-8d30

Conversation

@Pitchfork-and-Torch

Copy link
Copy Markdown
Owner

Bug

safety-label-user-agg is the only writer of POSSIBLY_NSFW_ACCOUNT. That label is how soft-NSFW posting becomes an account signal (nsfw_author_ads in gizmoduck hydration → ads brand safety).

The production default rule is unsatisfiable:

"windowSize": 10,
"minimumMatchingPosts": 11

matchesPostLabelCount does posts.take(windowSize).filter(match).size >= minimumMatchingPosts. A window of 10 can never contain 11 matches. enabled: true does not matter. The soft-NSFW account path never writes.

NSFW_HIGH_PRECISION (3 of last 5) still works. Accounts that post SOFT_NSFW without hitting 3/5 high-precision posts get no account label.

Validation allows this: maxConfiguredWindowSize = 10 and maxConfiguredMinimumMatchingPosts = 11, with no minimum <= window check.

Proof

take(10).size >= 11 is false for every timeline.

Last 10 posts Before After
10× NSFW_HIGH_PRECISION / SOFT_NSFW no label POSSIBLY_NSFW_ACCOUNT
9× NSFW + 1 clean no label no label
3/5 NSFW_HIGH_PRECISION NSFW_HIGH_PRECISION NSFW_HIGH_PRECISION (unchanged)

Stale feature-switch copies of the old 11/10 JSON still fire: required count is clamped to the window. Rejecting 11/10 in validRules would have dropped both default rules (all-or-nothing), including the working 3/5 path.

evaluateForTest on 10 labeled posts with the old default returns []. After clamp / 10-of-10 it returns POSSIBLY_NSFW_ACCOUNT.

Fix

  1. Default minimumMatchingPosts is 10 (all of the last 10).
  2. requiredMatchingPosts clamps minimumMatchingPosts to windowSize so a leftover 11/10 FS payload cannot keep the rule dead.

One file: safety-label-user-agg/postToUserLabelRules.strato.

Not a home-mixer / VF leftover. Not xai-org#165 (user-cred linked edges). Not a fork PR.

Fork PR: none

Open in Web Open in Cursor 

CI agent and others added 19 commits August 14, 2026 20:55
in_network_ids is passed to the VF client without deduplication, while
oon_ids is deduped four lines below. retweeted_tweet_id is pushed for
every candidate that has one, so the same ID repeats once per retweet of
a given post — most often when that post is going viral.

Neither VfClient implementation dedupes its input: StratoVfClient builds
one call per element, and XaiVfClient chunks by XAI_VF_MAX_BATCH_SIZE, so
duplicates consume batch slots and can force an extra round trip.

Not a correctness issue — results collapse into a HashMap keyed by tweet
ID — but redundant work on the For You serving path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deduplicate in_network_ids before VF lookup
The default post-to-user rule asked for more matching posts than the window can hold, so the account label never applied. Clamp the required count to the window and set the default to 10 of 10.

Co-authored-by: Jon Bailey <Pitchfork-and-Torch@users.noreply.github.com>
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.

4 participants